Namespaces
Variants

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

De es.cppreference.net
 
 
Biblioteca de algoritmos
Algoritmos restringidos y algoritmos sobre rangos (C++20)
Algoritmos restringidos, p. ej. ranges::copy, ranges::sort, ...
Operaciones de secuencia no modificadoras    
Operaciones por lotes
(C++17)
Operaciones de búsqueda
Operaciones de secuencia modificadoras
Operaciones de copia
(C++11)
(C++11)
Operaciones de intercambio
Operaciones de transformación
Operaciones de generación
Operaciones de eliminación
Operaciones de cambio de orden
(hasta C++17)(C++11)
(C++20)(C++20)
Operaciones de muestreo
(C++17)

Operaciones de ordenación y relacionadas
Operaciones de particionado
(C++11)    

Operaciones de ordenación
Operaciones de búsqueda binaria
(en rangos particionados)
Operaciones de conjunto (en rangos ordenados)
Operaciones de mezcla (en rangos ordenados)
Operaciones de montículo
Operaciones de mínimo/máximo
(C++11)
(C++17)
Operaciones de comparación lexicográfica
Operaciones de permutación


 
Algoritmos restringidos
Todos los nombres en este menú pertenecen al espacio de nombres std::ranges
Operaciones de secuencia no modificadoras
Operaciones de secuencia modificadoras
Operaciones de particionado
Operaciones de ordenación
Operaciones de búsqueda binaria (en rangos ordenados)
       
       
Operaciones de conjunto (en rangos ordenados)
Operaciones de montículo
Operaciones de mínimo/máximo
       
       
Operaciones de permutación
Operaciones de pliegue
Operaciones sobre almacenamiento no inicializado
Tipos de retorno
 
Definido en el encabezado <algorithm>
Firma de llamada
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) (desde 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) (desde 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) (desde 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) (desde C++20)
Tipos auxiliares
template< class I, class O >
using unary_transform_result = ranges::in_out_result<I, O>;
(5) (desde C++20)
template< class I1, class I2, class O >
using binary_transform_result = ranges::in_in_out_result<I1, I2, O>;
(6) (desde C++20)

Aplica la función dada a un rango y almacena el resultado en otro rango, comenzando en result.

1) La operación unaria op se aplica al rango definido por [first1, last1) (después de proyectar con la proyección proj).
2) Igual que (1), pero usa r como rango fuente, como si se usara ranges::begin(r) como first y ranges::end(r) como last.
3) La operación binaria binary_op se aplica a pares de elementos de dos rangos: uno definido por [first1, last1) y el otro definido por [first2, last2) (después de proyectar respectivamente con las proyecciones proj1 y proj2).
4) Igual que (3), pero usa r1 como el primer rango fuente, como si se usara ranges::begin(r1) como first1 y ranges::end(r1) como last1, y de manera similar para r2.

Las entidades similares a funciones descritas en esta página son objetos función de algoritmo (informalmente conocidos como niebloids), es decir:

Parámetros

first1, last1 - el par iterador-centinela que define el primer rango de elementos a transformar
r, r1 - el primer rango de elementos a transformar
first2, last2 - el par iterador-centinela que define el segundo rango de elementos a transformar
r2 - el segundo rango de elementos a transformar
result - el inicio del rango destino, puede ser igual a first1 o first2
op, binary_op - operación a aplicar a los elementos proyectados
proj1 - proyección a aplicar a los elementos del primer rango
proj2 - proyección a aplicar a los elementos del segundo rango

Valor de retorno

1,2) Un unary_transform_result contiene un iterador de entrada igual a last y un iterador de salida al elemento después del último elemento transformado.
3,4) Un binary_transform_result contiene iteradores de entrada a los últimos elementos transformados de los rangos [ first1 , last1 ) y [ first2 , last2 ) como in1 y in2 respectivamente, y el iterador de salida al elemento después del último elemento transformado como out .

Complejidad

1,2) Exactamente ranges:: distance ( first1, last1 ) aplicaciones de op y proj .
3,4) Exactamente ranges:: min ( ranges:: distance ( first1, last1 ) , ranges:: distance ( first2, last2 ) ) aplicaciones de binary_op y proyecciones.

Implementación posible

struct transform_fn
{
    // Primera versión
    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 {std::move(first1), std::move(result)};
    }
    // Segunda versión
    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), std::move(result),
                       std::move(op), std::move(proj));
    }
    // Tercera versión
    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 {std::move(first1), std::move(first2), std::move(result)};
    }
    // Cuarta versión
    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),
                       std::move(result), std::move(binary_op),
                       std::move(proj1), std::move(proj2));
    }
};
inline constexpr transform_fn transform;

Notas

ranges::transform no garantiza la aplicación en orden de op o binary_op . Para aplicar una función a una secuencia en orden o para aplicar una función que modifique los elementos de una secuencia, use ranges::for_each .

Ejemplo

El siguiente código utiliza ranges::transform para convertir una cadena in situ a mayúsculas usando la función std::toupper y luego transforma cada char a su valor ordinal. Luego se utiliza ranges::transform con una proyección para transformar elementos de std:: vector < Foo > en caracteres para llenar un std::string .

#include <algorithm>
#include <cctype>
#include <functional>
#include <iostream>
#include <string>
#include <vector>
int main()
{
    std::string s{"hello"};
    auto op = [](unsigned char c) -> unsigned char { return std::toupper(c); };
    namespace ranges = std::ranges;
    // convertir la cadena a mayúsculas in situ
    ranges::transform(s.begin(), s.end(), s.begin(), op );
    std::vector<std::size_t> ordinals;
    // convertir cada char a size_t
    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;
    // duplicar cada valor ordinal
    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 result;
    // proyectar, luego convertir a mayúsculas
    ranges::transform(f, std::back_inserter(result), op, &Foo::bar);
    std::cout << result << '\n';
}

Salida:

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

Véase también

aplica un objeto función unario a elementos de un rango
(objeto función algoritmo)
una view de una secuencia que aplica una función de transformación a cada elemento
(plantilla de clase) (objeto adaptador de rango)
aplica una función a un rango de elementos, almacenando resultados en un rango destino
(plantilla de función)