Espacios de nombres
Variantes
Acciones

std::forward

De cppreference.com
< cpp‎ | utility
 
 
Biblioteca de servicios
Servicios generales
Operadores relacionales (en desuso en C++20)
 
Definido en el archivo de 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 ya sea como lvalues o como rvalues, dependiendo de T.

Cuando t es una referencia reenviante (una función argumento que se declara como una referencia a un parámetro de plantilla de función no calificado-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 llamada.

Por ejemplo, si se usa en un envoltorio como el siguiente, la plantilla se comporta como se describe más abajo:

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

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

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

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

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

Contenido

[editar] Notas

Véase deducción de argumentos de plantilla para las reglas especiales detrás de las referencias reenviantes (T&& usadas como un parámetro de función) y referencias reenviantes para más detalles.

[editar] Parámetros

t - El objeto a ser reenviado.

[editar] Valor de retorno

static_cast<T&&>(t)

[editar] Ejemplo

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

#include <iostream>
#include <memory>
#include <utility>
 
struct A {
    A(int&& n) { std::cout << "sobrecarga rvalue, n=" << n << "\n"; }
    A(int& n)  { std::cout << "sobrecarga lvalue, 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)...));
}
 
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);
}

Salida:

sobrecarga rvalue, n=2
sobrecarga lvalue, n=1
B
sobrecarga rvalue, n=2
sobrecarga lvalue, n=1
sobrecarga rvalue, n=3

[editar] Complejidad

Constante

[editar] Véase también

(C++11)
Obtiene una referencia r-valor
(plantilla de función) [editar]
Obtiene una referencia r-valor si el constructor de movimiento no lanza una excepción
(plantilla de función) [editar]