Make variant's index part of the hash value
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@288554 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -3345,6 +3345,17 @@ struct __scalar_hash<_Tp, 4>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
inline size_t __hash_combine(size_t __lhs, size_t __rhs) _NOEXCEPT {
|
||||||
|
struct _PairT {
|
||||||
|
size_t first;
|
||||||
|
size_t second;
|
||||||
|
};
|
||||||
|
typedef __scalar_hash<_PairT> _HashT;
|
||||||
|
const _PairT __p{__lhs, __rhs};
|
||||||
|
return _HashT()(__p);
|
||||||
|
}
|
||||||
|
|
||||||
template<class _Tp>
|
template<class _Tp>
|
||||||
struct _LIBCPP_TYPE_VIS_ONLY hash<_Tp*>
|
struct _LIBCPP_TYPE_VIS_ONLY hash<_Tp*>
|
||||||
: public unary_function<_Tp*, size_t>
|
: public unary_function<_Tp*, size_t>
|
||||||
|
|||||||
@@ -1526,7 +1526,8 @@ struct _LIBCPP_TYPE_VIS_ONLY hash<variant<_Types...>> {
|
|||||||
inline _LIBCPP_INLINE_VISIBILITY
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
result_type operator()(const argument_type& __v) const {
|
result_type operator()(const argument_type& __v) const {
|
||||||
using __variant_detail::__visitation::__variant;
|
using __variant_detail::__visitation::__variant;
|
||||||
return __v.valueless_by_exception()
|
size_t __res =
|
||||||
|
__v.valueless_by_exception()
|
||||||
? __v.index()
|
? __v.index()
|
||||||
: __variant::__visit_alt(
|
: __variant::__visit_alt(
|
||||||
[](const auto& __alt) {
|
[](const auto& __alt) {
|
||||||
@@ -1535,6 +1536,7 @@ struct _LIBCPP_TYPE_VIS_ONLY hash<variant<_Types...>> {
|
|||||||
return hash<__value_type>{}(__alt.__value);
|
return hash<__value_type>{}(__alt.__value);
|
||||||
},
|
},
|
||||||
__v);
|
__v);
|
||||||
|
return __hash_combine(__res, hash<size_t>{}(__v.index()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
// Source Licenses. See LICENSE.TXT for details.
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
#undef NDEBUG
|
||||||
#include "experimental/filesystem"
|
#include "experimental/filesystem"
|
||||||
#include "string_view"
|
#include "string_view"
|
||||||
#include "utility"
|
#include "utility"
|
||||||
@@ -390,19 +391,13 @@ int path::__compare(string_view_t __s) const {
|
|||||||
// path.nonmembers
|
// path.nonmembers
|
||||||
size_t hash_value(const path& __p) noexcept {
|
size_t hash_value(const path& __p) noexcept {
|
||||||
auto PP = PathParser::CreateBegin(__p.native());
|
auto PP = PathParser::CreateBegin(__p.native());
|
||||||
struct HashPairT {
|
size_t hash_value = 0;
|
||||||
size_t first;
|
|
||||||
size_t second;
|
|
||||||
};
|
|
||||||
HashPairT hp = {0, 0};
|
|
||||||
std::hash<string_view> hasher;
|
std::hash<string_view> hasher;
|
||||||
std::__scalar_hash<decltype(hp)> pair_hasher;
|
|
||||||
while (PP) {
|
while (PP) {
|
||||||
hp.second = hasher(*PP);
|
hash_value = __hash_combine(hash_value, hasher(*PP));
|
||||||
hp.first = pair_hasher(hp);
|
|
||||||
++PP;
|
++PP;
|
||||||
}
|
}
|
||||||
return hp.first;
|
return hash_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -105,7 +105,20 @@ void test_hash_monostate() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_hash_variant_duplicate_elements() {
|
||||||
|
// Test that the index of the alternative participates in the hash value.
|
||||||
|
using V = std::variant<std::monostate, std::monostate>;
|
||||||
|
using H = std::hash<V>;
|
||||||
|
H h{};
|
||||||
|
const V v1(std::in_place_index<0>);
|
||||||
|
const V v2(std::in_place_index<1>);
|
||||||
|
assert(h(v1) == h(v1));
|
||||||
|
assert(h(v2) == h(v2));
|
||||||
|
LIBCPP_ASSERT(h(v1) != h(v2));
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
test_hash_variant();
|
test_hash_variant();
|
||||||
|
test_hash_variant_duplicate_elements();
|
||||||
test_hash_monostate();
|
test_hash_monostate();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user