From 2f7bba0c21e427fdf0bb597fb53e09ba721dc6dc Mon Sep 17 00:00:00 2001 From: Christian Mazakas Date: Wed, 14 Jun 2023 15:29:08 -0700 Subject: [PATCH] Implement proxy erase(iterator) --- include/boost/unordered/detail/foa/table.hpp | 27 +++++++++++++++++-- .../boost/unordered/unordered_flat_map.hpp | 10 +++++-- .../boost/unordered/unordered_flat_set.hpp | 4 ++- .../boost/unordered/unordered_node_map.hpp | 10 +++++-- .../boost/unordered/unordered_node_set.hpp | 4 ++- test/unordered/compile_tests.hpp | 4 +-- test/unordered/erase_tests.cpp | 13 +-------- test/unordered/transparent_tests.cpp | 16 ----------- 8 files changed, 50 insertions(+), 38 deletions(-) diff --git a/include/boost/unordered/detail/foa/table.hpp b/include/boost/unordered/detail/foa/table.hpp index a2fa96e6..e42e08e4 100644 --- a/include/boost/unordered/detail/foa/table.hpp +++ b/include/boost/unordered/detail/foa/table.hpp @@ -348,17 +348,40 @@ public: >::type insert(element_type&& x){return emplace_impl(std::move(x));} + struct proxy_erase { + const_iterator pos; + operator iterator()const noexcept + { + auto it=pos; + it.increment(); + return iterator(const_iterator_cast_tag{},it); + } + + template< + bool dependent_value=false, + typename std::enable_if< + has_mutable_iterator||dependent_value>::type* =nullptr + > + operator const_iterator()const noexcept + { + auto it=pos; + it.increment(); + return it; + } + }; + template< bool dependent_value=false, typename std::enable_if< has_mutable_iterator||dependent_value>::type* =nullptr > - void erase(iterator pos)noexcept{return erase(const_iterator(pos));} + proxy_erase erase(iterator pos)noexcept{return erase(const_iterator(pos));} BOOST_FORCEINLINE - void erase(const_iterator pos)noexcept + proxy_erase erase(const_iterator pos)noexcept { super::erase(pos.pc,pos.p); + return proxy_erase{pos}; } template diff --git a/include/boost/unordered/unordered_flat_map.hpp b/include/boost/unordered/unordered_flat_map.hpp index 1012798f..ad3f6fec 100644 --- a/include/boost/unordered/unordered_flat_map.hpp +++ b/include/boost/unordered/unordered_flat_map.hpp @@ -381,11 +381,17 @@ namespace boost { .first; } - BOOST_FORCEINLINE void erase(iterator pos) { table_.erase(pos); } - BOOST_FORCEINLINE void erase(const_iterator pos) + BOOST_FORCEINLINE typename table_type::proxy_erase erase(iterator pos) { return table_.erase(pos); } + + BOOST_FORCEINLINE typename table_type::proxy_erase erase( + const_iterator pos) + { + return table_.erase(pos); + } + iterator erase(const_iterator first, const_iterator last) { while (first != last) { diff --git a/include/boost/unordered/unordered_flat_set.hpp b/include/boost/unordered/unordered_flat_set.hpp index fc3b5f1b..4be909b7 100644 --- a/include/boost/unordered/unordered_flat_set.hpp +++ b/include/boost/unordered/unordered_flat_set.hpp @@ -282,10 +282,12 @@ namespace boost { return table_.emplace(std::forward(args)...).first; } - BOOST_FORCEINLINE void erase(const_iterator pos) + BOOST_FORCEINLINE typename table_type::proxy_erase erase( + const_iterator pos) { return table_.erase(pos); } + iterator erase(const_iterator first, const_iterator last) { while (first != last) { diff --git a/include/boost/unordered/unordered_node_map.hpp b/include/boost/unordered/unordered_node_map.hpp index f0ce0974..a5cecba7 100644 --- a/include/boost/unordered/unordered_node_map.hpp +++ b/include/boost/unordered/unordered_node_map.hpp @@ -458,11 +458,17 @@ namespace boost { .first; } - BOOST_FORCEINLINE void erase(iterator pos) { table_.erase(pos); } - BOOST_FORCEINLINE void erase(const_iterator pos) + BOOST_FORCEINLINE typename table_type::proxy_erase erase(iterator pos) { return table_.erase(pos); } + + BOOST_FORCEINLINE typename table_type::proxy_erase erase( + const_iterator pos) + { + return table_.erase(pos); + } + iterator erase(const_iterator first, const_iterator last) { while (first != last) { diff --git a/include/boost/unordered/unordered_node_set.hpp b/include/boost/unordered/unordered_node_set.hpp index 68be4a6e..57a7405c 100644 --- a/include/boost/unordered/unordered_node_set.hpp +++ b/include/boost/unordered/unordered_node_set.hpp @@ -352,10 +352,12 @@ namespace boost { return table_.emplace(std::forward(args)...).first; } - BOOST_FORCEINLINE void erase(const_iterator pos) + BOOST_FORCEINLINE typename table_type::proxy_erase erase( + const_iterator pos) { return table_.erase(pos); } + iterator erase(const_iterator first, const_iterator last) { while (first != last) { diff --git a/test/unordered/compile_tests.hpp b/test/unordered/compile_tests.hpp index e45a4570..0ca19487 100644 --- a/test/unordered/compile_tests.hpp +++ b/test/unordered/compile_tests.hpp @@ -844,7 +844,7 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq) a10.insert(t); q = a10.cbegin(); #ifdef BOOST_UNORDERED_FOA_TESTS - BOOST_STATIC_ASSERT(std::is_same::value); + test::check_return_type::convertible(a10.erase(q)); #else test::check_return_type::equals(a10.erase(q)); #endif @@ -937,7 +937,7 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq) a10.insert(boost::move(v5)); q = a10.cbegin(); #ifdef BOOST_UNORDERED_FOA_TESTS - BOOST_STATIC_ASSERT(std::is_same::value); + test::check_return_type::convertible(a10.erase(q)); #else test::check_return_type::equals(a10.erase(q)); #endif diff --git a/test/unordered/erase_tests.cpp b/test/unordered/erase_tests.cpp index e7b563ab..c75b33c2 100644 --- a/test/unordered/erase_tests.cpp +++ b/test/unordered/erase_tests.cpp @@ -23,9 +23,7 @@ namespace erase_tests { template void erase_tests1(Container*, test::random_generator generator) { -#ifndef BOOST_UNORDERED_FOA_TESTS typedef typename Container::iterator iterator; -#endif typedef typename Container::const_iterator c_iterator; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase by key.\n"; @@ -59,12 +57,8 @@ namespace erase_tests { while (size > 0 && !x.empty()) { typename Container::key_type key = test::get_key(*x.begin()); std::size_t count = x.count(key); -#ifdef BOOST_UNORDERED_FOA_TESTS - x.erase(x.begin()); -#else iterator pos = x.erase(x.begin()); - BOOST_TEST(pos == x.begin()); -#endif + BOOST_ASSERT(BOOST_TEST(pos == x.begin())); --size; BOOST_TEST(x.count(key) == count - 1); BOOST_TEST(x.size() == size); @@ -95,15 +89,10 @@ namespace erase_tests { typename Container::key_type key = test::get_key(*pos); std::size_t count = x.count(key); BOOST_TEST(count > 0); -#ifdef BOOST_UNORDERED_FOA_TESTS - x.erase(pos); - --size; -#else BOOST_TEST(next == x.erase(pos)); --size; if (size > 0) BOOST_TEST(index == 0 ? next == x.begin() : next == test::next(prev)); -#endif BOOST_TEST(x.count(key) == count - 1); if (x.count(key) != count - 1) { BOOST_LIGHTWEIGHT_TEST_OSTREAM << count << " => " << x.count(key) diff --git a/test/unordered/transparent_tests.cpp b/test/unordered/transparent_tests.cpp index a13d54c1..9d9b8458 100644 --- a/test/unordered/transparent_tests.cpp +++ b/test/unordered/transparent_tests.cpp @@ -1065,11 +1065,7 @@ typedef boost::unordered_map c; @@ -1079,11 +1075,7 @@ map_erase_overload_compile_test() return map.erase(c); } -#ifdef BOOST_UNORDERED_FOA_TESTS -void -#else transparent_unordered_map::const_iterator -#endif map_erase_const_overload_compile_test() { convertible_to_const_iterator c; @@ -1226,11 +1218,7 @@ typedef boost::unordered_multiset c; @@ -1240,11 +1228,7 @@ set_erase_overload_compile_test() return set.erase(c); } -#ifdef BOOST_UNORDERED_FOA_TESTS -void -#else transparent_unordered_set::const_iterator -#endif set_erase_const_overload_compile_test() { convertible_to_const_iterator c;