From a7873e975d67b69308976e695f25c6d97ec52238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sat, 1 Nov 2025 11:49:49 +0100 Subject: [PATCH] Add erase_if for set/flat_set --- include/boost/container/detail/algorithm.hpp | 22 +++++++++ include/boost/container/flat_set.hpp | 19 ++++++++ include/boost/container/set.hpp | 19 ++++++++ test/set_test.hpp | 49 ++++++++++++++++++++ 4 files changed, 109 insertions(+) diff --git a/include/boost/container/detail/algorithm.hpp b/include/boost/container/detail/algorithm.hpp index 38399d8..93ad74d 100644 --- a/include/boost/container/detail/algorithm.hpp +++ b/include/boost/container/detail/algorithm.hpp @@ -213,6 +213,28 @@ FwdIt remove_if(FwdIt first, FwdIt last, Pred p) return first; } +template +typename Cont::size_type container_erase_if(Cont& c, Pred p) +{ + typedef typename Cont::size_type size_type; + typedef typename Cont::iterator it_t; + + size_type prev_size = c.size(); + it_t it = c.begin(); + + //end() must be called each loop for non-node containers + while ( it != c.end() ) { + if (p(*it)) { + it = c.erase(it); + } + else { + ++it; + } + } + + return prev_size - c.size(); +} + } //namespace container { } //namespace boost { diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp index caffd16..7ee5ada 100644 --- a/include/boost/container/flat_set.hpp +++ b/include/boost/container/flat_set.hpp @@ -28,6 +28,7 @@ // container/detail #include #include +#include // move #include #include @@ -1132,6 +1133,15 @@ class flat_set { return this->get_sequence_cref(); } }; +//! Effects: Erases all elements that satisfy the predicate pred from the container c. +//! +//! Complexity: Linear. +template +inline typename flat_set::size_type erase_if(flat_set& c, Pred pred) +{ + return container_erase_if(c, pred); +} + #ifndef BOOST_CONTAINER_NO_CXX17_CTAD template @@ -1863,6 +1873,15 @@ class flat_multiset { return this->get_sequence_cref(); } }; +//! Effects: Erases all elements that satisfy the predicate pred from the container c. +//! +//! Complexity: Linear. +template +inline typename flat_multiset::size_type erase_if(flat_multiset& c, Pred pred) +{ + return container_erase_if(c, pred); +} + #ifndef BOOST_CONTAINER_NO_CXX17_CTAD template diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp index e71a1ec..4974f72 100644 --- a/include/boost/container/set.hpp +++ b/include/boost/container/set.hpp @@ -27,6 +27,7 @@ #include #include #include //new_allocator +#include // intrusive/detail #include //pair #include //less, equal @@ -957,6 +958,15 @@ class set #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) }; +//! Effects: Erases all elements that satisfy the predicate pred from the container c. +//! +//! Complexity: Linear. +template +inline typename set::size_type erase_if(set& c, Pred pred) +{ + return container_erase_if(c, pred); +} + #ifndef BOOST_CONTAINER_NO_CXX17_CTAD template @@ -1612,6 +1622,15 @@ class multiset #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) }; +//! Effects: Erases all elements that satisfy the predicate pred from the container c. +//! +//! Complexity: Linear. +template +inline typename multiset::size_type erase_if(multiset& c, Pred pred) +{ + return container_erase_if(c, pred); +} + #ifndef BOOST_CONTAINER_NO_CXX17_CTAD template diff --git a/test/set_test.hpp b/test/set_test.hpp index 5846748..b564424 100644 --- a/test/set_test.hpp +++ b/test/set_test.hpp @@ -12,6 +12,7 @@ #define BOOST_CONTAINER_TEST_SET_TEST_HEADER #include +#include #include "check_equal_containers.hpp" #include "print_container.hpp" #include "movable_int.hpp" @@ -823,6 +824,54 @@ int set_test () if(!CheckEqualContainers(boostmultiset, stdmultiset)) return 1; } + { //erase_if + boostset.clear(); + boostmultiset.clear(); + stdset.clear(); + stdmultiset.clear(); + + { + IntType aux_vect[(std::size_t)MaxElem]; + IntType aux_vect2[(std::size_t)MaxElem]; + IntType aux_vect3[(std::size_t)MaxElem]; + + for(int i = 0; i < MaxElem; ++i){ + aux_vect[i] = i; + aux_vect2[i] = i; + aux_vect3[i] = i; + } + + boostset. insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem)); + boostmultiset.insert(boost::make_move_iterator(&aux_vect2[0]), boost::make_move_iterator(&aux_vect2[0] + MaxElem)); + boostmultiset.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem)); + } + + for(int i = 0; i < MaxElem; ++i){ + stdset.insert(i); + stdmultiset.insert(i); + stdmultiset.insert(i); + } + + for(int i = 0; i < MaxElem; ++i) { + //erase_if + const int setkey = (i + MaxElem/2) % MaxElem; + if (1 != erase_if(boostset, equal_to_value(setkey))) + return 1; + if (0 != erase_if(boostset, equal_to_value(setkey))) + return 1; + stdset.erase(setkey); + if(!test::CheckEqualContainers(boostset, stdset)) return false; + + //erase_if + if (2 != erase_if(boostmultiset, equal_to_value(setkey))) + return 1; + if (0 != erase_if(boostmultiset, equal_to_value(setkey))) + return 1; + stdmultiset.erase(setkey); + if(!test::CheckEqualContainers(boostmultiset, stdmultiset)) return false; + } + } + if(set_test_copyable (dtl::bool_::value>())){ return 1;