Make variant's index part of the hash value
llvm-svn: 288554
This commit is contained in:
parent
75453b057b
commit
918f32fc7b
|
@ -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>
|
||||
struct _LIBCPP_TYPE_VIS_ONLY hash<_Tp*>
|
||||
: public unary_function<_Tp*, size_t>
|
||||
|
|
|
@ -1526,7 +1526,8 @@ struct _LIBCPP_TYPE_VIS_ONLY hash<variant<_Types...>> {
|
|||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
result_type operator()(const argument_type& __v) const {
|
||||
using __variant_detail::__visitation::__variant;
|
||||
return __v.valueless_by_exception()
|
||||
size_t __res =
|
||||
__v.valueless_by_exception()
|
||||
? __v.index()
|
||||
: __variant::__visit_alt(
|
||||
[](const auto& __alt) {
|
||||
|
@ -1535,6 +1536,7 @@ struct _LIBCPP_TYPE_VIS_ONLY hash<variant<_Types...>> {
|
|||
return hash<__value_type>{}(__alt.__value);
|
||||
},
|
||||
__v);
|
||||
return __hash_combine(__res, hash<size_t>{}(__v.index()));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#undef NDEBUG
|
||||
#include "experimental/filesystem"
|
||||
#include "string_view"
|
||||
#include "utility"
|
||||
|
@ -390,19 +391,13 @@ int path::__compare(string_view_t __s) const {
|
|||
// path.nonmembers
|
||||
size_t hash_value(const path& __p) noexcept {
|
||||
auto PP = PathParser::CreateBegin(__p.native());
|
||||
struct HashPairT {
|
||||
size_t first;
|
||||
size_t second;
|
||||
};
|
||||
HashPairT hp = {0, 0};
|
||||
size_t hash_value = 0;
|
||||
std::hash<string_view> hasher;
|
||||
std::__scalar_hash<decltype(hp)> pair_hasher;
|
||||
while (PP) {
|
||||
hp.second = hasher(*PP);
|
||||
hp.first = pair_hasher(hp);
|
||||
hash_value = __hash_combine(hash_value, hasher(*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() {
|
||||
test_hash_variant();
|
||||
test_hash_variant_duplicate_elements();
|
||||
test_hash_monostate();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue