From ff4ca3098b8fde810213cd7d32827d29c78b7eff Mon Sep 17 00:00:00 2001 From: Christian Mazakas Date: Mon, 27 Dec 2021 09:01:07 -0800 Subject: [PATCH 1/3] Rename transparent `equal_range()` tests to include map in their name --- test/unordered/transparent_tests.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/unordered/transparent_tests.cpp b/test/unordered/transparent_tests.cpp index 9734e28e..0930c02d 100644 --- a/test/unordered/transparent_tests.cpp +++ b/test/unordered/transparent_tests.cpp @@ -365,7 +365,7 @@ template void test_set_non_transparent_find() } } -template void test_transparent_equal_range() +template void test_map_transparent_equal_range() { count_reset(); @@ -493,7 +493,7 @@ template void test_transparent_equal_range() } } -template void test_non_transparent_equal_range() +template void test_map_non_transparent_equal_range() { count_reset(); @@ -986,7 +986,7 @@ void test_unordered_map() test_transparent_count(); test_map_transparent_find(); - test_transparent_equal_range(); + test_map_transparent_equal_range(); test_map_transparent_erase(); test_transparent_extract(); } @@ -998,7 +998,7 @@ void test_unordered_map() test_non_transparent_count(); test_map_non_transparent_find(); - test_non_transparent_equal_range(); + test_map_non_transparent_equal_range(); test_map_non_transparent_erase(); test_non_transparent_extract(); } @@ -1011,7 +1011,7 @@ void test_unordered_map() test_non_transparent_count(); test_map_non_transparent_find(); - test_non_transparent_equal_range(); + test_map_non_transparent_equal_range(); test_map_non_transparent_erase(); test_non_transparent_extract(); } @@ -1024,7 +1024,7 @@ void test_unordered_map() test_non_transparent_count(); test_map_non_transparent_find(); - test_non_transparent_equal_range(); + test_map_non_transparent_equal_range(); test_map_non_transparent_erase(); test_non_transparent_extract(); } @@ -1039,7 +1039,7 @@ void test_unordered_multimap() test_transparent_count(); test_map_transparent_find(); - test_transparent_equal_range(); + test_map_transparent_equal_range(); test_map_transparent_erase(); test_transparent_extract(); } @@ -1052,7 +1052,7 @@ void test_unordered_multimap() test_non_transparent_count(); test_map_non_transparent_find(); - test_non_transparent_equal_range(); + test_map_non_transparent_equal_range(); test_map_non_transparent_erase(); test_non_transparent_extract(); } @@ -1065,7 +1065,7 @@ void test_unordered_multimap() test_non_transparent_count(); test_map_non_transparent_find(); - test_non_transparent_equal_range(); + test_map_non_transparent_equal_range(); test_map_non_transparent_erase(); test_non_transparent_extract(); } @@ -1078,7 +1078,7 @@ void test_unordered_multimap() test_non_transparent_count(); test_map_non_transparent_find(); - test_non_transparent_equal_range(); + test_map_non_transparent_equal_range(); test_map_non_transparent_erase(); test_non_transparent_extract(); } From b23e47c478914b62ffeebb18d0e59390adc71ce3 Mon Sep 17 00:00:00 2001 From: Christian Mazakas Date: Mon, 27 Dec 2021 12:07:42 -0800 Subject: [PATCH 2/3] Add transparent test support for set's `equal_range()` --- test/unordered/transparent_tests.cpp | 261 +++++++++++++++++++++++++++ 1 file changed, 261 insertions(+) diff --git a/test/unordered/transparent_tests.cpp b/test/unordered/transparent_tests.cpp index 0930c02d..fb9339d3 100644 --- a/test/unordered/transparent_tests.cpp +++ b/test/unordered/transparent_tests.cpp @@ -622,6 +622,263 @@ template void test_map_non_transparent_equal_range() } } +template void test_set_transparent_equal_range() +{ + count_reset(); + + UnorderedSet unordered_set; + + // empty tests + // + // explicitly test `equal_range()` vs `equal_range() const` + // + { + typedef typename UnorderedSet::iterator iterator; + typedef std::pair iterator_pair; + + UnorderedSet& set = unordered_set; + BOOST_TEST(set.empty()); + + iterator_pair iters = set.equal_range(0); + + iterator begin = iters.first; + iterator end = iters.second; + + BOOST_TEST(begin == end); + BOOST_TEST(begin == set.end()); + BOOST_TEST_EQ(std::distance(begin, end), 0); + } + + { + typedef typename UnorderedSet::const_iterator iterator; + typedef std::pair iterator_pair; + + UnorderedSet const& set = unordered_set; + BOOST_TEST(set.empty()); + + iterator_pair iters = set.equal_range(0); + + iterator begin = iters.first; + iterator end = iters.second; + + BOOST_TEST(begin == end); + BOOST_TEST(begin == set.end()); + BOOST_TEST_EQ(std::distance(begin, end), 0); + } + + BOOST_TEST_EQ(key::count_, 0); + + unordered_set.insert(0); + unordered_set.insert(1); + unordered_set.insert(2); + unordered_set.insert(0); + unordered_set.insert(0); + unordered_set.insert(0); + + int const expected_key_count = key::count_; + + // do this so that multiset tests actually test a range with len > 1 + // + int const expected_range_len = static_cast(unordered_set.size() - 2); + + typedef typename UnorderedSet::value_type value_type; + + // explicitly test `equal_range()` vs `equal_range() const` + // + { + typedef typename UnorderedSet::iterator iterator; + typedef std::pair iterator_pair; + + UnorderedSet& set = unordered_set; + + iterator_pair iters = set.equal_range(0); + + iterator begin = iters.first; + iterator end = iters.second; + + BOOST_TEST(begin != end); + BOOST_TEST(begin != set.end()); + BOOST_TEST_EQ(std::distance(begin, end), expected_range_len); + + for (iterator pos = begin; pos != end; ++pos) { + value_type const& val = *pos; + BOOST_TEST_EQ(val, 0); + } + + iters = set.equal_range(1337); + + begin = iters.first; + end = iters.second; + + BOOST_TEST(begin == end); + BOOST_TEST(begin == set.end()); + BOOST_TEST_EQ(std::distance(begin, end), 0); + + BOOST_TEST_EQ(key::count_, expected_key_count); + } + + { + typedef typename UnorderedSet::const_iterator iterator; + typedef std::pair iterator_pair; + + UnorderedSet const& set = unordered_set; + + iterator_pair iters = set.equal_range(0); + + iterator begin = iters.first; + iterator end = iters.second; + + BOOST_TEST(begin != end); + BOOST_TEST(begin != set.end()); + BOOST_TEST_EQ(std::distance(begin, end), expected_range_len); + + for (iterator pos = begin; pos != end; ++pos) { + value_type const& val = *begin; + BOOST_TEST_EQ(val, 0); + } + + iters = set.equal_range(1337); + + begin = iters.first; + end = iters.second; + + BOOST_TEST(begin == end); + BOOST_TEST(begin == set.end()); + BOOST_TEST_EQ(std::distance(begin, end), 0); + + BOOST_TEST_EQ(key::count_, expected_key_count); + } +} + +template void test_set_non_transparent_equal_range() +{ + count_reset(); + + UnorderedSet unordered_set; + + // empty tests + // + // explicitly test `equal_range()` vs `equal_range() const` + // + { + typedef typename UnorderedSet::iterator iterator; + typedef std::pair iterator_pair; + + UnorderedSet& set = unordered_set; + BOOST_TEST(set.empty()); + + iterator_pair iters = set.equal_range(0); + + iterator begin = iters.first; + iterator end = iters.second; + + BOOST_TEST(begin == end); + BOOST_TEST(begin == set.end()); + BOOST_TEST_EQ(std::distance(begin, end), 0); + } + + { + typedef typename UnorderedSet::const_iterator iterator; + typedef std::pair iterator_pair; + + UnorderedSet const& set = unordered_set; + BOOST_TEST(set.empty()); + + iterator_pair iters = set.equal_range(0); + + iterator begin = iters.first; + iterator end = iters.second; + + BOOST_TEST(begin == end); + BOOST_TEST(begin == set.end()); + BOOST_TEST_EQ(std::distance(begin, end), 0); + } + + BOOST_TEST_EQ(key::count_, 2); + + unordered_set.insert(0); + unordered_set.insert(1); + unordered_set.insert(2); + unordered_set.insert(0); + unordered_set.insert(0); + unordered_set.insert(0); + + int key_count = key::count_; + + // do this so that multiset tests actually test a range with len > 1 + // + int const expected_range_len = static_cast(unordered_set.size() - 2); + + typedef typename UnorderedSet::value_type value_type; + + // explicitly test `equal_range()` vs `equal_range() const` + // + { + typedef typename UnorderedSet::iterator iterator; + typedef std::pair iterator_pair; + + UnorderedSet& set = unordered_set; + + iterator_pair iters = set.equal_range(0); + + iterator begin = iters.first; + iterator end = iters.second; + + BOOST_TEST(begin != end); + BOOST_TEST(begin != set.end()); + BOOST_TEST_EQ(std::distance(begin, end), expected_range_len); + + for (iterator pos = begin; pos != end; ++pos) { + value_type const& val = *begin; + BOOST_TEST_EQ(val, 0); + } + + iters = set.equal_range(1337); + + begin = iters.first; + end = iters.second; + + BOOST_TEST(begin == end); + BOOST_TEST(begin == set.end()); + BOOST_TEST_EQ(std::distance(begin, end), 0); + + BOOST_TEST_EQ(key::count_, 2 + key_count); + key_count += 2; + } + + { + typedef typename UnorderedSet::const_iterator iterator; + typedef std::pair iterator_pair; + + UnorderedSet const& set = unordered_set; + + iterator_pair iters = set.equal_range(0); + + iterator begin = iters.first; + iterator end = iters.second; + + BOOST_TEST(begin != end); + BOOST_TEST(begin != set.end()); + BOOST_TEST_EQ(std::distance(begin, end), expected_range_len); + + for (iterator pos = begin; pos != end; ++pos) { + value_type const& val = *pos; + BOOST_TEST_EQ(val, 0); + } + + iters = set.equal_range(1337); + + begin = iters.first; + end = iters.second; + + BOOST_TEST(begin == end); + BOOST_TEST(begin == set.end()); + BOOST_TEST_EQ(std::distance(begin, end), 0); + + BOOST_TEST_EQ(key::count_, 2 + key_count); + } +} + template struct convertible_to_iterator { operator typename UnorderedMap::iterator() @@ -1092,6 +1349,7 @@ void test_unordered_set() test_set_transparent_find(); test_set_transparent_erase(); + test_set_transparent_equal_range(); } { @@ -1101,6 +1359,7 @@ void test_unordered_set() test_set_non_transparent_find(); test_set_non_transparent_erase(); + test_set_non_transparent_equal_range(); } { @@ -1111,6 +1370,7 @@ void test_unordered_set() test_set_non_transparent_find(); test_set_non_transparent_erase(); + test_set_non_transparent_equal_range(); } { @@ -1121,6 +1381,7 @@ void test_unordered_set() test_set_non_transparent_find(); test_set_non_transparent_erase(); + test_set_non_transparent_equal_range(); } } From 57a2b654889cff4b5785ad1edf481fafd775d6b2 Mon Sep 17 00:00:00 2001 From: Christian Mazakas Date: Mon, 27 Dec 2021 12:08:01 -0800 Subject: [PATCH 3/3] Implement heterogeneous `equal_range()` for set --- include/boost/unordered/unordered_set.hpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index c0841cf7..75003bf4 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -503,6 +503,19 @@ namespace boost { std::pair equal_range( const key_type&) const; + template + typename boost::enable_if_c::value, + std::pair >::type + equal_range(Key const& k) const + { + node_pointer n = table_.find_node_impl( + table::policy::apply_hash(this->hash_function(), k), k, + this->key_eq()); + + return std::make_pair( + const_iterator(n), const_iterator(n ? table::next_node(n) : n)); + } + // bucket interface size_type bucket_count() const BOOST_NOEXCEPT