Author: ericwf Date: Fri Dec 2 17:38:31 2016 New Revision: 288554 URL: http://llvm.org/viewvc/llvm-project?rev=288554&view=rev Log: Make variant's index part of the hash value
Modified: libcxx/trunk/include/memory libcxx/trunk/include/variant libcxx/trunk/src/experimental/filesystem/path.cpp libcxx/trunk/test/std/utilities/variant/variant.hash/hash.pass.cpp Modified: libcxx/trunk/include/memory URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=288554&r1=288553&r2=288554&view=diff ============================================================================== --- libcxx/trunk/include/memory (original) +++ libcxx/trunk/include/memory Fri Dec 2 17:38:31 2016 @@ -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> Modified: libcxx/trunk/include/variant URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/variant?rev=288554&r1=288553&r2=288554&view=diff ============================================================================== --- libcxx/trunk/include/variant (original) +++ libcxx/trunk/include/variant Fri Dec 2 17:38:31 2016 @@ -1526,7 +1526,8 @@ struct _LIBCPP_TYPE_VIS_ONLY hash<varian 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<varian return hash<__value_type>{}(__alt.__value); }, __v); + return __hash_combine(__res, hash<size_t>{}(__v.index())); } }; Modified: libcxx/trunk/src/experimental/filesystem/path.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/experimental/filesystem/path.cpp?rev=288554&r1=288553&r2=288554&view=diff ============================================================================== --- libcxx/trunk/src/experimental/filesystem/path.cpp (original) +++ libcxx/trunk/src/experimental/filesystem/path.cpp Fri Dec 2 17:38:31 2016 @@ -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) c // 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; } //////////////////////////////////////////////////////////////////////////// Modified: libcxx/trunk/test/std/utilities/variant/variant.hash/hash.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/variant/variant.hash/hash.pass.cpp?rev=288554&r1=288553&r2=288554&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/variant/variant.hash/hash.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/variant/variant.hash/hash.pass.cpp Fri Dec 2 17:38:31 2016 @@ -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(); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits