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: