c++ - Cuándo usar std:: forward para reenviar argumentos?
templates forwarding (1)
C ++ 0x muestra un ejemplo de uso de std::forward
:
template<class T>
void foo(T&& arg)
{
bar(std::forward<T>(arg));
}
¿Cuándo es ventajoso usar std::forward
, always?
Además, requiere usar &&
en la declaración de parámetros, ¿es válido en todos los casos? Pensé que tenías que pasar temporarios a una función si la función se declaró con &&
en ella, entonces ¿se puede llamar con algún parámetro?
Por último, si tengo una llamada de función como esta:
template<int val, typename... Params>
void doSomething(Params... args) {
doSomethingElse<val, Params...>(args...);
}
Debo usar esto en su lugar:
template<int val, typename... Params>
void doSomething(Params&&... args) {
doSomethingElse<val, Params...>(std::forward<Params>(args)...);
}
Además, si usa los parámetros dos veces en la función, es decir, reenvía a dos funciones al mismo tiempo, ¿es aconsejable usar std::forward
? No std::forward
convierte lo mismo en temporal dos veces, ¿mueve la memoria y la invalida para un segundo uso? ¿El siguiente código estaría bien?
template<int val, typename... Params>
void doSomething(Params&&... args) {
doSomethingElse<val, Params...>(std::forward<Params>(args)...);
doSomethingWeird<val, Params...>(std::forward<Params>(args)...);
}
Estoy un poco confundido por std::forward
, y con gusto usaré un poco de aclaración.
Úselo como su primer ejemplo:
template <typename T> void f(T && x)
{
g(std::forward<T>(x));
}
template <typename ...Args> void f(Args && ...args)
{
g(std::forward<Args>(args)...);
}
Esto se debe a las reglas de colapso de referencia : si T = U&
, entonces T&& = U&
, pero si T = U&&
, entonces T&& = U&&
, por lo que siempre termina con el tipo correcto dentro del cuerpo de la función. Finalmente, necesita forward
el x
convertido por valor (porque ahora tiene un nombre) a una referencia rvalue si fue uno inicialmente.
No se puede reenviar algo más de una vez, porque eso no tiene sentido. El reenvío significa que estás moviendo potencialmente el argumento hasta la llamada final, y una vez que se ha movido ya no está, por lo que no puedes volver a utilizarlo.