std::ranges::remove, std::ranges::remove_if - cppreference.com

Defined in header

<algorithm>

Call signature

template<std::permutableI,std::sentinel_for<I>S,classT,classProj=std::identity>requiresstd::indirect_binary_predicate<ranges::equal_to,std::projected<I,Proj>,constT*>constexprranges::subrange<I>remove(Ifirst,Slast,constT&value,Projproj={}); (1)(since C++20)
(until C++26)template<std::permutableI,std::sentinel_for<I>S,classProj=std::identity,classT=std::projected_value_t<I,Proj>>requiresstd::indirect_binary_predicate<ranges::equal_to,std::projected<I,Proj>,constT*>constexprranges::subrange<I>remove(Ifirst,Slast,constT&value,Projproj={});(since C++26)template<ranges::forward_rangeR,classT,classProj=std::identity>requiresstd::permutable<ranges::iterator_t<R>>&&std::indirect_binary_predicate<ranges::equal_to,std::projected<ranges::iterator_t<R>,Proj>,constT*>constexprranges::borrowed_subrange_t<R>remove(R&&r,constT&value,Projproj={}); (2)(since C++20)
(until C++26)template<ranges::forward_rangeR,classProj=std::identity,classT=std::projected_value_t<ranges::iterator_t<R>,Proj>>requiresstd::permutable<ranges::iterator_t<R>>&&std::indirect_binary_predicate<ranges::equal_to,std::projected<ranges::iterator_t<R>,Proj>,constT*>constexprranges::borrowed_subrange_t<R>remove(R&&r,constT&value,Projproj={});(since C++26)template<std::permutableI,std::sentinel_for<I>S,classProj=std::identity,std::indirect_unary_predicate<std::projected<I,Proj>>Pred>constexprranges::subrange<I>remove_if(Ifirst,Slast,Predpred,Projproj={}); (3)(since C++20)template<ranges::forward_rangeR,classProj=std::identity,std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>,Proj>>Pred>requiresstd::permutable<ranges::iterator_t<R>>constexprranges::borrowed_subrange_t<R>remove_if(R&&r,Predpred,Projproj={}); (4) (since C++20)template</*execution-policy*/Ep,std::random_access_iteratorI,std::sized_sentinel_for<I>S,classProj=std::identity,classT=std::projected_value_t<I,Proj>>requiresstd::permutable<I>&&std::indirect_binary_predicate<ranges::equal_to,std::projected<I,Proj>,constT*>ranges::subrange<I>remove(Ep&&policy,Ifirst,Slast,constT&value,Projproj={}); (5) (since C++26)template</*execution-policy*/Ep,/*sized-random-access-range*/R,classProj=std::identity,classT=std::projected_value_t<ranges::iterator_t<R>,Proj>>requiresstd::permutable<ranges::iterator_t<R>>&&std::indirect_binary_predicate<ranges::equal_to,std::projected<ranges::iterator_t<R>,Proj>,constT*>ranges::borrowed_subrange_t<R>remove(Ep&&policy,R&&r,constT&value,Projproj={}); (6) (since C++26)template</*execution-policy*/Ep,std::random_access_iteratorI,std::sized_sentinel_for<I>S,classProj=std::identity,std::indirect_unary_predicate<std::projected<I,Proj>>Pred>requiresstd::permutable<I>ranges::subrange<I>remove_if(Ep&&policy,Ifirst,Slast,Predpred,Projproj={}); (7) (since C++26)template</*execution-policy*/Ep,/*sized-random-access-range*/R,classProj=std::identity,std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>,Proj>>Pred>requiresstd::permutable<ranges::iterator_t<R>>ranges::borrowed_subrange_t<R>remove_if(Ep&&policy,R&&r,Predpred,Projproj={}); (8) (since C++26)For the definition of /*execution-policy*/, see

this page

; for the definition of /*sized-random-access-range*/, see

this page

.

“Removes” all elements (projected by proj) satisfying specific criteria from the target range [first, last) or r.

1,2)remove removes all elements that are equal to value (using operator==).

3,4)remove_if removes all elements for which predicate p returns true.

5-8) Same as (1-4), but executed according to policy.

Removing is done by partitioning the elements in the target range. Given the partition point result, all elements that are not to be removed appear before result, while other elements can only appear since result.

The underlying sequence of the target range is not shortened by the removing operation.

Elements are shifted by

move assignment

.

All iterators in the target range are still

dereferenceable

, and each element starting from result has a valid but unspecified state.

The removing operation is stable: the relative order of the elements not to be removed stays the same.

The function-like entities described on this page are

algorithm function objects

(informally known as niebloids), that is:

Explicit template argument lists cannot be specified when calling any of them.

None of them are visible to

argument-dependent lookup

.

When any of them are found by

normal unqualified lookup

as the name to the left of the function-call operator,

argument-dependent lookup

is inhibited.

Parameters

first, last - the iterator-sentinel pair defining the target

range

r - the target range value - the value of elements to remove pred - the predicate to be applied to the (projected) elements proj - the projection to be applied to the elements policy - the

execution policy

to use Return value

A subrange starting from the iterator result mentioned above and ends at the end of the target range.

Complexity

Given N as ranges::distance(first,last) or ranges::distance(r):

1,2) Exactly N comparisons with value using operator==, and the same number of applications of proj.

3,4) Exactly N applications of pred and proj.

5,6)𝓞(N) comparisons with value using operator==, and the same number of applications of proj.

7,8)𝓞(N) applications of pred and proj.

Exceptions

5-8) During the execution process:

If the temporary memory resources required for parallelization are not available,

std::bad_alloc

is thrown.

If an uncaught exception is thrown while accessing objects via an algorithm argument, the behavior is determined by the execution policy (for

standard policies

,

std::terminate

is invoked).

Notes

A call to ranges::remove or ranges::remove_if is typically followed by a call to a container's erase member function to actually remove elements from the container. These two invocations together constitute a so-called

erase-remove idiom

.

The same effect can also be achieved by the following non-member functions:

std::erase

, which has

overloads

for all standard sequence containers.

std::erase_if

, which has

overloads

for all standard containers.

The similarly-named container

member functions

list::remove

,

list::remove_if

,

forward_list::remove

, and

forward_list::remove_if

erase the removed elements.

These algorithms cannot be used with associative containers such as

std::set

and

std::map

because their iterator types do not dereference to

MoveAssignable

types (the keys in these containers are not modifiable).

Because ranges::remove takes value by reference, it can have unexpected behavior if it is a reference to an element of the target range.

Feature-test

macroValueStdFeature

__cpp_lib_algorithm_default_value_type

202403

(C++26)

List-initialization

for algorithms (

1,2

)Possible implementation

remove

structremove_fn{template<std::permutableI,std::sentinel_for<I>S,classProj=std::identity,classT=std::projected_value_t<I,Proj>>requiresstd::indirect_binary_predicate<ranges::equal_to,std::projected<I,Proj>,constT*>constexprranges::subrange<I>operator()(Ifirst,Slast,constT&value,Projproj={})const{first=ranges::find(std::move(first),last,value,proj);if(first!=last){for(Ii{std::next(first)};i!=last;++i)if(value!=std::invoke(proj,*i)){*first=ranges::iter_move(i);++first;}}return{first,last};}template<ranges::forward_rangeR,classProj=std::identity,classT=std::projected_value_t<ranges::iterator_t<R>,Proj>>requiresstd::permutable<ranges::iterator_t<R>>&&std::indirect_binary_predicate<ranges::equal_to,std::projected<ranges::iterator_t<R>,Proj>,constT*>constexprranges::borrowed_subrange_t<R>operator()(R&&r,constT&value,Projproj={})const{return(*this)(ranges::begin(r),ranges::next(ranges::begin(r),ranges::end(r)),value,std::move(proj));}};inlineconstexprremove_fnremove{};

remove_if

structremove_if_fn{template<std::permutableI,std::sentinel_for<I>S,classProj=std::identity,std::indirect_unary_predicate<std::projected<I,Proj>>Pred>constexprranges::subrange<I>operator()(Ifirst,Slast,Predpred,Projproj={})const{first=ranges::find_if(std::move(first),last,pred,proj);if(first!=last){for(Ii{std::next(first)};i!=last;++i)if(!std::invoke(pred,std::invoke(proj,*i))){*first=ranges::iter_move(i);++first;}}return{first,last};}template<ranges::forward_rangeR,classProj=std::identity,std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>,Proj>>Pred>requiresstd::permutable<ranges::iterator_t<R>>constexprranges::borrowed_subrange_t<R>operator()(R&&r,Predpred,Projproj={})const{return(*this)(ranges::begin(r),ranges::next(ranges::begin(r),ranges::end(r)),pred,std::move(proj));}};inlineconstexprremove_if_fnremove_if{};Example

Run this code

#include<algorithm>#include<cassert>#include<complex>#include<cctype>#include<iomanip>#include<iostream>#include<string>#include<string_view>#include<vector>intmain(){std::stringv1{"No - Diagnostic - Required"};std::cout<<std::quoted(v1)<<" (v1, size: "<<v1.size()<<")\n";constautoret=std::ranges::remove(v1,' ');std::cout<<std::quoted(v1)<<" (v1 after ‘remove’, size: "<<v1.size()<<")\n";std::cout<<' '<<std::string(std::distance(v1.begin(),ret.begin()),'^')<<'\n';v1.erase(ret.begin(),ret.end());std::cout<<std::quoted(v1)<<" (v1 after ‘erase’, size: "<<v1.size()<<")\n\n";// remove_if with custom unary predicate:autorm=[](charc){return!std::isupper(c);};std::stringv2{"Substitution Failure Is Not An Error"};std::cout<<std::quoted(v2)<<" (v2, size: "<<v2.size()<<")\n";constauto[first,last]=std::ranges::remove_if(v2,rm);std::cout<<std::quoted(v2)<<" (v2 after ‘remove_if’, size: "<<v2.size()<<")\n";std::cout<<' '<<std::string(std::distance(v2.begin(),first),'^')<<'\n';v2.erase(first,last);std::cout<<std::quoted(v2)<<" (v2 after ‘erase’, size: "<<v2.size()<<")\n\n";// creating a view into a container that is modified by ‘remove_if’:for(std::strings:{"Small Object Optimization","Non-Type Template Parameter"})std::cout<<std::quoted(s)<<" => "<<std::string_view{begin(s),std::ranges::remove_if(s,rm).begin()}<<'\n';std::vector<std::complex<double>>nums{{2,2},{1,3},{4,8}};#ifdef __cpp_lib_algorithm_default_value_typeautoe=std::ranges::remove(nums,{1,3});// T gets deduced#elseautoe=std::ranges::remove(nums,std::complex<double>{1,3});#endifnums.erase(e.begin(),e.end());assert((nums==std::vector<std::complex<double>>{{2,2},{4,8}}));}Possible output:

"No _ Diagnostic _ Required" (v1, size: 26) "No_Diagnostic_Requiredired" (v1 after ‘remove’, size: 26) ^^^^^^^^^^^^^^^^^^^^^^ "No_Diagnostic_Required" (v1 after ‘erase’, size: 22) "Substitution Failure Is Not An Error" (v2, size: 36) "SFINAEtution Failure Is Not An Error" (v2 after ‘remove_if’, size: 36) ^^^^^^ "SFINAE" (v2 after ‘erase’, size: 6) "Small Object Optimization" => SOO "Non-Type Template Parameter" => NTTP See also