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 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
std::ranges
Non-modifying sequence operations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Modifying sequence operations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Partitioning operations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sorting operations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Binary search operations (on sorted ranges) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Set operations (on sorted ranges) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Heap operations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Minimum/maximum operations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Permutation operations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Fold operations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Operations on uninitialized storage | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Return types | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Defined in header <algorithm> | ||
Call signature | ||
(1) | ||
template<std::forward_iterator I,std::sentinel_for<I> S, class T, | (since C++23) (until C++26) | |
template<std::forward_iterator I,std::sentinel_for<I> S, class Proj=std::identity, | (since C++26) | |
(2) | ||
template<ranges::forward_range R, class T, | (since C++23) (until C++26) | |
template<ranges::forward_range R, class Proj=std::identity, | (since C++26) | |
template<std::forward_iterator I,std::sentinel_for<I> S, class Proj=std::identity, | (3) | (since C++23) |
template<ranges::forward_range R, class Proj=std::identity, | (4) | (since C++23) |
template<std::forward_iterator I,std::sentinel_for<I> S, class Proj=std::identity, | (5) | (since C++23) |
template<ranges::forward_range R, class Proj=std::identity, | (6) | (since C++23) |
Returns the last element in the range[
first,
last)
that satisfies specific criteria:
find_last
searches for an element equal tovalue.find_last_if
searches for the last element in the range[
first,
last)
for which predicatepred returnstrue.find_last_if_not
searches for the last element in the range[
first,
last)
for which predicatepred returnsfalse.The function-like entities described on this page arealgorithm function objects (informally known asniebloids), that is:
Contents |
first, last | - | the iterator-sentinel pair defining therange of elements to examine |
r | - | the range of the elements to examine |
value | - | value to compare the elements to |
pred | - | predicate to apply to the projected elements |
proj | - | projection to apply to the elements |
[
first,
last)
for whichE istrue.At mostlast- first applications of the predicate and projection.
ranges::find_last
,ranges::find_last_if
,ranges::find_last_if_not
have better efficiency on common implementations ifI
modelsbidirectional_iterator
or (better)random_access_iterator
.
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_lib_ranges_find_last | 202207L | (C++23) | ranges::find_last ,ranges::find_last_if ,ranges::find_last_if_not |
__cpp_lib_algorithm_default_value_type | 202403L | (C++26) | List-initialization for algorithms(1,2) |
These implementations only show the slower algorithm used whenI modelsforward_iterator
.
find_last (1,2) |
---|
struct find_last_fn{template<std::forward_iterator I,std::sentinel_for<I> S,class Proj=std::identity,class T= std::projected_value_t<iterator_t<R>, Proj>> requiresstd::indirect_binary_predicate<ranges::equal_to, std::projected<I, Proj>,const T*>constexprranges::subrange<I> operator()(I first, S last,const T&value, Proj proj={})const{// Note: if I is mere forward_iterator, we may only go from begin to end.std::optional<I> found;for(; first!= last;++first)if(std::invoke(proj,*first)== value) found= first; if(!found)return{first, first}; return{*found, std::ranges::next(*found, last)};} template<ranges::forward_range R,class Proj=std::identity,class T= std::projected_value_t<iterator_t<R>, Proj>> requiresstd::indirect_binary_predicate<ranges::equal_to, std::projected<ranges::iterator_t<R>, Proj>,const T*>constexprranges::borrowed_subrange_t<R> operator()(R&& r,const T&value, Proj proj={})const{return this->operator()(ranges::begin(r),ranges::end(r), value,std::ref(proj));}}; inlineconstexpr find_last_fn find_last; |
find_last_if (3,4) |
struct find_last_if_fn{template<std::forward_iterator I,std::sentinel_for<I> S,class Proj=std::identity,std::indirect_unary_predicate<std::projected<I, Proj>> Pred>constexprranges::subrange<I> operator()(I first, S last, Pred pred, Proj proj={})const{// Note: if I is mere forward_iterator, we may only go from begin to end.std::optional<I> found;for(; first!= last;++first)if(std::invoke(pred,std::invoke(proj,*first))) found= first; if(!found)return{first, first}; return{*found, std::ranges::next(*found, last)};} template<ranges::forward_range R,class Proj=std::identity,std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>> Pred>constexprranges::borrowed_subrange_t<R> operator()(R&& r, Pred pred, Proj proj={})const{return this->operator()(ranges::begin(r),ranges::end(r),std::ref(pred),std::ref(proj));}}; inlineconstexpr find_last_if_fn find_last_if; |
find_last_if_not (5,6) |
struct find_last_if_not_fn{template<std::forward_iterator I,std::sentinel_for<I> S,class Proj=std::identity,std::indirect_unary_predicate<std::projected<I, Proj>> Pred>constexprranges::subrange<I> operator()(I first, S last, Pred pred, Proj proj={})const{// Note: if I is mere forward_iterator, we may only go from begin to end.std::optional<I> found;for(; first!= last;++first)if(!std::invoke(pred,std::invoke(proj,*first))) found= first; if(!found)return{first, first}; return{*found, std::ranges::next(*found, last)};} template<ranges::forward_range R,class Proj=std::identity,std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>> Pred>constexprranges::borrowed_subrange_t<R> operator()(R&& r, Pred pred, Proj proj={})const{return this->operator()(ranges::begin(r),ranges::end(r),std::ref(pred),std::ref(proj));}}; inlineconstexpr find_last_if_not_fn find_last_if_not; |
#include <algorithm>#include <cassert>#include <forward_list>#include <iomanip>#include <iostream>#include <string_view> int main(){namespace ranges= std::ranges; constexprstaticauto v={1,2,3,1,2,3,1,2}; {constexprauto i1= ranges::find_last(v.begin(), v.end(),3);constexprauto i2= ranges::find_last(v,3); static_assert(ranges::distance(v.begin(), i1.begin())==5); static_assert(ranges::distance(v.begin(), i2.begin())==5);}{constexprauto i1= ranges::find_last(v.begin(), v.end(),-3);constexprauto i2= ranges::find_last(v,-3); static_assert(i1.begin()== v.end()); static_assert(i2.begin()== v.end());} auto abs=[](int x){return x<0?-x: x;}; {auto pred=[](int x){return x==3;};constexprauto i1= ranges::find_last_if(v.begin(), v.end(), pred, abs);constexprauto i2= ranges::find_last_if(v, pred, abs); static_assert(ranges::distance(v.begin(), i1.begin())==5); static_assert(ranges::distance(v.begin(), i2.begin())==5);}{auto pred=[](int x){return x==-3;};constexprauto i1= ranges::find_last_if(v.begin(), v.end(), pred, abs);constexprauto i2= ranges::find_last_if(v, pred, abs); static_assert(i1.begin()== v.end()); static_assert(i2.begin()== v.end());} {auto pred=[](int x){return x==1 or x==2;};constexprauto i1= ranges::find_last_if_not(v.begin(), v.end(), pred, abs);constexprauto i2= ranges::find_last_if_not(v, pred, abs); static_assert(ranges::distance(v.begin(), i1.begin())==5); static_assert(ranges::distance(v.begin(), i2.begin())==5);}{auto pred=[](int x){return x==1 or x==2 or x==3;};constexprauto i1= ranges::find_last_if_not(v.begin(), v.end(), pred, abs);constexprauto i2= ranges::find_last_if_not(v, pred, abs); static_assert(i1.begin()== v.end()); static_assert(i2.begin()== v.end());} using P=std::pair<std::string_view,int>;std::forward_list<P> list{{"one",1},{"two",2},{"three",3},{"one",4},{"two",5},{"three",6},};auto cmp_one=[](conststd::string_view&s){return s=="one";}; // find latest element that satisfy the comparator, and projecting pair::firstconstauto subrange= ranges::find_last_if(list, cmp_one,&P::first); std::cout<<"The found element and the tail after it are:\n";for(Pconst& e: subrange)std::cout<<'{'<<std::quoted(e.first)<<", "<< e.second<<"} ";std::cout<<'\n'; #if __cpp_lib_algorithm_default_value_typeconstauto i3= ranges::find_last(list,{"three",3});// (2) C++26#elseconstauto i3= ranges::find_last(list, P{"three",3});// (2) C++23#endifassert(i3.begin()->first=="three"&& i3.begin()->second==3);}
Output:
The found element and the tail after it are:{"one", 4} {"two", 5} {"three", 6}
(C++20) | finds the last sequence of elements in a certain range (algorithm function object)[edit] |
(C++20)(C++20)(C++20) | finds the first element satisfying specific criteria (algorithm function object)[edit] |
(C++20) | searches for the first occurrence of a range of elements (algorithm function object)[edit] |
(C++20) | returnstrue if one sequence is a subsequence of another (algorithm function object)[edit] |
(C++20) | determines if an element exists in a partially-ordered range (algorithm function object)[edit] |
(C++23)(C++23) | checks if the range contains the given element or subrange (algorithm function object)[edit] |