Added C++20 remove and remove_if overloads to vector-like containers

This commit is contained in:
Ion Gaztañaga
2025-10-29 00:12:43 +01:00
parent 4f6c915f95
commit 3763c80ec6
9 changed files with 213 additions and 0 deletions

View File

@@ -3065,6 +3065,28 @@ template <typename InputIterator, typename Allocator>
deque(InputIterator, InputIterator, Allocator const&) -> deque<typename iterator_traits<InputIterator>::value_type, Allocator>;
#endif
//! <b>Effects</b>: Erases all elements that compare equal to v from the container c.
//!
//! <b>Complexity</b>: Linear.
template <class T, class A, class O, class U>
inline typename deque<T, A, O>::size_type erase(deque<T, A, O>& c, const U& v)
{
typename deque<T, A, O>::size_type old_size = c.size();
c.erase(boost::container::remove(c.begin(), c.end(), v), c.end());
return old_size - c.size();
}
//! <b>Effects</b>: Erases all elements that satisfy the predicate pred from the container c.
//!
//! <b>Complexity</b>: Linear.
template <class T, class A, class O, class Pred>
inline typename deque<T, A, O>::size_type erase_if(deque<T, A, O>& c, Pred pred)
{
typename deque<T, A, O>::size_type old_size = c.size();
c.erase(boost::container::remove_if(c.begin(), c.end(), pred), c.end());
return old_size - c.size();
}
} //namespace container
} //namespace boost

View File

@@ -22,6 +22,7 @@
#endif
#include <boost/intrusive/detail/algorithm.hpp>
#include <boost/move/utility_core.hpp>
namespace boost {
namespace container {
@@ -179,6 +180,39 @@ ForwardIt1 search(ForwardIt1 first1, ForwardIt1 last1,
}
}
template<class InpIt, class U>
InpIt find(InpIt first, InpIt last, const U& value)
{
for (; first != last; ++first)
if (*first == value)
return first;
return last;
}
template<class FwdIt, class U>
FwdIt remove(FwdIt first, FwdIt last, const U& value)
{
first = find(first, last, value);
if (first != last)
for (FwdIt i = first; ++i != last;)
if (!(*i == value))
*first++ = boost::move(*i);
return first;
}
template<class FwdIt, class Pred>
FwdIt remove_if(FwdIt first, FwdIt last, Pred p)
{
first = find_if(first, last, p);
if (first != last)
for (FwdIt i = first; ++i != last;)
if (!p(*i))
*first++ = boost::move(*i);
return first;
}
} //namespace container {
} //namespace boost {

View File

@@ -3040,6 +3040,28 @@ class devector
#endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
//! <b>Effects</b>: Erases all elements that compare equal to v from the container c.
//!
//! <b>Complexity</b>: Linear.
template <class T, class A, class O, class U>
inline typename devector<T, A, O>::size_type erase(devector<T, A, O>& c, const U& v)
{
typename devector<T, A, O>::size_type old_size = c.size();
c.erase(boost::container::remove(c.begin(), c.end(), v), c.end());
return old_size - c.size();
}
//! <b>Effects</b>: Erases all elements that satisfy the predicate pred from the container c.
//!
//! <b>Complexity</b>: Linear.
template <class T, class A, class O, class Pred>
inline typename devector<T, A, O>::size_type erase_if(devector<T, A, O>& c, Pred pred)
{
typename devector<T, A, O>::size_type old_size = c.size();
c.erase(boost::container::remove_if(c.begin(), c.end(), pred), c.end());
return old_size - c.size();
}
}} // namespace boost::container
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED

View File

@@ -675,6 +675,28 @@ class small_vector
{ this->base_type::prot_shrink_to_fit_small(this->internal_capacity()); }
};
//! <b>Effects</b>: Erases all elements that compare equal to v from the container c.
//!
//! <b>Complexity</b>: Linear.
template <class T, std::size_t N, class A, class O, class U>
inline typename small_vector<T, N, A, O>::size_type erase(small_vector<T, N, A, O>& c, const U& v)
{
typename small_vector<T, N, A, O>::size_type old_size = c.size();
c.erase(boost::container::remove(c.begin(), c.end(), v), c.end());
return old_size - c.size();
}
//! <b>Effects</b>: Erases all elements that satisfy the predicate pred from the container c.
//!
//! <b>Complexity</b>: Linear.
template <class T, std::size_t N, class A, class O, class Pred>
inline typename small_vector<T, N, A, O>::size_type erase_if(small_vector<T, N, A, O>& c, Pred pred)
{
typename small_vector<T, N, A, O>::size_type old_size = c.size();
c.erase(boost::container::remove_if(c.begin(), c.end(), pred), c.end());
return old_size - c.size();
}
}}
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED

View File

@@ -2251,6 +2251,28 @@ stable_vector(InputIterator, InputIterator, Allocator const&) ->
#undef BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT
//! <b>Effects</b>: Erases all elements that compare equal to v from the container c.
//!
//! <b>Complexity</b>: Linear.
template <class T, class A, class U>
inline typename stable_vector<T, A>::size_type erase(stable_vector<T, A>& c, const U& v)
{
typename stable_vector<T, A>::size_type old_size = c.size();
c.erase(boost::container::remove(c.begin(), c.end(), v), c.end());
return old_size - c.size();
}
//! <b>Effects</b>: Erases all elements that satisfy the predicate pred from the container c.
//!
//! <b>Complexity</b>: Linear.
template <class T, class A, class Pred>
inline typename stable_vector<T, A>::size_type erase_if(stable_vector<T, A>& c, Pred pred)
{
typename stable_vector<T, A>::size_type old_size = c.size();
c.erase(boost::container::remove_if(c.begin(), c.end(), pred), c.end());
return old_size - c.size();
}
} //namespace container {
//!has_trivial_destructor_after_move<> == true_type

View File

@@ -1333,6 +1333,28 @@ inline void swap(static_vector<V, C1, O1> & x, static_vector<V, C2, O2> & y
#endif // BOOST_CONTAINER_DOXYGEN_INVOKED
//! <b>Effects</b>: Erases all elements that compare equal to v from the container c.
//!
//! <b>Complexity</b>: Linear.
template <class T, std::size_t N, class O, class U>
inline typename static_vector<T, N, O>::size_type erase(static_vector<T, N, O>& c, const U& v)
{
typename static_vector<T, N, O>::size_type old_size = c.size();
c.erase(boost::container::remove(c.begin(), c.end(), v), c.end());
return old_size - c.size();
}
//! <b>Effects</b>: Erases all elements that satisfy the predicate pred from the container c.
//!
//! <b>Complexity</b>: Linear.
template <class T, std::size_t N, class O, class Pred>
inline typename static_vector<T, N, O>::size_type erase_if(static_vector<T, N, O>& c, Pred pred)
{
typename static_vector<T, N, O>::size_type old_size = c.size();
c.erase(boost::container::remove_if(c.begin(), c.end(), pred), c.end());
return old_size - c.size();
}
}} // namespace boost::container
#include <boost/container/detail/config_end.hpp>

View File

@@ -3550,6 +3550,28 @@ getline(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,Allocat
return getline(is, s, '\n');
}
//! <b>Effects</b>: Erases all elements that compare equal to v from the container c.
//!
//! <b>Complexity</b>: Linear.
template <class T, class Tr, class A, class U>
inline typename basic_string<T, Tr, A>::size_type erase(basic_string<T, Tr, A>& c, const U& v)
{
typename basic_string<T, Tr, A>::size_type old_size = c.size();
c.erase(boost::container::remove(c.begin(), c.end(), v), c.end());
return old_size - c.size();
}
//! <b>Effects</b>: Erases all elements that satisfy the predicate pred from the container c.
//!
//! <b>Complexity</b>: Linear.
template <class T, class Tr, class A, class Pred>
inline typename basic_string<T, Tr, A>::size_type erase_if(basic_string<T, Tr, A>& c, Pred pred)
{
typename basic_string<T, Tr, A>::size_type old_size = c.size();
c.erase(boost::container::remove_if(c.begin(), c.end(), pred), c.end());
return old_size - c.size();
}
}}
//GCC 12 has a regression for array-bounds warnings

View File

@@ -3351,6 +3351,27 @@ vector(InputIterator, InputIterator, Allocator const&) ->
#endif
//! <b>Effects</b>: Erases all elements that compare equal to v from the container c.
//!
//! <b>Complexity</b>: Linear.
template <class T, class A, class O, class U>
inline typename vector<T, A, O>::size_type erase(vector<T, A, O>& c, const U& v)
{
typename vector<T, A, O>::size_type old_size = c.size();
c.erase(boost::container::remove(c.begin(), c.end(), v), c.end());
return old_size - c.size();
}
//! <b>Effects</b>: Erases all elements that satisfy the predicate pred from the container c.
//!
//! <b>Complexity</b>: Linear.
template <class T, class A, class O, class Pred>
inline typename vector<T, A, O>::size_type erase_if(vector<T, A, O>& c, Pred pred)
{
typename vector<T, A, O>::size_type old_size = c.size();
c.erase(boost::container::remove_if(c.begin(), c.end(), pred), c.end());
return old_size - c.size();
}
}} //namespace boost::container

View File

@@ -19,6 +19,7 @@
#include <boost/move/utility_core.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/algorithm.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/move/iterator.hpp>
#include <boost/move/make_unique.hpp>
@@ -558,6 +559,31 @@ int vector_move_assignable_only(boost::container::dtl::true_type)
boostvector.resize(100u);
if(!test_nth_index_of(boostvector))
return 1;
//test erase/erase_if
IntType aux_vect[50];
for(int i = 0; i < 50; ++i){
aux_vect[i] = i;
}
int aux_vect2[50];
for(int i = 0; i < 50; ++i){
aux_vect2[i] = i;
}
boostvector.clear();
stdvector.clear();
boostvector.insert(boostvector.end()
,boost::make_move_iterator(&aux_vect[0])
,boost::make_move_iterator(aux_vect + 50));
stdvector.insert(stdvector.end(), aux_vect2, aux_vect2 + 50);
if (1 != erase(boostvector, 25))
return 1;
stdvector.erase(boost::container::find(stdvector.begin(), stdvector.end(), 25));
if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
if (0 != erase(boostvector, 25))
return 1;
}
return 0;
}