std::ranges::transform, std::ranges::unary_transform_result, std::ranges::binary_transform_result - cppreference.com

Defined in header

<algorithm>

Call signature

template<std::input_iteratorI,std::sentinel_for<I>S,std::weakly_incrementableO,std::copy_constructibleF,classProj=std::identity>requiresstd::indirectly_writable<O,std::indirect_result_t<F&,std::projected<I,Proj>>>constexprranges::unary_transform_result<I,O>transform(Ifirst1,Slast1,Od_first,Funary_op,Projproj1={}); (1) (since C++20)template<ranges::input_rangeR,std::weakly_incrementableO,std::copy_constructibleF,classProj=std::identity>requiresstd::indirectly_writable<O,std::indirect_result_t<F&,std::projected<ranges::iterator_t<R>,Proj>>>constexprranges::unary_transform_result<ranges::borrowed_iterator_t<R>,O>transform(R&&r1,Od_first,Funary_op,Projproj1={}); (2) (since C++20)template<std::input_iteratorI1,std::sentinel_for<I1>S1,std::input_iteratorI2,std::sentinel_for<I2>S2,std::weakly_incrementableO,std::copy_constructibleF,classProj1=std::identity,classProj2=std::identity>requiresstd::indirectly_writable<O,std::indirect_result_t<F&,std::projected<I1,Proj1>,std::projected<I2,Proj2>>>constexprranges::binary_transform_result<I1,I2,O>transform(I1first1,S1last1,I2first2,S2last2,Od_first,Fbinary_op,Proj1proj1={},Proj2proj2={}); (3) (since C++20)template<ranges::input_rangeR1,ranges::input_rangeR2,std::weakly_incrementableO,std::copy_constructibleF,classProj1=std::identity,classProj2=std::identity>requiresstd::indirectly_writable<O,std::indirect_result_t<F&,std::projected<ranges::iterator_t<R1>,Proj1>,std::projected<ranges::iterator_t<R2>,Proj2>>>constexprranges::binary_transform_result<ranges::borrowed_iterator_t<R1>,ranges::borrowed_iterator_t<R2>,O>transform(R1&&r1,R2&&r2,Od_first,Fbinary_op,Proj1proj1={},Proj2proj2={}); (4) (since C++20)template</*execution-policy*/Ep,std::random_access_iteratorI,std::sized_sentinel_for<I>S,std::random_access_iteratorO,std::sized_sentinel_for<O>OutS,std::copy_constructibleF,classProj=std::identity>requiresstd::indirectly_writable<O,std::indirect_result_t<F&,std::projected<I,Proj>>>ranges::unary_transform_result<I,O>transform(Ep&&policy,Ifirst1,Slast1,Od_first,OutSd_last,Funary_op,Projproj1={}); (5) (since C++26)template</*execution-policy*/Ep,/*sized-random-access-range*/R,/*sized-random-access-range*/OutR,std::copy_constructibleF,classProj=std::identity>requiresstd::indirectly_writable<ranges::iterator_t<OutR>,std::indirect_result_t<F&,std::projected<ranges::iterator_t<R>,Proj>>>ranges::unary_transform_result<ranges::borrowed_iterator_t<R>,ranges::borrowed_iterator_t<OutR>>transform(Ep&&policy,R&&r1,OutR&&d_r,Funary_op,Projproj1={}); (6) (since C++26)template</*execution-policy*/Ep,std::random_access_iteratorI1,std::sized_sentinel_for<I1>S1,std::random_access_iteratorI2,std::sized_sentinel_for<I2>S2,std::random_access_iteratorO,std::sized_sentinel_for<O>OutS,std::copy_constructibleF,classProj1=std::identity,classProj2=std::identity>requiresstd::indirectly_writable<O,std::indirect_result_t<F&,std::projected<I1,Proj1>,std::projected<I2,Proj2>>>ranges::binary_transform_result<I1,I2,O>transform(Ep&&policy,I1first1,S1last1,I2first2,S2last2,Od_first,OutSd_last,Fbinary_op,Proj1proj1={},Proj2proj2={}); (7) (since C++26)template</*execution-policy*/Ep,/*sized-random-access-range*/R1,sized-random-access-range*/R2,/*sized-random-access-range*/OutR,std::copy_constructibleF,classProj1=std::identity,classProj2=std::identity>requiresstd::indirectly_writable<ranges::iterator_t<OutR>,std::indirect_result_t<F&,std::projected<ranges::iterator_t<R1>,Proj1>,std::projected<ranges::iterator_t<R2>,Proj2>>>ranges::binary_transform_result<ranges::borrowed_iterator_t<R1>,ranges::borrowed_iterator_t<R2>,ranges::borrowed_iterator_t<OutR>>transform(Ep&&policy,R1&&r1,R2&&r2,OutR&&d_r,Fbinary_op,Proj1proj1={},Proj2proj2={}); (8) (since C++26)Helper types

template<classI,classO>usingunary_transform_result=ranges::in_out_result<I,O>; (9) (since C++20)template<classI1,classI2,classO>usingbinary_transform_result=ranges::in_in_out_result<I1,I2,O>; (10) (since C++20)For the definition of /*execution-policy*/, see

this page

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

this page

.

Applies the given function to the (projected) elements of the given source range(s), and stores the result in the destination range.

1-4) The destination range is [d_first, ranges::next(d_first,count)), where count is defined below.

1,2) There is only one source range, and the unary operation unary_op is applied to each of its elements (projected by proj1).

1) The source range is [first1, last1), and count is ranges::distance(first1,last1).

2) The source range is r1, and count is ranges::distance(r1).

3,4) There are two source ranges, and the binary operation binary_op is applied to each pair of their corresponding elements (projected by proj1 and proj2 respectively).

3) The two source ranges are [first1, last1) and [first2, last2), and count is the lesser of ranges::distance(first1,last1) and ranges::distance(first2,last2).

4) The two source ranges are r1 and r2, and count is the lesser of ranges::distance(r1) and ranges::distance(r2).

5-8) Same as (1-4), but executed according to policy, and the destination range is [d_first, d_last) or d_r. If the destination range is exhausted before reaching the end of any source range, the remaining elements in the source range(s) will not be transformed.

If unary_op or binary_op invalidates an iterator or subrange, or modifies an element in any of the following ranges, the behavior is undefined:

[first1, last1]

[r1.begin(), ranges::next(r1.begin(),r1.end())]

[first2, last2]

[r2.begin(), ranges::next(r2.begin(),r2.end())]

[d_first, ranges::next(d_first,count)] (count is defined above)

[d_first, d_last]

[d_r.begin(), ranges::next(d_r.begin(),d_r.end())]

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

first1, last1 - the iterator-sentinel pair defining the first source

range

r1 - the first source range first2, last2 - the iterator-sentinel pair defining the second source

range

r2 - the second source range d_first - the beginning of the destination range d_last - the sentinel of the destination range d_r - the destination range unary_op, binary_op - operation to apply to the projected element(s) proj1 - the projection to be applied to the elements in the first source range proj2 - the projection to be applied to the elements in the second source range policy - the

execution policy

to use Return value

1,2,5,6) A ranges::unary_transform_result object where:

The data member

in

holds an iterator past the last transformed element in the source range, or an iterator to the beginning of the source range if no element is transformed.

The data member

out

holds an iterator past the last assigned element in the destination range, or an iterator to the beginning of the destination range if no element is transformed.

3,4,7,8) A ranges::binary_transform_result object where:

The data member

in1

holds an iterator past the last transformed element in the first source range, or an iterator to the beginning of the first source range if no element is transformed.

The data member

in2

holds an iterator past the last transformed element in the second source range, or an iterator to the beginning of the second source range if no element is transformed.

The data member

out

holds an iterator past the last assigned element in the destination range, or an iterator to the beginning of the destination range if no element is transformed.

Complexity

Given

N1 as ranges::distance(first1,last1) or ranges::distance(r1),

N2 as ranges::distance(first2,last2) or ranges::distance(r2), and

N3 as ranges::distance(d_first,d_last) or ranges::distance(d_r):

1,2) Exactly N1 applications of unary_op and proj1.

3,4) Exactly min(N1,N2) applications of binary_op, proj1 and proj2.

5,6)𝓞(min(N1,N3)) applications of unary_op and proj1.

7,8)𝓞(min(N1,N2,N3)) applications of binary_op, proj1 and proj2.

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

ranges::transform does not guarantee in-order application of unary_op or binary_op. To apply a function to a sequence in-order or to apply a function that modifies the elements of a sequence, use

ranges::for_each

.

Possible implementation

structtransform_fn{// First versiontemplate<std::input_iteratorI,std::sentinel_for<I>S,std::weakly_incrementableO,std::copy_constructibleF,classProj=std::identity>requiresstd::indirectly_writable<O,std::indirect_result_t<F&,std::projected<I,Proj>>>constexprranges::unary_transform_result<I,O>operator()(Ifirst1,Slast1,Od_first,Funary_op,Projproj1={})const{for(;first1!=last1;++first1,(void)++result)*result=std::invoke(unary_op,std::invoke(proj1,*first1));return{std::move(first1),std::move(d_first)};}template<ranges::input_rangeR>constexprautoget_end(R&&r){returnranges::end(r);}template<ranges::forward_rangeR>constexprautoget_end(R&&r){returnranges::next(ranges::begin(r),ranges::end(r));}// Second versiontemplate<ranges::input_rangeR,std::weakly_incrementableO,std::copy_constructibleF,classProj=std::identity>requiresstd::indirectly_writable<O,std::indirect_result_t<F&,std::projected<ranges::iterator_t<R>,Proj>>>constexprranges::unary_transform_result<ranges::borrowed_iterator_t<R>,O>operator()(R&&r1,Od_first,Funary_op,Projproj1={})const{return(*this)(ranges::begin(r1),get_end(r1),std::move(d_first),std::move(unary_op),std::move(proj1));}// Third versiontemplate<std::input_iteratorI1,std::sentinel_for<I1>S1,std::input_iteratorI2,std::sentinel_for<I2>S2,std::weakly_incrementableO,std::copy_constructibleF,classProj1=std::identity,classProj2=std::identity>requiresstd::indirectly_writable<O,std::indirect_result_t<F&,std::projected<I1,Proj1>,std::projected<I2,Proj2>>>constexprranges::binary_transform_result<I1,I2,O>operator()(I1first1,S1last1,I2first2,S2last2,Od_first,Fbinary_op,Proj1proj1={},Proj2proj2={})const{for(;first1!=last1&&first2!=last2;++first1,(void)++first2,(void)++result)*result=std::invoke(binary_op,std::invoke(proj1,*first1),std::invoke(proj2,*first2));return{std::move(first1),std::move(first2),std::move(d_first)};}// Fourth versiontemplate<ranges::input_rangeR1,ranges::input_rangeR2,std::weakly_incrementableO,std::copy_constructibleF,classProj1=std::identity,classProj2=std::identity>requiresstd::indirectly_writable<O,std::indirect_result_t<F&,std::projected<ranges::iterator_t<R1>,Proj1>,std::projected<ranges::iterator_t<R2>,Proj2>>>constexprranges::binary_transform_result<ranges::borrowed_iterator_t<R1>,ranges::borrowed_iterator_t<R2>,O>operator()(R1&&r1,R2&&r2,Od_first,Fbinary_op,Proj1proj1={},Proj2proj2={})const{return(*this)(ranges::begin(r1),get_end(r1),ranges::begin(r2),get_end(r2),std::move(d_first),std::move(binary_op),std::move(proj1),std::move(proj2));}};inlineconstexprtransform_fntransform;Example

The following code uses ranges::transform to convert a string in place to uppercase using the std::toupper function and then transforms each char to its ordinal value. Then ranges::transform with a projection is used to transform elements of std::vector<Foo> into chars to fill a

std::string

.

Run this code

#include<algorithm>#include<cctype>#include<functional>#include<iostream>#include<string>#include<vector>intmain(){std::strings{"hello"};autoop=[](unsignedcharc)->unsignedchar{returnstd::toupper(c);};namespaceranges=std::ranges;// uppercase the string in-placeranges::transform(s.begin(),s.end(),s.begin(),op);std::vector<std::size_t>ordinals;// convert each char to size_tranges::transform(s,std::back_inserter(ordinals),[](unsignedcharc)->std::size_t{returnc;});std::cout<<s<<':';for(autoord:ordinals)std::cout<<' '<<ord;// double each ordinalranges::transform(ordinals,ordinals,ordinals.begin(),std::plus{});std::cout<<'\n';for(autoord:ordinals)std::cout<<ord<<' ';std::cout<<'\n';structFoo{charbar;};conststd::vector<Foo>f={{'h'},{'e'},{'l'},{'l'},{'o'}};std::stringresult;// project, then uppercaseranges::transform(f,std::back_inserter(result),op,&Foo::bar);std::cout<<result<<'\n';}Output:

HELLO: 72 69 76 76 79 144 138 152 152 158 HELLO See also