Constrained algorithms and algorithms on ranges(C++20) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Constrained algorithms, e.g.ranges::copy,ranges::sort, ... | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Execution policies(C++17) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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=typenamestd::iterator_traits <ForwardIt>::value_type> | (since C++26) | |
(2) | ||
template<class ExecutionPolicy,class ForwardIt,class T> ForwardIt remove( ExecutionPolicy&& policy, | (since C++17) (until C++26) | |
template<class ExecutionPolicy,class ForwardIt, class T=typenamestd::iterator_traits | (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, | (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.
std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> istrue. | (until C++20) |
std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> istrue. | (since C++20) |
If thevalue type of | (until C++11) |
If the type of*first is notMoveAssignable, the behavior is undefined. | (since C++11) |
Contents |
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.
[
first,
last)
is not shortened by the removing operation. Givenresult as the returned iterator:[
result,
last)
are stilldereferenceable.
| (since C++11) |
first, last | - | the pair of iterators defining therange of elements to process |
value | - | the value of elements to remove |
policy | - | theexecution policy to use |
p | - | unary predicate which returns true if the element should be removed. The expressionp(v) must be convertible tobool for every argument |
Type requirements | ||
-ForwardIt must meet the requirements ofLegacyForwardIterator. | ||
-UnaryPredicate must meet the requirements ofPredicate. |
Past-the-end iterator for the new range of values (if this is notend, then it points to an unspecified value, and so do iterators to any values between this iterator andend).
Given\(\scriptsize N\)N asstd::distance(first, last):
The overloads with a template parameter namedExecutionPolicy
report errors as follows:
ExecutionPolicy
is one of thestandard policies,std::terminate is called. For any otherExecutionPolicy
, the behavior is implementation-defined.remove (1) |
---|
template<class ForwardIt,class T=typenamestd::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;} |
A call toremove
is typically followed by a call to a container'serase
member function to actually remove elements from the container. These two invocations together constitute a so-callederase-remove idiom.
The same effect can also be achieved by the following non-member functions:
| (since C++20) |
The similarly-named containermember functionslist::remove,list::remove_if,forward_list::remove, andforward_list::remove_if erase the removed elements.
These algorithms cannot be used with associative containers such asstd::set andstd::map because their iterator types do not dereference toMoveAssignable types (the keys in these containers are not modifiable).
The standard library also defines an overload ofstd::remove in<cstdio>, which takes aconstchar* and is used to delete files.
Becausestd::remove
takesvalue 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) |
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 oferase-remove idiom.
#include <algorithm>#include <cassert>#include <cctype>#include <complex>#include <iomanip>#include <iostream>#include <string>#include <string_view>#include <vector> int main(){std::string str1{"Quick Red Dog"};std::cout<<"1) "<<std::quoted(str1)<<'\n';constauto noSpaceEnd= 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::string str2="Jumped\n Over\tA\vLazy\t Fox\r\n"; str2.erase(std::remove_if(str2.begin(), str2.end(),[](unsignedchar x){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_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());#endifassert((nums==std::vector<std::complex<double>>{{2,2},{4,8}}));}
Output:
1) "Quick Red Dog"2) "QuickRedDog Dog"3) "QuickRedDog", size: 154) "QuickRedDog", size: 115) "JumpedOverALazyFox"
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 beEqualityComparable, butthe value type of ForwardIt is not alwaysT | required the value type ofForwardIt to beCopyAssignable instead |
copies a range of elements omitting those that satisfy specific criteria (function template)[edit] | |
removes consecutive duplicate elements in a range (function template)[edit] | |
(C++20)(C++20) | removes elements satisfying specific criteria (algorithm function object)[edit] |