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
, entoncesT
se deduce comostd::string
(no comostd::string&
,const std::string&
, ostd::string&&
), ystd::forward
se asegura que se pasa una referencia rvalue afoo
. - Si una llamada a
wrapper()
pasa un lvaluestd::string
constante, entoncesT
se deduce comoconst std::string&
, ystd::forward
se asegura que se pasa una referencia lvalue constante afoo
. - Si una llamada a
wrapper()
pasa un lvaluestd::string
no constante, entoncesT
se deduce comostd::string&
, ystd::forward
se 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.
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) |
(C++11) |
Obtiene una referencia r-valor si el constructor de movimiento no lanza una excepción (plantilla de función) |