Namespaces
Variants

std::forward

De es.cppreference.net
 
 
Biblioteca de utilidades
Soporte del lenguaje
Soporte de tipos (tipos básicos, RTTI)
Macros de prueba de características de biblioteca (C++20)
Utilidades de programa
Funciones variádicas
Soporte de corrutinas (C++20)
Soporte de contratos (C++26)
Comparación de tres vías
(C++20)
(C++20)(C++20)(C++20)    
(C++20)(C++20)(C++20)

Utilidades generales
Operadores relacionales (obsoleto en C++20)
 
Definido en el encabezado <utility>
template< class T >
T&& forward( typename std::remove_reference<T>::type& t ) noexcept;
(1) (desde C++11)
(hasta C++14)
template< class T >
constexpr T&& forward( std::remove_reference_t<T>& t ) noexcept;
(desde C++14)
template< class T >
T&& forward( typename std::remove_reference<T>::type&& t ) noexcept;
(2) (desde C++11)
(hasta C++14)
template< class T >
constexpr T&& forward( std::remove_reference_t<T>&& t ) noexcept;
(desde C++14)
1) Reenvía valores l como valores l o como valores r, dependiendo de T.

Cuando t es una referencia de reenvío (un argumento de función que se declara como una referencia a un valor r de un parámetro de plantilla de función sin calificación cv), esta sobrecarga reenvía el argumento a otra función con la categoría de valor que tenía cuando se pasó a la función llamante.

Por ejemplo, si se usa en un envoltorio como el siguiente, la plantilla se comporta como se describe a continuación:

template<class T>
void wrapper(T&& arg)
{
    // arg is always lvalue
    foo(std::forward<T>(arg)); // Forward as lvalue or as rvalue, depending on T
}
  • Si una llamada a wrapper() pasa un valor r std::string, entonces T se deduce a std::string (no std::string&, const std::string&, o std::string&&), y std::forward asegura que se pase una referencia a valor r a foo.
  • Si una llamada a wrapper() pasa un valor l constante std::string, entonces T se deduce a const std::string&, y std::forward asegura que se pase una referencia a valor l constante a foo.
  • Si una llamada a wrapper() pasa un valor l no constante std::string, entonces T se deduce a std::string&, y std::forward asegura que se pase una referencia a valor l no constante a foo.
2) Reenvía valores r como valores r y prohíbe reenviar valores r como valores l.

Esta sobrecarga hace posible reenviar el resultado de una expresión (como una llamada a función), que puede ser valor r o valor l, como la categoría de valor original de un argumento de referencia de reenvío.

Por ejemplo, si un envoltorio no solo reenvía su argumento, sino que llama a una función miembro en el argumento y reenvía su resultado:

// transforming wrapper
template<class T>
void wrapper(T&& arg)
{
    foo(forward<decltype(forward<T>(arg).get())>(forward<T>(arg).get()));
}

donde el tipo de arg puede ser

struct Arg
{
    int i = 1;
    int  get() && { return i; } // call to this overload is rvalue
    int& get() &  { return i; } // call to this overload is lvalue
};

Intentar reenviar un valor r como un valor l, como al instanciar la forma (2) con el tipo de referencia a valor l T, es un error en tiempo de compilación.

Notas

Consulte deducción de argumentos de plantilla para las reglas especiales detrás de las referencias de reenvío ( T&& usado como parámetro de función) y referencias de reenvío para más detalles.

Parámetros

t - el objeto a ser reenviado

Valor de retorno

static_cast < T && > ( t )

Complejidad

Constante.

Ejemplo

Este ejemplo demuestra el reenvío perfecto de los parámetros al argumento del constructor de la clase T . También se demuestra el reenvío perfecto de paquetes de parámetros.

#include <iostream>
#include <memory>
#include <utility>
struct A
{
    A(int&& n) { std::cout << "rvalue overload, n=" << n << '\n'; }
    A(int& n)  { std::cout << "lvalue overload, n=" << n << '\n'; }
};
class B
{
public:
    template<class T1, class T2, class T3>
    B(T1&& t1, T2&& t2, T3&& t3) :
        a1_{std::forward<T1>(t1)},
        a2_{std::forward<T2>(t2)},
        a3_{std::forward<T3>(t3)}
    {}
private:
    A a1_, a2_, a3_;
};
template<class T, class U>
std::unique_ptr<T> make_unique1(U&& u)
{
    return std::unique_ptr<T>(new T(std::forward<U>(u)));
}
template<class T, class... U>
std::unique_ptr<T> make_unique2(U&&... u)
{
    return std::unique_ptr<T>(new T(std::forward<U>(u)...));
}
auto make_B(auto&&... args) // since C++20
{
    return B(std::forward<decltype(args)>(args)...);
}
int main()
{
    auto p1 = make_unique1<A>(2); // rvalue
    int i = 1;
    auto p2 = make_unique1<A>(i); // lvalue
    std::cout << "B\n";
    auto t = make_unique2<B>(2, i, 3);
    std::cout << "make_B\n";
    [[maybe_unused]] B b = make_B(4, i, 5);
}

Salida:

rvalue overload, n=2
lvalue overload, n=1
B
rvalue overload, n=2
lvalue overload, n=1
rvalue overload, n=3
make_B
rvalue overload, n=4
lvalue overload, n=1
rvalue overload, n=5

Véase también

(C++11)
convierte el argumento a un xvalue
(plantilla de función)
convierte el argumento a un xvalue si el constructor de movimiento no lanza excepciones
(plantilla de función)