c++ c++11 perfect-forwarding

c++ - ¿Por qué una función de reenvío perfecta tiene que estar programada?



c++11 perfect-forwarding (1)

En primer lugar, lea esto para tener una idea completa de reenvío. (Sí, estoy delegando la mayor parte de esta respuesta en otra parte).

Para resumir, el reenvío significa que lvalues ​​permanece lvalues ​​y rvalues ​​permanece rvalues. No puedes hacer eso con un solo tipo, así que necesitas dos. Entonces, para cada argumento reenviado, necesita dos versiones para ese argumento, que requiere un total de 2 N de combinaciones para la función. Puede codificar todas las combinaciones de la función, pero si usa plantillas, esas diversas combinaciones se generan para usted según sea necesario.

Si está intentando optimizar copias y movimientos, como en:

struct foo { foo(const T& pX, const U& pY, const V& pZ) : x(pX), y(pY), z(pZ) {} foo(T&& pX, const U& pY, const V& pZ) : x(std::move(pX)), y(pY), z(pZ) {} // etc.? :( T x; U y; V z; };

Entonces deberías parar y hacerlo de esta manera:

struct foo { // these are either copy-constructed or move-constructed, // but after that they''re all yours to move to wherever // (that is, either: copy->move, or move->move) foo(T pX, U pY, V pZ) : x(std::move(pX)), y(std::move(pY)), z(std::move(pZ)) {} T x; U y; V z; };

Solo necesitas un constructor. Pauta : si necesita su propia copia de los datos, haga esa copia en la lista de parámetros; esto permite la decisión de copiar o subir a la persona que llama y al compilador.

¿Por qué es válido el siguiente código?

template<typename T1> void foo(T1 &&arg) { bar(std::forward<T1>(arg)); } std::string str = "Hello World"; foo(str); // Valid even though str is an lvalue foo(std::string("Hello World")); // Valid because literal is rvalue

Pero no:

void foo(std::string &&arg) { bar(std::forward<std::string>(arg)); } std::string str = "Hello World"; foo(str); // Invalid, str is not convertible to an rvalue foo(std::string("Hello World")); // Valid

¿Por qué el valor en el ejemplo 2 no se resuelve de la misma manera que en el ejemplo 1?

Además, ¿por qué el estándar considera que es importante proporcionar el tipo de argumento en std :: forward versus simple deduced it? Simplemente llamar hacia adelante es mostrar intención, independientemente del tipo.

Si esto no es una cosa estándar y solo mi compilador, estoy usando msvc10, lo que explicaría el horrible soporte de C ++ 11.

Gracias

Edición 1: se modificó el literal "Hello World" para que sea std :: string ("Hello World") para hacer un valor.