Namespaces
Variants

std:: forward

From cppreference.net
Utilities library
Definido en el encabezado <utility>
(1)
template < class T >
T && forward ( typename std:: remove_reference < T > :: type & t ) noexcept ;
(desde C++11)
(hasta C++14)
template < class T >
constexpr T && forward ( std:: remove_reference_t < T > & t ) noexcept ;
(desde C++14)
(2)
template < class T >
T && forward ( typename std:: remove_reference < T > :: type && t ) noexcept ;
(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 lvalues como lvalues o como rvalues, dependiendo de T.

Cuando t es una forwarding reference (un argumento de función que se declara como referencia de valor derecho a un parámetro de plantilla de función no calificado cv), esta sobrecarga reenvía el argumento a otra función con la value category que tenía cuando se pasó a la función de llamada.

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

template<class T>
void wrapper(T&& arg)
{
    // arg es siempre un lvalue
    foo(std::forward<T>(arg)); // Reenviar como lvalue o como rvalue, dependiendo de T
}
  • Si una llamada a wrapper() pasa un rvalue std::string , entonces T se deduce como std::string (no std::string& , const std::string& , o std::string&& ), y std::forward asegura que se pase una referencia de rvalue a foo .
  • Si una llamada a wrapper() pasa un lvalue constante std::string , entonces T se deduce como const std::string& , y std::forward asegura que se pase una referencia de lvalue constante a foo .
  • Si una llamada a wrapper() pasa un lvalue no constante std::string , entonces T se deduce como std::string& , y std::forward asegura que se pase una referencia de lvalue no constante a foo .
2) Reenvía los rvalues como rvalues y prohíbe el reenvío de rvalues como lvalues.

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

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

// envoltorio transformador
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; } // la llamada a esta sobrecarga es rvalue
    int& get() &  { return i; } // la llamada a esta sobrecarga es lvalue
};

Intentar reenviar un rvalue como lvalue, como al instanciar la forma (2) con tipo de referencia lvalue T, es un error en tiempo de compilación.

Contenidos

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)