From 3002a898a0a980017af146b89e7f843ef0d5d010 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 16 Dec 2007 18:20:25 +0000 Subject: [PATCH] If the containers have equality comparisons, they'll also need 'hash_value'. Untested and undocumented, as before. [SVN r42108] --- doc/ref.xml | 80 +++++++++++++++++++ .../unordered/detail/hash_table_impl.hpp | 35 ++++++++ include/boost/unordered_map.hpp | 12 ++- include/boost/unordered_set.hpp | 12 ++- test/container/compile_tests.hpp | 5 ++ test/objects/minimal.hpp | 4 + 6 files changed, 146 insertions(+), 2 deletions(-) diff --git a/doc/ref.xml b/doc/ref.xml index c0e4bc30..58e14a95 100644 --- a/doc/ref.xml +++ b/doc/ref.xml @@ -636,6 +636,25 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) This is a boost extension. + + + + unordered_set<Value, Hash, Pred, Alloc> const& + + std::size_t + + This is a boost extension. + + @@ -1293,6 +1312,25 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) This is a boost extension. + + + + unordered_multiset<Value, Hash, Pred, Alloc> const& + + std::size_t + + This is a boost extension. + + @@ -2005,6 +2043,27 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) This is a boost extension. + + + + unordered_map<Key, Mapped, Hash, Pred, Alloc> const& + + std::size_t + + This is a boost extension. + + @@ -2676,6 +2735,27 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) This is a boost extension. + + + + unordered_multimap<Key, Mapped, Hash, Pred, Alloc> const& + + std::size_t + + This is a boost extension. + + diff --git a/include/boost/unordered/detail/hash_table_impl.hpp b/include/boost/unordered/detail/hash_table_impl.hpp index 30e662a6..98aac7db 100644 --- a/include/boost/unordered/detail/hash_table_impl.hpp +++ b/include/boost/unordered/detail/hash_table_impl.hpp @@ -1926,6 +1926,41 @@ public: return true; } + inline bool group_hash(local_iterator_base it, type_wrapper*) const + { + std::size_t seed = group_count(it); + boost::hash_combine(seed, hash_function()(*it)); + return seed; + } + + inline bool group_hash(local_iterator_base it, void*) const + { + std::size_t seed = hash_function()(it->first); + + local_iterator_base end = it; + end.next_group(); + + do { + boost::hash_combine(seed, it->second); + } while(it != end); + + return seed; + } + + std::size_t hash_value() const + { + std::size_t seed = 0; + + for(bucket_ptr i = this->cached_begin_bucket_, + j = this->buckets_ + this->bucket_count_; i != j; ++i) + { + for(local_iterator_base it(i->next_); it.not_finished(); it.next_group()) + seed ^= group_hash(it, (type_wrapper*)0); + } + + return seed; + } + private: // strong exception safety, no side effects diff --git a/include/boost/unordered_map.hpp b/include/boost/unordered_map.hpp index 6fe05b69..7dd7b185 100644 --- a/include/boost/unordered_map.hpp +++ b/include/boost/unordered_map.hpp @@ -16,8 +16,8 @@ #include #include -#include #include +#include namespace boost { @@ -335,6 +335,11 @@ namespace boost { return !m1.base.equals(m2.base); } + + friend std::size_t hash_value(unordered_map const& m) + { + return m.base.hash_value(); + } }; // class template unordered_map template @@ -642,6 +647,11 @@ namespace boost { return !m1.base.equals(m2.base); } + + friend std::size_t hash_value(unordered_multimap const& m) + { + return m.base.hash_value(); + } }; // class template unordered_multimap template diff --git a/include/boost/unordered_set.hpp b/include/boost/unordered_set.hpp index 9f713587..f20aef0c 100644 --- a/include/boost/unordered_set.hpp +++ b/include/boost/unordered_set.hpp @@ -16,8 +16,8 @@ #include #include -#include #include +#include namespace boost { @@ -305,6 +305,11 @@ namespace boost { return !m1.base.equals(m2.base); } + + friend std::size_t hash_value(unordered_set const& m) + { + return m.base.hash_value(); + } }; // class template unordered_set template @@ -597,6 +602,11 @@ namespace boost { return !m1.base.equals(m2.base); } + + friend std::size_t hash_value(unordered_multiset const& m) + { + return m.base.hash_value(); + } }; // class template unordered_multiset template diff --git a/test/container/compile_tests.hpp b/test/container/compile_tests.hpp index 19455aba..c8a22ae7 100644 --- a/test/container/compile_tests.hpp +++ b/test/container/compile_tests.hpp @@ -129,4 +129,9 @@ void equality_test(X& r, T&) test::check_return_type::equals(a == b); test::check_return_type::equals(a != b); +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) + test::check_return_type::equals(boost::hash_value(a)); +#else + test::check_return_type::equals(hash_value(a)); +#endif } diff --git a/test/objects/minimal.hpp b/test/objects/minimal.hpp index a1450437..f8f84445 100644 --- a/test/objects/minimal.hpp +++ b/test/objects/minimal.hpp @@ -57,6 +57,10 @@ namespace minimal return false; } + std::size_t hash_value(copy_constructible_equality_comparable) { + return 1; + } + class default_copy_constructible { public: