# std::ranges::transform, std::ranges::unary_transform_result, std::ranges::binary_transform_result

From cppreference.com
< cpp‎ | algorithm‎ | ranges

Defined in header `<algorithm>` |  |
Call signature |  |
template< std::input_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O, std::copy_constructible F, class Proj = std::identity > requires std::indirectly_writable<O, std::indirect_result_t<F&, std::projected<I, Proj>>> constexpr unary_transform_result<I, O> transform( I first1, S last1, O result, F op, Proj proj = {} ); | (1) | (since C++20)
template< ranges::input_range R, std::weakly_incrementable O, std::copy_constructible F, class Proj = std::identity > requires std::indirectly_writable<O, std::indirect_result_t<F&, std::projected<ranges::iterator_t<R>, Proj>>> constexpr unary_transform_result<ranges::borrowed_iterator_t<R>, O> transform( R&& r, O result, F op, Proj proj = {} ); | (2) | (since C++20)
template< std::input_iterator I1, std::sentinel_for<I1> S1, std::input_iterator I2, std::sentinel_for<I2> S2, std::weakly_incrementable O, std::copy_constructible F, class Proj1 = std::identity, class Proj2 = std::identity > requires std::indirectly_writable<O, std::indirect_result_t<F&, std::projected<I1, Proj1>, std::projected<I2, Proj2>>> constexpr binary_transform_result<I1, I2, O> transform( I1 first1, S1 last1, I2 first2, S2 last2, O result, F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {} ); | (3) | (since C++20)
template< ranges::input_range R1, ranges::input_range R2, std::weakly_incrementable O, std::copy_constructible F, class Proj1 = std::identity, class Proj2 = std::identity > requires std::indirectly_writable<O, std::indirect_result_t<F&, std::projected<ranges::iterator_t<R1>, Proj1>, std::projected<ranges::iterator_t<R2>, Proj2>>> constexpr binary_transform_result<ranges::borrowed_iterator_t<R1>, ranges::borrowed_iterator_t<R2>, O> transform( R1&& r1, R2&& r2, O result, F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {} ); | (4) | (since C++20)
Helper types |  |
template< class I, class O > using unary_transform_result = ranges::in_out_result<I, O>; | (5) | (since C++20)
template< class I1, class I2, class O > using binary_transform_result = ranges::in_in_out_result<I1, I2, O>; | (6) | (since C++20)

Applies the given function to a range and stores the result in another range, beginning at result.

1) The unary operation op is applied to the range defined by `[`first1`,` last1`)` (after projecting with the projection proj).
2) Same as (1), but uses r as the source range, as if using ranges::begin(r) as first and ranges::end(r) as last.
3) The binary operation binary_op is applied to pairs of elements from two ranges: one defined by `[`first1`,` last1`)` and the other defined by `[`first2`,` last2`)` (after respectively projecting with the projections proj1 and proj2).
4) Same as (3), but uses r1 as the first source range, as if using ranges::begin(r1) as first1 and ranges::end(r1) as last1, and similarly for r2.

The function-like entities described on this page are 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.

In practice, they may be implemented as function objects, or with special compiler extensions.

### Parameters

first1, last1 | - | the first range of elements to transform
r, r1 | - | the first range of elements to transform
first2, last2 | - | the second range of elements to transform
r2 | - | the second range of elements to transform
result | - | the beginning of the destination range, may be equal to first1 or first2
op, binary_op | - | operation to apply to the projected element(s)
proj1 | - | projection to apply to the elements in the first range
proj2 | - | projection to apply to the elements in the second range.

### Return value

1-2) a `unary_transform_result` contains an input iterator equal to last and an output iterator to the element past the last element transformed.
3-4) a `binary_transform_result` contains input iterators to last transformed elements from ranges `[`first1`,` last1`)` and `[`first2`,` last2`)` as `in1` and `in2` respectively, and the output iterator to the element past the last element transformed as `out`.

### Complexity

1,2) Exactly ranges::distance(first1, last1) applications of op and proj.
3,4) Exactly ranges::min(ranges::distance(first1, last1), ranges::distance(first2, last2)) applications of binary_op and projections.

### Possible implementation

    struct transform_fn
    {
        // First version
        template<std::input_iterator I, std::sentinel_for<I> S, std::weakly_incrementable O,
                 std::copy_constructible F, class Proj = std::identity>
        requires std::indirectly_writable<O, std::indirect_result_t<F&, std::projected<I, Proj>>>
        constexpr ranges::unary_transform_result<I, O>
            operator()(I first1, S last1, O result, F op, Proj proj = {}) const
        {
            for (; first1 != last1; ++first1, (void)++result)
                *result = std::invoke(op, std::invoke(proj, *first1));

            return {first1, result};
        }

        // Second version
        template<ranges::input_range R, std::weakly_incrementable O,
                 std::copy_constructible F, class Proj = std::identity>
        requires std::indirectly_writable<O,
                     std::indirect_result_t<F&, std::projected<ranges::iterator_t<R>, Proj>>>
        constexpr ranges::unary_transform_result<ranges::borrowed_iterator_t<R>, O>
            operator()(R&& r, O result, F op, Proj proj = {}) const
        {
            return (*this)(ranges::begin(r), ranges::end(r), result, std::ref(op), std::ref(proj));
        }

        // Third version
        template<std::input_iterator I1, std::sentinel_for<I1> S1,
                 std::input_iterator I2, std::sentinel_for<I2> S2,
                 std::weakly_incrementable O,
                 std::copy_constructible F,
                 class Proj1 = std::identity, class Proj2 = std::identity>
        requires std::indirectly_writable<O,
                     std::indirect_result_t<F&,
                                            std::projected<I1, Proj1>,
                                            std::projected<I2, Proj2>>>
        constexpr ranges::binary_transform_result<I1, I2, O>
            operator()(I1 first1, S1 last1, I2 first2, S2 last2, O result,
                       F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}) 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 {first1, first2, result};
        }

        // Fourth version
        template<ranges::input_range R1, ranges::input_range R2,
                 std::weakly_incrementable O, std::copy_constructible F,
                 class Proj1 = std::identity, class Proj2 = std::identity>
        requires std::indirectly_writable<O,
                     std::indirect_result_t<F&,
                         std::projected<ranges::iterator_t<R1>, Proj1>,
                         std::projected<ranges::iterator_t<R2>, Proj2>>>
        constexpr ranges::binary_transform_result<ranges::borrowed_iterator_t<R1>,
                                                  ranges::borrowed_iterator_t<R2>, O>
            operator()(R1&& r1, R2&& r2, O result,
                       F binary_op, Proj1 proj1 = {}, Proj2 proj2 = {}) const
        {
            return (*this)(ranges::begin(r1), ranges::end(r1),
                           ranges::begin(r2), ranges::end(r2),
                           result, std::ref(binary_op),
                           std::ref(proj1), std::ref(proj2));
        }
    };

    inline constexpr transform_fn transform;

### Notes

`ranges::transform` does not guarantee in-order application of 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.

### 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>

    int main()
    {
        std::string s {"hello"};

        namespace ranges = std::ranges;

        ranges::transform(s.begin(), s.end(), s.begin(),
                          [](unsigned char c) -> unsigned char { return std::toupper(c); });

        std::vector<std::size_t> ordinals;
        ranges::transform(s, std::back_inserter(ordinals),
                          [](unsigned char c) -> std::size_t { return c; });

        std::cout << s << ':';
        for (auto ord : ordinals)
            std::cout << ' ' << ord;

        ranges::transform(ordinals, ordinals, ordinals.begin(), std::plus {});

        std::cout << '\n';
        for (auto ord : ordinals)
            std::cout << ord << ' ';
        std::cout << '\n';

        struct Foo
        {
            char bar;
        };
        const std::vector<Foo> f = { {'h'},{'e'},{'l'},{'l'},{'o'} };
        std::string bar;
        ranges::transform(f, std::back_inserter(bar), &Foo::bar);
        std::cout << bar << '\n';
    }

Output:

    HELLO: 72 69 76 76 79
    144 138 152 152 158
    hello

### See also

ranges::for_each (C++20) | applies a function to a range of elements (niebloid)
ranges::transform_view views::transform (C++20) | a `view` of a sequence that applies a transformation function to each element (class template) (range adaptor object)
transform | applies a function to a range of elements, storing results in a destination range (function template)

Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/algorithm/ranges/transform&oldid=150666"