diff --git a/doc/changes.qbk b/doc/changes.qbk
index adddc366..4bdcdaa3 100644
--- a/doc/changes.qbk
+++ b/doc/changes.qbk
@@ -111,6 +111,7 @@ First official release.
Add `erase_return_void` as a temporary workaround for the current
`erase` which can be inefficient because it has to find the next
element to return an iterator.
+* Add templated find overload for compatible keys.
* [@http://svn.boost.org/trac/boost/ticket/3773 Ticket 3773]:
Add missing `std` qualifier to `ptrdiff_t`.
diff --git a/doc/ref.xml b/doc/ref.xml
index a245397d..76d15a1a 100644
--- a/doc/ref.xml
+++ b/doc/ref.xml
@@ -576,6 +576,40 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
const_iterator
+
+
+
+
+
+
+
+ CompatibleKey const&
+
+
+ CompatibleHash const&
+
+
+ CompatiblePredicate const&
+
+ iterator
+
+
+
+
+
+
+
+
+ CompatibleKey const&
+
+
+ CompatibleHash const&
+
+
+ CompatiblePredicate const&
+
+ const_iterator
+
An iterator pointing to an element with key equivalent to k
, or b.end()
if no such element exists.
@@ -1399,6 +1433,40 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
const_iterator
+
+
+
+
+
+
+
+ CompatibleKey const&
+
+
+ CompatibleHash const&
+
+
+ CompatiblePredicate const&
+
+ iterator
+
+
+
+
+
+
+
+
+ CompatibleKey const&
+
+
+ CompatibleHash const&
+
+
+ CompatiblePredicate const&
+
+ const_iterator
+
An iterator pointing to an element with key equivalent to k
, or b.end()
if no such element exists.
@@ -2236,6 +2304,40 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
const_iterator
+
+
+
+
+
+
+
+ CompatibleKey const&
+
+
+ CompatibleHash const&
+
+
+ CompatiblePredicate const&
+
+ iterator
+
+
+
+
+
+
+
+
+ CompatibleKey const&
+
+
+ CompatibleHash const&
+
+
+ CompatiblePredicate const&
+
+ const_iterator
+
An iterator pointing to an element with key equivalent to k
, or b.end()
if no such element exists.
@@ -3108,6 +3210,40 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
const_iterator
+
+
+
+
+
+
+
+ CompatibleKey const&
+
+
+ CompatibleHash const&
+
+
+ CompatiblePredicate const&
+
+ iterator
+
+
+
+
+
+
+
+
+ CompatibleKey const&
+
+
+ CompatibleHash const&
+
+
+ CompatiblePredicate const&
+
+ const_iterator
+
An iterator pointing to an element with key equivalent to k
, or b.end()
if no such element exists.
diff --git a/include/boost/unordered/detail/fwd.hpp b/include/boost/unordered/detail/fwd.hpp
index 7128dbe9..ab028710 100644
--- a/include/boost/unordered/detail/fwd.hpp
+++ b/include/boost/unordered/detail/fwd.hpp
@@ -466,6 +466,9 @@ namespace boost { namespace unordered_detail {
return extractor::extract(node::get_value(n));
}
bool equal(key_type const& k, value_type const& v) const;
+ template
+ node_ptr find_iterator(bucket_ptr bucket, Key const& k,
+ Pred const&) const;
node_ptr find_iterator(bucket_ptr bucket, key_type const& k) const;
node_ptr find_iterator(key_type const& k) const;
node_ptr* find_for_erase(bucket_ptr bucket, key_type const& k) const;
@@ -523,6 +526,8 @@ namespace boost { namespace unordered_detail {
std::size_t count(key_type const& k) const;
iterator_base find(key_type const& k) const;
+ template
+ iterator_base find(Key const& k, Hash const& h, Pred const& eq) const;
value_type& at(key_type const& k) const;
iterator_pair equal_range(key_type const& k) const;
diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp
index ab95f595..198548d3 100644
--- a/include/boost/unordered/detail/table.hpp
+++ b/include/boost/unordered/detail/table.hpp
@@ -28,6 +28,23 @@ namespace boost { namespace unordered_detail {
return this->key_eq()(k, get_key(v));
}
+ // strong exception safety, no side effects
+ template
+ template
+ inline BOOST_DEDUCED_TYPENAME T::node_ptr
+ hash_table::find_iterator(bucket_ptr bucket, Key const& k,
+ Pred const& eq) const
+ {
+ node_ptr it = bucket->next_;
+ while (BOOST_UNORDERED_BORLAND_BOOL(it) &&
+ !eq(k, get_key(node::get_value(it))))
+ {
+ it = node::next_group(it);
+ }
+
+ return it;
+ }
+
// strong exception safety, no side effects
template
inline BOOST_DEDUCED_TYPENAME T::node_ptr
@@ -570,6 +587,22 @@ namespace boost { namespace unordered_detail {
return this->end();
}
+ template
+ template
+ BOOST_DEDUCED_TYPENAME T::iterator_base hash_table::find(Key const& k,
+ Hash const& h, Pred const& eq) const
+ {
+ if(!this->size_) return this->end();
+
+ bucket_ptr bucket = this->get_bucket(h(k) % this->bucket_count_);
+ node_ptr it = find_iterator(bucket, k, eq);
+
+ if (BOOST_UNORDERED_BORLAND_BOOL(it))
+ return iterator_base(bucket, it);
+ else
+ return this->end();
+ }
+
template
BOOST_DEDUCED_TYPENAME T::value_type&
hash_table::at(key_type const& k) const
diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp
index 712f769c..58ca3014 100644
--- a/include/boost/unordered/unordered_map.hpp
+++ b/include/boost/unordered/unordered_map.hpp
@@ -422,6 +422,26 @@ namespace boost
return const_iterator(table_.find(k));
}
+ template
+ iterator find(
+ CompatibleKey const& k,
+ CompatibleHash const& hash,
+ CompatiblePredicate const& eq)
+ {
+ return iterator(table_.find(k, hash, eq));
+ }
+
+ template
+ const_iterator find(
+ CompatibleKey const& k,
+ CompatibleHash const& hash,
+ CompatiblePredicate const& eq) const
+ {
+ return iterator(table_.find(k, hash, eq));
+ }
+
size_type count(const key_type& k) const
{
return table_.count(k);
@@ -925,6 +945,26 @@ namespace boost
return const_iterator(table_.find(k));
}
+ template
+ iterator find(
+ CompatibleKey const& k,
+ CompatibleHash const& hash,
+ CompatiblePredicate const& eq)
+ {
+ return iterator(table_.find(k, hash, eq));
+ }
+
+ template
+ const_iterator find(
+ CompatibleKey const& k,
+ CompatibleHash const& hash,
+ CompatiblePredicate const& eq) const
+ {
+ return iterator(table_.find(k, hash, eq));
+ }
+
size_type count(const key_type& k) const
{
return table_.count(k);
diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp
index 6982cf93..87c1011b 100644
--- a/include/boost/unordered/unordered_set.hpp
+++ b/include/boost/unordered/unordered_set.hpp
@@ -395,6 +395,15 @@ namespace boost
return const_iterator(table_.find(k));
}
+ template
+ const_iterator find(
+ CompatibleKey const& k,
+ CompatibleHash const& hash,
+ CompatiblePredicate const& eq) const
+ {
+ return iterator(table_.find(k, hash, eq));
+ }
size_type count(const key_type& k) const
{
return table_.count(k);
@@ -874,6 +883,16 @@ namespace boost
return const_iterator(table_.find(k));
}
+ template
+ const_iterator find(
+ CompatibleKey const& k,
+ CompatibleHash const& hash,
+ CompatiblePredicate const& eq) const
+ {
+ return iterator(table_.find(k, hash, eq));
+ }
+
size_type count(const key_type& k) const
{
return table_.count(k);
diff --git a/test/unordered/find_tests.cpp b/test/unordered/find_tests.cpp
index 24523fd3..e823a04d 100644
--- a/test/unordered/find_tests.cpp
+++ b/test/unordered/find_tests.cpp
@@ -83,6 +83,55 @@ void find_tests1(X*, test::random_generator generator = test::default_generator)
}
}
+struct compatible_key
+{
+ test::object o_;
+
+ compatible_key(test::object const& o) : o_(o) {}
+};
+
+struct compatible_hash
+{
+ test::hash hash_;
+
+ std::size_t operator()(compatible_key const& k) const {
+ return hash_(k.o_);
+ }
+};
+
+struct compatible_predicate
+{
+ test::equal_to equal_;
+
+ bool operator()(compatible_key const& k1, compatible_key const& k2) const {
+ return equal_(k1.o_, k2.o_);
+ }
+};
+
+template
+void find_compatible_keys_test(X*, test::random_generator generator = test::default_generator)
+{
+ typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
+ typedef BOOST_DEDUCED_TYPENAME test::random_values::iterator value_iterator;
+ test::random_values v(500, generator);
+ X x(v.begin(), v.end());
+
+ compatible_hash h;
+ compatible_predicate eq;
+
+ for(value_iterator it = v.begin(), end = v.end(); it != end; ++it) {
+ BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key(*it);
+ BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq));
+ }
+
+ test::random_values v2(20, generator);
+
+ for(value_iterator it = v2.begin(), end = v2.end(); it != end; ++it) {
+ BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key(*it);
+ BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq));
+ }
+}
+
boost::unordered_set >* test_set;
boost::unordered_multiset >* test_multiset;
boost::unordered_map >* test_map;
@@ -95,6 +144,10 @@ UNORDERED_TEST(find_tests1,
((test_set)(test_multiset)(test_map)(test_multimap))
((default_generator)(generate_collisions))
)
+UNORDERED_TEST(find_compatible_keys_test,
+ ((test_set)(test_multiset)(test_map)(test_multimap))
+ ((default_generator)(generate_collisions))
+)
}