[libcxx] r288554 - Make variant's index part of the hash value
Eric Fiselier via cfe-commits
cfe-commits at lists.llvm.org
Fri Dec 2 15:38:31 PST 2016
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();
}
More information about the cfe-commits
mailing list