diff --git a/doc/ref.xml b/doc/ref.xml
index 08b061ac..5cd4362e 100644
--- a/doc/ref.xml
+++ b/doc/ref.xml
@@ -657,6 +657,71 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unordered_set<Value, Hash, Pred, Alloc> const&
+
+
+ unordered_set<Value, Hash, Pred, Alloc> const&
+
+ bool
+
+ This is a boost extension.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unordered_set<Value, Hash, Pred, Alloc> const&
+
+
+ unordered_set<Value, Hash, Pred, Alloc> const&
+
+ bool
+
+ This is a boost extension.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unordered_set<Value, Hash, Pred, Alloc> const&
+
+ std::size_t
+
+ This is a boost extension.
+
+
+
@@ -1339,6 +1404,71 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unordered_multiset<Value, Hash, Pred, Alloc> const&
+
+
+ unordered_multiset<Value, Hash, Pred, Alloc> const&
+
+ bool
+
+ This is a boost extension.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unordered_multiset<Value, Hash, Pred, Alloc> const&
+
+
+ unordered_multiset<Value, Hash, Pred, Alloc> const&
+
+ bool
+
+ This is a boost extension.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unordered_multiset<Value, Hash, Pred, Alloc> const&
+
+ std::size_t
+
+ This is a boost extension.
+
+
+
@@ -2070,6 +2200,77 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unordered_map<Key, Mapped, Hash, Pred, Alloc> const&
+
+
+ unordered_map<Key, Mapped, Hash, Pred, Alloc> const&
+
+ bool
+
+ This is a boost extension.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unordered_map<Key, Mapped, Hash, Pred, Alloc> const&
+
+
+ unordered_map<Key, Mapped, Hash, Pred, Alloc> const&
+
+ bool
+
+ This is a boost extension.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unordered_map<Key, Mapped, Hash, Pred, Alloc> const&
+
+ std::size_t
+
+ This is a boost extension.
+
+
+
@@ -2762,6 +2963,77 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unordered_multimap<Key, Mapped, Hash, Pred, Alloc> const&
+
+
+ unordered_multimap<Key, Mapped, Hash, Pred, Alloc> const&
+
+ bool
+
+ This is a boost extension.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unordered_multimap<Key, Mapped, Hash, Pred, Alloc> const&
+
+
+ unordered_multimap<Key, Mapped, Hash, Pred, Alloc> const&
+
+ bool
+
+ 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 b07cf369..022d50ce 100644
--- a/include/boost/unordered/detail/hash_table_impl.hpp
+++ b/include/boost/unordered/detail/hash_table_impl.hpp
@@ -1128,11 +1128,13 @@ namespace boost {
private:
- typedef boost::unordered_detail::buffered_functions buffered_functions;
- typedef BOOST_DEDUCED_TYPENAME buffered_functions::functions functions;
- typedef BOOST_DEDUCED_TYPENAME buffered_functions::functions_ptr functions_ptr;
+ typedef boost::unordered_detail::buffered_functions
+ function_store;
+ typedef BOOST_DEDUCED_TYPENAME function_store::functions functions;
+ typedef BOOST_DEDUCED_TYPENAME function_store::functions_ptr
+ functions_ptr;
- buffered_functions functions_;
+ function_store functions_;
float mlf_;
size_type max_load_;
@@ -1376,10 +1378,17 @@ namespace boost {
// accessors
// no throw
+#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)
node_allocator get_allocator() const
{
return data_.allocators_.node_alloc_;
}
+#else
+ value_allocator get_allocator() const
+ {
+ return data_.allocators_.value_alloc_;
+ }
+#endif
// no throw
hasher const& hash_function() const
@@ -2136,6 +2145,98 @@ namespace boost {
}
}
+ //
+ // equals
+ //
+
+private:
+#if BOOST_UNORDERED_EQUIVALENT_KEYS
+ static inline bool group_equals(link_ptr it1, link_ptr it2,
+ type_wrapper*)
+ {
+ return data::group_count(it1) == data::group_count(it2);
+ }
+
+ static inline bool group_equals(link_ptr it1, link_ptr it2, void*)
+ {
+ link_ptr end1 = data::next_group(it1);
+ link_ptr end2 = data::next_group(it2);
+ do {
+ if(data::get_value(it1).second != data::get_value(it2).second) return false;
+ it1 = it1->next_;
+ it2 = it2->next_;
+ } while(it1 != end1 && it2 != end2);
+ return it1 == end1 && it2 == end2;
+ }
+#else
+ static inline bool group_equals(link_ptr it1, link_ptr it2,
+ type_wrapper*)
+ {
+ return true;
+ }
+
+ static inline bool group_equals(link_ptr it1, link_ptr it2, void*)
+ {
+ return data::get_value(it1).second == data::get_value(it2).second;
+ }
+#endif
+
+public:
+ bool equals(BOOST_UNORDERED_TABLE const& other) const
+ {
+ if(size() != other.size()) return false;
+
+ for(bucket_ptr i = data_.cached_begin_bucket_,
+ j = data_.buckets_end(); i != j; ++i)
+ {
+ for(link_ptr it(i->next_); BOOST_UNORDERED_BORLAND_BOOL(it); it = data::next_group(it))
+ {
+ link_ptr other_pos = other.find_iterator(other.extract_key(data::get_value(it)));
+ if(!BOOST_UNORDERED_BORLAND_BOOL(other_pos) ||
+ !group_equals(it, other_pos, (type_wrapper*)0))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ inline std::size_t group_hash(link_ptr it, type_wrapper*) const
+ {
+ std::size_t seed = data::group_count(it);
+ std::size_t hashed_key = hash_function()(data::get_value(it));
+ boost::hash_combine(seed, hashed_key);
+ return seed;
+ }
+
+ inline std::size_t group_hash(link_ptr it, void*) const
+ {
+ std::size_t seed = hash_function()(data::get_value(it).first);
+
+ link_ptr end = data::next_group(it);
+
+ do {
+ boost::hash_combine(seed, data::get_value(it).second);
+ it = it->next_;
+ } while(it != end);
+
+ return seed;
+ }
+
+ std::size_t hash_value() const
+ {
+ std::size_t seed = 0;
+
+ for(bucket_ptr i = data_.cached_begin_bucket_,
+ j = data_.buckets_end(); i != j; ++i)
+ {
+ for(link_ptr it(i->next_); BOOST_UNORDERED_BORLAND_BOOL(it); it = data::next_group(it))
+ 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 21765eaa..b233988c 100644
--- a/include/boost/unordered_map.hpp
+++ b/include/boost/unordered_map.hpp
@@ -18,8 +18,8 @@
#include
#include
-#include
#include
+#include
#if !defined(BOOST_HAS_RVALUE_REFS)
#include
@@ -387,6 +387,21 @@ namespace boost
{
base.rehash(n);
}
+
+ friend bool operator==(unordered_map const& m1, unordered_map const& m2)
+ {
+ return m1.base.equals(m2.base);
+ }
+
+ friend bool operator!=(unordered_map const& m1, unordered_map const& m2)
+ {
+ 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
@@ -739,6 +754,21 @@ namespace boost
{
base.rehash(n);
}
+
+ friend bool operator==(unordered_multimap const& m1, unordered_multimap const& m2)
+ {
+ return m1.base.equals(m2.base);
+ }
+
+ friend bool operator!=(unordered_multimap const& m1, unordered_multimap const& m2)
+ {
+ 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 bd4ceb1c..01954af9 100644
--- a/include/boost/unordered_set.hpp
+++ b/include/boost/unordered_set.hpp
@@ -18,8 +18,8 @@
#include
#include
-#include
#include
+#include
#if !defined(BOOST_HAS_RVALUE_REFS)
#include
@@ -358,6 +358,21 @@ namespace boost
{
base.rehash(n);
}
+
+ friend bool operator==(unordered_set const& m1, unordered_set const& m2)
+ {
+ return m1.base.equals(m2.base);
+ }
+
+ friend bool operator!=(unordered_set const& m1, unordered_set const& m2)
+ {
+ 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
@@ -695,6 +710,21 @@ namespace boost
{
base.rehash(n);
}
+
+ friend bool operator==(unordered_multiset const& m1, unordered_multiset const& m2)
+ {
+ return m1.base.equals(m2.base);
+ }
+
+ friend bool operator!=(unordered_multiset const& m1, unordered_multiset const& m2)
+ {
+ 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/helpers/equivalent.hpp b/test/helpers/equivalent.hpp
index c6e51815..ec605fc2 100644
--- a/test/helpers/equivalent.hpp
+++ b/test/helpers/equivalent.hpp
@@ -8,10 +8,10 @@
#include
#include
-#include
#include
#include "./metafunctions.hpp"
#include "./fwd.hpp"
+#include "./list.hpp"
namespace test
{
@@ -56,20 +56,17 @@ namespace test
BOOST_DEDUCED_TYPENAME Container::key_equal key_equal_;
float max_load_factor_;
- typedef BOOST_DEDUCED_TYPENAME non_const_value_type::type value_type;
- std::vector values_;
+ typedef test::list
+ value_list;
+ value_list values_;
public:
unordered_equivalence_tester(Container const &x)
: size_(x.size()),
hasher_(x.hash_function()), key_equal_(x.key_eq()),
max_load_factor_(x.max_load_factor()),
- values_()
+ values_(x.begin(), x.end())
{
- // Can't initialise values_ straight from x because of Visual C++ 6
- values_.reserve(x.size());
- std::copy(x.begin(), x.end(), std::back_inserter(values_));
-
- std::sort(values_.begin(), values_.end());
+ values_.sort();
}
bool operator()(Container const& x) const
@@ -80,11 +77,9 @@ namespace test
(max_load_factor_ == x.max_load_factor()) &&
(values_.size() == x.size()))) return false;
- std::vector copy;
- copy.reserve(x.size());
- std::copy(x.begin(), x.end(), std::back_inserter(copy));
- std::sort(copy.begin(), copy.end());
- return(std::equal(values_.begin(), values_.end(), copy.begin()));
+ value_list copy(x.begin(), x.end());
+ copy.sort();
+ return values_ == copy;
}
private:
unordered_equivalence_tester();
diff --git a/test/helpers/metafunctions.hpp b/test/helpers/metafunctions.hpp
index c0c56e71..a3b0eb04 100644
--- a/test/helpers/metafunctions.hpp
+++ b/test/helpers/metafunctions.hpp
@@ -75,35 +75,6 @@ namespace test
sizeof(has_unique_key_impl((Container const*)0))
== sizeof(no_type));
};
-
- // Non Const Value Type
-
- template
- struct non_const_value_type_impl
- {
- template
- struct apply {
- typedef std::pair<
- BOOST_DEDUCED_TYPENAME Container::key_type,
- BOOST_DEDUCED_TYPENAME Container::mapped_type> type;
- };
- };
-
- template<>
- struct non_const_value_type_impl
- {
- template
- struct apply {
- typedef BOOST_DEDUCED_TYPENAME Container::value_type type;
- };
- };
-
- template
- struct non_const_value_type
- : non_const_value_type_impl< ::test::is_map::value>::
- BOOST_NESTED_TEMPLATE apply
- {
- };
}
#endif
diff --git a/test/helpers/random_values.hpp b/test/helpers/random_values.hpp
index c811b4d5..07d83efd 100644
--- a/test/helpers/random_values.hpp
+++ b/test/helpers/random_values.hpp
@@ -6,7 +6,7 @@
#if !defined(BOOST_UNORDERED_TEST_HELPERS_RANDOM_VALUES_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_RANDOM_VALUES_HEADER
-#include
+#include "./list.hpp"
#include
#include
#include "./generators.hpp"
@@ -97,7 +97,7 @@ namespace test
template
struct random_values
- : public std::list
+ : public test::list
{
random_values(int count, test::random_generator const& generator =
test::default_generator)
diff --git a/test/helpers/strong.hpp b/test/helpers/strong.hpp
index 474882be..e71e8b5b 100644
--- a/test/helpers/strong.hpp
+++ b/test/helpers/strong.hpp
@@ -7,10 +7,10 @@
#define BOOST_UNORDERED_TEST_HELPERS_STRONG_HEADER
#include
-#include
#include
#include "./metafunctions.hpp"
#include "./equivalent.hpp"
+#include "./list.hpp"
#include "../objects/exception.hpp"
namespace test
@@ -18,19 +18,19 @@ namespace test
template
class strong
{
- typedef std::vector::type> values_type;
+ typedef test::list values_type;
values_type values_;
public:
void store(X const& x) {
DISABLE_EXCEPTIONS;
values_.clear();
- values_.reserve(x.size());
- std::copy(x.cbegin(), x.cend(), std::back_inserter(values_));
+ values_.insert(x.cbegin(), x.cend());
}
void test(X const& x) const {
if(!(x.size() == values_.size() &&
- std::equal(x.cbegin(), x.cend(), values_.begin(), test::equivalent)))
+ std::equal(x.cbegin(), x.cend(), values_.begin(),
+ test::equivalent)))
BOOST_ERROR("Strong exception safety failure.");
}
};
diff --git a/test/helpers/test.hpp b/test/helpers/test.hpp
index 532f56fb..f42f4ce3 100644
--- a/test/helpers/test.hpp
+++ b/test/helpers/test.hpp
@@ -61,7 +61,7 @@ namespace test {
for(registered_test_base* i = first(); i; i = i->next)
i->run();
}
- };
+ }
}
#endif
diff --git a/test/helpers/tracker.hpp b/test/helpers/tracker.hpp
index 8fd7d6fb..44deb4f1 100644
--- a/test/helpers/tracker.hpp
+++ b/test/helpers/tracker.hpp
@@ -11,7 +11,6 @@
#include
#include