diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index f5d59c19..a7765fe7 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -796,6 +796,23 @@ namespace boost { const_iterator find(CompatibleKey const&, CompatibleHash const&, CompatiblePredicate const&) const; + bool contains(const key_type& k) const + { + return table_.find_node_impl( + table::policy::apply_hash(this->hash_function(), k), k, + this->key_eq()); + } + + template + typename boost::enable_if_c::value, + bool>::type + contains(const Key& k) const + { + return table_.find_node_impl( + table::policy::apply_hash(this->hash_function(), k), k, + this->key_eq()); + } + size_type count(const key_type&) const; template diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 68617f89..d2573d20 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -64,6 +64,7 @@ test-suite unordered [ run unordered/scoped_allocator.cpp /boost/filesystem//boost_filesystem ] [ run unordered/transparent_tests.cpp ] [ run unordered/reserve_tests.cpp ] + [ run unordered/contains_tests.cpp ] [ run unordered/compile_set.cpp : : : BOOST_UNORDERED_USE_MOVE diff --git a/test/unordered/contains_tests.cpp b/test/unordered/contains_tests.cpp new file mode 100644 index 00000000..f1cefbc4 --- /dev/null +++ b/test/unordered/contains_tests.cpp @@ -0,0 +1,155 @@ +// Copyright 2021 Christian Mazakas. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// clang-format off +#include "../helpers/prefix.hpp" +#include +#include +#include "../helpers/postfix.hpp" +// clang-format on + +#include "../helpers/test.hpp" + +struct key +{ + int x_; + static int count_; + + key(int x) : x_(x) { ++count_; } + key(key const& k) : x_(k.x_) { ++count_; } +}; + +int key::count_; + +std::ostream& operator<<(std::ostream& os, key const& k) +{ + os << "key { x_: " << k.x_ << " }"; + return os; +} + +bool operator==(key const& k, int const x) { return k.x_ == x; } +bool operator==(int const x, key const& k) { return k.x_ == x; } + +struct transparent_hasher +{ + typedef void is_transparent; + + std::size_t operator()(key const& k) const + { + return boost::hash()(k.x_); + } + + std::size_t operator()(int const k) const { return boost::hash()(k); } +}; + +struct transparent_key_equal +{ + typedef void is_transparent; + + bool operator()(key const& k1, key const& k2) const { return k1.x_ == k2.x_; } + bool operator()(int const x, key const& k1) const { return k1 == x; } + bool operator()(key const& k1, int const x) const { return k1 == x; } +}; + +struct hasher +{ + std::size_t operator()(key const& k) const + { + return boost::hash()(k.x_); + } +}; + +struct key_equal +{ + bool operator()(key const& k1, key const& k2) const { return k1.x_ == k2.x_; } +}; + +void count_reset() { key::count_ = 0; } + +template void test_map_transparent_contains() +{ + count_reset(); + + UnorderedMap map; + bool contains = map.contains(0); + BOOST_TEST(!contains); + + BOOST_TEST_EQ(key::count_, 0); + + map.insert(std::make_pair(0, 1337)); + map.insert(std::make_pair(0, 1338)); + map.insert(std::make_pair(0, 1339)); + map.insert(std::make_pair(1, 1340)); + + int const expected_key_count = key::count_; + + contains = map.contains(0); + BOOST_TEST(contains); + + contains = map.contains(1); + BOOST_TEST(contains); + + contains = map.contains(2); + BOOST_TEST(!contains); + + BOOST_TEST_EQ(key::count_, expected_key_count); +} + +template void test_map_non_transparent_contains() +{ + count_reset(); + + UnorderedMap map; + bool contains = map.contains(0); + BOOST_TEST(!contains); + BOOST_TEST_EQ(key::count_, 1); + + map.insert(std::make_pair(0, 1337)); + map.insert(std::make_pair(0, 1338)); + map.insert(std::make_pair(0, 1339)); + map.insert(std::make_pair(1, 1340)); + + int key_count = key::count_; + + contains = map.contains(0); + ++key_count; + BOOST_TEST(contains); + + contains = map.contains(1); + ++key_count; + BOOST_TEST(contains); + + contains = map.contains(2); + ++key_count; + BOOST_TEST(!contains); + + BOOST_TEST_EQ(key::count_, key_count); +} + +void test_map() +{ + typedef boost::unordered_map + transparent_map; + + typedef boost::unordered_map + non_transparent_map1; + + typedef boost::unordered_map + non_transparent_map2; + + typedef boost::unordered_map + non_transparent_map3; + + test_map_transparent_contains(); + test_map_non_transparent_contains(); + test_map_non_transparent_contains(); + test_map_non_transparent_contains(); +} + +UNORDERED_AUTO_TEST (contains) { + test_map(); +} + +RUN_TESTS()