std:: remove, std:: remove_if

From cppreference.com
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
remove remove_if
Order-changing operations
(until C++17) (C++11)
(C++20) (C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
Defined in header <algorithm>
(1)
template < class ForwardIt, class T >
ForwardIt remove ( ForwardIt first, ForwardIt last, const T & value ) ;
(constexpr since C++20)
(until C++26)
template < class ForwardIt, class T = typename std:: iterator_traits

< ForwardIt > :: value_type >
constexpr ForwardIt remove ( ForwardIt first, ForwardIt last,

const T & value ) ;
(since C++26)
(2)
template < class ExecutionPolicy, class ForwardIt, class T >

ForwardIt remove ( ExecutionPolicy && policy,

ForwardIt first, ForwardIt last, const T & value ) ;
(since C++17)
(until C++26)
template < class ExecutionPolicy, class ForwardIt,

class T = typename std:: iterator_traits
< ForwardIt > :: value_type >
ForwardIt remove ( ExecutionPolicy && policy,

ForwardIt first, ForwardIt last, const T & value ) ;
(since C++26)
template < class ForwardIt, class UnaryPred >
ForwardIt remove_if ( ForwardIt first, ForwardIt last, UnaryPred p ) ;
(3) (constexpr since C++20)
template < class ExecutionPolicy, class ForwardIt, class UnaryPred >

ForwardIt remove_if ( ExecutionPolicy && policy,

ForwardIt first, ForwardIt last, UnaryPred p ) ;
(4) (since C++17)

Removes all elements satisfying specific criteria from the range [ first , last ) and returns a past-the-end iterator for the new end of the range.

1) Removes all elements that are equal to value (using operator == ).
3) Removes all elements for which predicate p returns true .
2,4) Same as (1,3) , but executed according to policy .
These overloads participate in overload resolution only if

std:: is_execution_policy_v < std:: decay_t < ExecutionPolicy >> is true .

(until C++20)

std:: is_execution_policy_v < std:: remove_cvref_t < ExecutionPolicy >> is true .

(since C++20)


If the value type of ForwardIt is not CopyAssignable , the behavior is undefined.

(until C++11)

If the type of * first is not MoveAssignable , the behavior is undefined.

(since C++11)

Explanation

Removing is done by shifting the elements in the range in such a way that the elements that are not to be removed appear in the beginning of the range.

  • Shifting is done by copy assignment (until C++11) move assignment (since C++11) .
  • The removing operation is stable: the relative order of the elements not to be removed stays the same.
  • The underlying sequence of [ first , last ) is not shortened by the removing operation. Given result as the returned iterator:
  • Each element of [ result , last ) has a valid but unspecified state, because move assignment can eliminate elements by moving from elements that were originally in that range.
(since C++11)

Parameters

first, last - the range of elements to process
value - the value of elements to remove
policy - the execution policy to use. See execution policy for details.
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) . ​

Type requirements
-
ForwardIt must meet the requirements of LegacyForwardIterator .
-
UnaryPredicate must meet the requirements of Predicate .

Return value

Past-the-end iterator for the new range of values (if this is not end , then it points to an unspecified value, and so do iterators to any values between this iterator and end ).

Complexity

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

1,2) Exactly N comparisons using operator == .
3,4) Exactly N applications of the predicate p .

Exceptions

The overloads with a template parameter named ExecutionPolicy report errors as follows:

  • If execution of a function invoked as part of the algorithm throws an exception and ExecutionPolicy is one of the standard policies , std::terminate is called. For any other ExecutionPolicy , the behavior is implementation-defined.
  • If the algorithm fails to allocate memory, std::bad_alloc is thrown.

Possible implementation

remove (1)
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type>
ForwardIt remove(ForwardIt first, ForwardIt last, const T& value)
{
    first = std::find(first, last, value);
    if (first != last)
        for (ForwardIt i = first; ++i != last;)
            if (!(*i == value))
                *first++ = std::move(*i);
    return first;
}
remove_if (3)
template<class ForwardIt, class UnaryPred>
ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPred p)
{
    first = std::find_if(first, last, p);
    if (first != last)
        for (ForwardIt i = first; ++i != last;)
            if (!p(*i))
                *first++ = std::move(*i);
    return first;
}

Notes

A call to remove 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:

(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 const char * 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 range [ first , last ) .

Feature-test macro Value Std Feature
__cpp_lib_algorithm_default_value_type 202403 (C++26) List-initialization for algorithms ( 1,2 )

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 .

#include <algorithm>
#include <cassert>
#include <cctype>
#include <complex>
#include <iostream>
#include <string>
#include <string_view>
#include <vector>
 
int main()
{
    std::string str1{"Text with some   spaces"};
 
    auto noSpaceEnd = std::remove(str1.begin(), str1.end(), ' ');
 
    // The spaces are removed from the string only logically.
    // Note, we use view, the original string is still not shrunk:
    std::cout << 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 << str1 << " size: " << str1.size() << '\n';
 
    std::string str2 = "Text\n with\tsome \t  whitespaces\n\n";
    str2.erase(std::remove_if(str2.begin(), 
                              str2.end(),
                              [](unsigned char x) { return std::isspace(x); }),
               str2.end());
    std::cout << str2 << '\n';
 
    std::vector<std::complex<double>> nums{{2, 2}, {1, 3}, {4, 8}};
    #ifdef __cpp_lib_algorithm_default_value_type
        nums.erase(std::remove(nums.begin(), nums.end(), {1, 3}), nums.end());
    #else
        nums.erase(std::remove(nums.begin(), nums.end(), std::complex<double>{1, 3}),
                   nums.end());
    #endif
    assert((nums == std::vector<std::complex<double>>{{2, 2}, {4, 8}}));
}

Output:

Textwithsomespaces size: 23
Textwithsomespaces size: 18
Textwithsomewhitespaces

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 T
required the value type of ForwardIt
to be CopyAssignable instead

See also

copies a range of elements omitting those that satisfy specific criteria
(function template)
removes consecutive duplicate elements in a range
(function template)
removes elements satisfying specific criteria
(algorithm function object)