std::forward
| 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) | |
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 rvaluestd::string, entoncesTse deduce comostd::string(no comostd::string&,const std::string&, ostd::string&&), ystd::forwardse asegura que se pasa una referencia rvalue afoo. - Si una llamada a
wrapper()pasa un lvaluestd::stringconstante, entoncesTse deduce comoconst std::string&, ystd::forwardse asegura que se pasa una referencia lvalue constante afoo. - Si una llamada a
wrapper()pasa un lvaluestd::stringno constante, entoncesTse deduce comostd::string&, ystd::forwardse asegura que se pasa una referencia lvalue no constante afoo.
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.
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.
Parámetros
| t | - | El objeto a ser reenviado. |
Valor de retorno
static_cast<T&&>(t)
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
Complejidad
Constante
Véase también
(C++11) |
Obtiene una referencia r-valor (plantilla de función) |
(C++11) |
Obtiene una referencia r-valor si el constructor de movimiento no lanza una excepción (plantilla de función) |