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

Defined in header

<algorithm>

template<classForwardIt,classT>ForwardItremove(ForwardItfirst,ForwardItlast,constT&value); (1)(constexpr since C++20)
(until C++26)template<classForwardIt,classT=typenamestd::iterator_traits<ForwardIt>::value_type>constexprForwardItremove(ForwardItfirst,ForwardItlast,constT&value);(since C++26)template<classForwardIt,classUnaryPred>ForwardItremove_if(ForwardItfirst,ForwardItlast,UnaryPredp); (2)(constexpr since C++20)template<classExecutionPolicy,classForwardIt,classT>ForwardItremove(ExecutionPolicy&&policy,ForwardItfirst,ForwardItlast,constT&value); (3)(since C++17)
(until C++26)template<classExecutionPolicy,classForwardIt,classT=typenamestd::iterator_traits<ForwardIt>::value_type>ForwardItremove(ExecutionPolicy&&policy,ForwardItfirst,ForwardItlast,constT&value);(since C++26)template<classExecutionPolicy,classForwardIt,classUnaryPred>ForwardItremove_if(ExecutionPolicy&&policy,ForwardItfirst,ForwardItlast,UnaryPredp); (4) (since C++17)“Removes” all elements satisfying specific criteria from the target range [first, last).

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

2)remove_if removes all elements for which predicate p returns true.

3,4) Same as (1,2), but executed according to policy.

These overloads participate in overload resolution only if the value of the following expression is true:

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>

(until C++20)std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>

(since C++20)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 in [first, result), while other elements can only appear in [result, last).

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

Elements are shifted by

copy assignment

(until C++11)

move assignment

(since C++11).

All iterators in [result, last) are still

dereferenceable

, and each element of [result, last) has a valid but unspecified state(since C++11).

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

Parameters

first, last - the pair of iterators defining the target

range

value - the value of elements to remove p - unary predicate which returns ​true if the element should be removed. The expression p(v) must be convertible to bool for every argument v of type (possibly const) VT, where VT is the value type of ForwardIt, regardless of

value category

, and must not modify v. Thus, a parameter type of VT&is not allowed, nor is VT unless for VT a move is equivalent to a copy(since C++11). ​

policy - the

execution policy

to use Type requirements -ForwardIt must meet the requirements of

LegacyForwardIterator

. -UnaryPredicate must meet the requirements of

Predicate

. Return value

The iterator result mentioned above.

Complexity

Given N as std::distance(first,last):

1) Exactly N comparisons using operator==.

2) Exactly N applications of the predicate p.

3)𝓞(N) comparisons using operator==.

4)𝓞(N) applications of the predicate p.

Exceptions

3,4) 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 remove or 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.

(since C++20)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).

The standard library also defines an overload of

std::remove

in

<cstdio>

, which takes a constchar* and is used to delete files.

Because std::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,3

)Possible implementation

remove

template<classForwardIt,classT=typenamestd::iterator_traits<ForwardIt>::value_type>ForwardItremove(ForwardItfirst,ForwardItlast,constT&value){first=std::find(first,last,value);if(first!=last)for(ForwardIti=first;++i!=last;)if(!(*i==value))*first++=std::move(*i);returnfirst;}

remove_if

template<classForwardIt,classUnaryPred>ForwardItremove_if(ForwardItfirst,ForwardItlast,UnaryPredp){first=std::find_if(first,last,p);if(first!=last)for(ForwardIti=first;++i!=last;)if(!p(*i))*first++=std::move(*i);returnfirst;}Example

The following code removes all spaces from a string by shifting all non-space characters to the left and then erasing the extra. This is an example of

erase-remove idiom

.

Run this code

#include<algorithm>#include<cassert>#include<cctype>#include<complex>#include<iomanip>#include<iostream>#include<string>#include<string_view>#include<vector>intmain(){std::stringstr1{"Quick Red Dog"};std::cout<<"1) "<<std::quoted(str1)<<'\n';constautonoSpaceEnd=std::remove(str1.begin(),str1.end(),' ');std::cout<<"2) "<<std::quoted(str1)<<'\n';// The spaces are removed from the string only logically.// Note, we use view, the original string is still not shrunk:std::cout<<"3) "<<std::quoted(std::string_view(str1.begin(),noSpaceEnd))<<", size: "<<str1.size()<<'\n';str1.erase(noSpaceEnd,str1.end());// The spaces are removed from the string physically.std::cout<<"4) "<<std::quoted(str1)<<", size: "<<str1.size()<<'\n';std::stringstr2="Jumped\n Over\tA\vLazy \t Fox\r\n";str2.erase(std::remove_if(str2.begin(),str2.end(),[](unsignedcharx){returnstd::isspace(x);}),str2.end());std::cout<<"5) "<<std::quoted(str2)<<'\n';std::vector<std::complex<double>>nums{{2,2},{1,3},{4,8}};#ifdef __cpp_lib_algorithm_default_value_typenums.erase(std::remove(nums.begin(),nums.end(),{1,3}),nums.end());#elsenums.erase(std::remove(nums.begin(),nums.end(),std::complex<double>{1,3}),nums.end());#endifassert((nums==std::vector<std::complex<double>>{{2,2},{4,8}}));}Output:

1) "Quick Red Dog" 2) "QuickRedDog Dog" 3) "QuickRedDog", size: 15 4) "QuickRedDog", size: 11 5) "JumpedOverALazyFox" Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior

LWG 283

C++98 T was required to be

EqualityComparable

, but
the value type of ForwardIt is not always Trequired the value type of ForwardIt
to be

CopyAssignable

instead See also