Skip to content

Commit 3763c80

Browse files
committed
Added C++20 remove and remove_if overloads to vector-like containers
1 parent 4f6c915 commit 3763c80

File tree

9 files changed

+213
-0
lines changed

9 files changed

+213
-0
lines changed

include/boost/container/deque.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3065,6 +3065,28 @@ template <typename InputIterator, typename Allocator>
30653065
deque(InputIterator, InputIterator, Allocator const&) -> deque<typename iterator_traits<InputIterator>::value_type, Allocator>;
30663066
#endif
30673067

3068+
//! <b>Effects</b>: Erases all elements that compare equal to v from the container c.
3069+
//!
3070+
//! <b>Complexity</b>: Linear.
3071+
template <class T, class A, class O, class U>
3072+
inline typename deque<T, A, O>::size_type erase(deque<T, A, O>& c, const U& v)
3073+
{
3074+
typename deque<T, A, O>::size_type old_size = c.size();
3075+
c.erase(boost::container::remove(c.begin(), c.end(), v), c.end());
3076+
return old_size - c.size();
3077+
}
3078+
3079+
//! <b>Effects</b>: Erases all elements that satisfy the predicate pred from the container c.
3080+
//!
3081+
//! <b>Complexity</b>: Linear.
3082+
template <class T, class A, class O, class Pred>
3083+
inline typename deque<T, A, O>::size_type erase_if(deque<T, A, O>& c, Pred pred)
3084+
{
3085+
typename deque<T, A, O>::size_type old_size = c.size();
3086+
c.erase(boost::container::remove_if(c.begin(), c.end(), pred), c.end());
3087+
return old_size - c.size();
3088+
}
3089+
30683090
} //namespace container
30693091
} //namespace boost
30703092

include/boost/container/detail/algorithm.hpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#endif
2323

2424
#include <boost/intrusive/detail/algorithm.hpp>
25+
#include <boost/move/utility_core.hpp>
2526

2627
namespace boost {
2728
namespace container {
@@ -179,6 +180,39 @@ ForwardIt1 search(ForwardIt1 first1, ForwardIt1 last1,
179180
}
180181
}
181182

183+
template<class InpIt, class U>
184+
InpIt find(InpIt first, InpIt last, const U& value)
185+
{
186+
for (; first != last; ++first)
187+
if (*first == value)
188+
return first;
189+
190+
return last;
191+
}
192+
193+
194+
template<class FwdIt, class U>
195+
FwdIt remove(FwdIt first, FwdIt last, const U& value)
196+
{
197+
first = find(first, last, value);
198+
if (first != last)
199+
for (FwdIt i = first; ++i != last;)
200+
if (!(*i == value))
201+
*first++ = boost::move(*i);
202+
return first;
203+
}
204+
205+
template<class FwdIt, class Pred>
206+
FwdIt remove_if(FwdIt first, FwdIt last, Pred p)
207+
{
208+
first = find_if(first, last, p);
209+
if (first != last)
210+
for (FwdIt i = first; ++i != last;)
211+
if (!p(*i))
212+
*first++ = boost::move(*i);
213+
return first;
214+
}
215+
182216
} //namespace container {
183217
} //namespace boost {
184218

include/boost/container/devector.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3040,6 +3040,28 @@ class devector
30403040
#endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
30413041
};
30423042

3043+
//! <b>Effects</b>: Erases all elements that compare equal to v from the container c.
3044+
//!
3045+
//! <b>Complexity</b>: Linear.
3046+
template <class T, class A, class O, class U>
3047+
inline typename devector<T, A, O>::size_type erase(devector<T, A, O>& c, const U& v)
3048+
{
3049+
typename devector<T, A, O>::size_type old_size = c.size();
3050+
c.erase(boost::container::remove(c.begin(), c.end(), v), c.end());
3051+
return old_size - c.size();
3052+
}
3053+
3054+
//! <b>Effects</b>: Erases all elements that satisfy the predicate pred from the container c.
3055+
//!
3056+
//! <b>Complexity</b>: Linear.
3057+
template <class T, class A, class O, class Pred>
3058+
inline typename devector<T, A, O>::size_type erase_if(devector<T, A, O>& c, Pred pred)
3059+
{
3060+
typename devector<T, A, O>::size_type old_size = c.size();
3061+
c.erase(boost::container::remove_if(c.begin(), c.end(), pred), c.end());
3062+
return old_size - c.size();
3063+
}
3064+
30433065
}} // namespace boost::container
30443066

30453067
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED

include/boost/container/small_vector.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,28 @@ class small_vector
675675
{ this->base_type::prot_shrink_to_fit_small(this->internal_capacity()); }
676676
};
677677

678+
//! <b>Effects</b>: Erases all elements that compare equal to v from the container c.
679+
//!
680+
//! <b>Complexity</b>: Linear.
681+
template <class T, std::size_t N, class A, class O, class U>
682+
inline typename small_vector<T, N, A, O>::size_type erase(small_vector<T, N, A, O>& c, const U& v)
683+
{
684+
typename small_vector<T, N, A, O>::size_type old_size = c.size();
685+
c.erase(boost::container::remove(c.begin(), c.end(), v), c.end());
686+
return old_size - c.size();
687+
}
688+
689+
//! <b>Effects</b>: Erases all elements that satisfy the predicate pred from the container c.
690+
//!
691+
//! <b>Complexity</b>: Linear.
692+
template <class T, std::size_t N, class A, class O, class Pred>
693+
inline typename small_vector<T, N, A, O>::size_type erase_if(small_vector<T, N, A, O>& c, Pred pred)
694+
{
695+
typename small_vector<T, N, A, O>::size_type old_size = c.size();
696+
c.erase(boost::container::remove_if(c.begin(), c.end(), pred), c.end());
697+
return old_size - c.size();
698+
}
699+
678700
}}
679701

680702
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED

include/boost/container/stable_vector.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2251,6 +2251,28 @@ stable_vector(InputIterator, InputIterator, Allocator const&) ->
22512251

22522252
#undef BOOST_CONTAINER_STABLE_VECTOR_CHECK_INVARIANT
22532253

2254+
//! <b>Effects</b>: Erases all elements that compare equal to v from the container c.
2255+
//!
2256+
//! <b>Complexity</b>: Linear.
2257+
template <class T, class A, class U>
2258+
inline typename stable_vector<T, A>::size_type erase(stable_vector<T, A>& c, const U& v)
2259+
{
2260+
typename stable_vector<T, A>::size_type old_size = c.size();
2261+
c.erase(boost::container::remove(c.begin(), c.end(), v), c.end());
2262+
return old_size - c.size();
2263+
}
2264+
2265+
//! <b>Effects</b>: Erases all elements that satisfy the predicate pred from the container c.
2266+
//!
2267+
//! <b>Complexity</b>: Linear.
2268+
template <class T, class A, class Pred>
2269+
inline typename stable_vector<T, A>::size_type erase_if(stable_vector<T, A>& c, Pred pred)
2270+
{
2271+
typename stable_vector<T, A>::size_type old_size = c.size();
2272+
c.erase(boost::container::remove_if(c.begin(), c.end(), pred), c.end());
2273+
return old_size - c.size();
2274+
}
2275+
22542276
} //namespace container {
22552277

22562278
//!has_trivial_destructor_after_move<> == true_type

include/boost/container/static_vector.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,6 +1333,28 @@ inline void swap(static_vector<V, C1, O1> & x, static_vector<V, C2, O2> & y
13331333

13341334
#endif // BOOST_CONTAINER_DOXYGEN_INVOKED
13351335

1336+
//! <b>Effects</b>: Erases all elements that compare equal to v from the container c.
1337+
//!
1338+
//! <b>Complexity</b>: Linear.
1339+
template <class T, std::size_t N, class O, class U>
1340+
inline typename static_vector<T, N, O>::size_type erase(static_vector<T, N, O>& c, const U& v)
1341+
{
1342+
typename static_vector<T, N, O>::size_type old_size = c.size();
1343+
c.erase(boost::container::remove(c.begin(), c.end(), v), c.end());
1344+
return old_size - c.size();
1345+
}
1346+
1347+
//! <b>Effects</b>: Erases all elements that satisfy the predicate pred from the container c.
1348+
//!
1349+
//! <b>Complexity</b>: Linear.
1350+
template <class T, std::size_t N, class O, class Pred>
1351+
inline typename static_vector<T, N, O>::size_type erase_if(static_vector<T, N, O>& c, Pred pred)
1352+
{
1353+
typename static_vector<T, N, O>::size_type old_size = c.size();
1354+
c.erase(boost::container::remove_if(c.begin(), c.end(), pred), c.end());
1355+
return old_size - c.size();
1356+
}
1357+
13361358
}} // namespace boost::container
13371359

13381360
#include <boost/container/detail/config_end.hpp>

include/boost/container/string.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3550,6 +3550,28 @@ getline(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,Allocat
35503550
return getline(is, s, '\n');
35513551
}
35523552

3553+
//! <b>Effects</b>: Erases all elements that compare equal to v from the container c.
3554+
//!
3555+
//! <b>Complexity</b>: Linear.
3556+
template <class T, class Tr, class A, class U>
3557+
inline typename basic_string<T, Tr, A>::size_type erase(basic_string<T, Tr, A>& c, const U& v)
3558+
{
3559+
typename basic_string<T, Tr, A>::size_type old_size = c.size();
3560+
c.erase(boost::container::remove(c.begin(), c.end(), v), c.end());
3561+
return old_size - c.size();
3562+
}
3563+
3564+
//! <b>Effects</b>: Erases all elements that satisfy the predicate pred from the container c.
3565+
//!
3566+
//! <b>Complexity</b>: Linear.
3567+
template <class T, class Tr, class A, class Pred>
3568+
inline typename basic_string<T, Tr, A>::size_type erase_if(basic_string<T, Tr, A>& c, Pred pred)
3569+
{
3570+
typename basic_string<T, Tr, A>::size_type old_size = c.size();
3571+
c.erase(boost::container::remove_if(c.begin(), c.end(), pred), c.end());
3572+
return old_size - c.size();
3573+
}
3574+
35533575
}}
35543576

35553577
//GCC 12 has a regression for array-bounds warnings

include/boost/container/vector.hpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3351,6 +3351,27 @@ vector(InputIterator, InputIterator, Allocator const&) ->
33513351

33523352
#endif
33533353

3354+
//! <b>Effects</b>: Erases all elements that compare equal to v from the container c.
3355+
//!
3356+
//! <b>Complexity</b>: Linear.
3357+
template <class T, class A, class O, class U>
3358+
inline typename vector<T, A, O>::size_type erase(vector<T, A, O>& c, const U& v)
3359+
{
3360+
typename vector<T, A, O>::size_type old_size = c.size();
3361+
c.erase(boost::container::remove(c.begin(), c.end(), v), c.end());
3362+
return old_size - c.size();
3363+
}
3364+
3365+
//! <b>Effects</b>: Erases all elements that satisfy the predicate pred from the container c.
3366+
//!
3367+
//! <b>Complexity</b>: Linear.
3368+
template <class T, class A, class O, class Pred>
3369+
inline typename vector<T, A, O>::size_type erase_if(vector<T, A, O>& c, Pred pred)
3370+
{
3371+
typename vector<T, A, O>::size_type old_size = c.size();
3372+
c.erase(boost::container::remove_if(c.begin(), c.end(), pred), c.end());
3373+
return old_size - c.size();
3374+
}
33543375

33553376
}} //namespace boost::container
33563377

test/vector_test.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include <boost/move/utility_core.hpp>
2121
#include <boost/container/detail/mpl.hpp>
22+
#include <boost/container/detail/algorithm.hpp>
2223
#include <boost/move/utility_core.hpp>
2324
#include <boost/move/iterator.hpp>
2425
#include <boost/move/make_unique.hpp>
@@ -558,6 +559,31 @@ int vector_move_assignable_only(boost::container::dtl::true_type)
558559
boostvector.resize(100u);
559560
if(!test_nth_index_of(boostvector))
560561
return 1;
562+
563+
//test erase/erase_if
564+
IntType aux_vect[50];
565+
for(int i = 0; i < 50; ++i){
566+
aux_vect[i] = i;
567+
}
568+
int aux_vect2[50];
569+
for(int i = 0; i < 50; ++i){
570+
aux_vect2[i] = i;
571+
}
572+
573+
boostvector.clear();
574+
stdvector.clear();
575+
boostvector.insert(boostvector.end()
576+
,boost::make_move_iterator(&aux_vect[0])
577+
,boost::make_move_iterator(aux_vect + 50));
578+
stdvector.insert(stdvector.end(), aux_vect2, aux_vect2 + 50);
579+
580+
if (1 != erase(boostvector, 25))
581+
return 1;
582+
stdvector.erase(boost::container::find(stdvector.begin(), stdvector.end(), 25));
583+
if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
584+
585+
if (0 != erase(boostvector, 25))
586+
return 1;
561587
}
562588
return 0;
563589
}

0 commit comments

Comments
 (0)