Ambos std::forward
y std::move
no son más que moldes.
X x;
std::move(x);
Lo anterior x
convierte la expresión lvalue de tipo X en una expresión rvalue de tipo X (un valor x para ser exactos). move
También puede aceptar un valor r:
std::move(make_X());
y en este caso es una función de identidad: toma un valor de tipo X y devuelve un valor de tipo X.
Con std::forward
usted puede seleccionar el destino hasta cierto punto:
X x;
std::forward<Y>(x);
Convierte la expresión lvalue x
de tipo X en una expresión de tipo Y. Existen restricciones sobre lo que Y puede ser.
Y puede ser una Base de X accesible, o una referencia a una Base de X. Y puede ser X, o una referencia a X. No se pueden descartar los calificadores cv forward
, pero se pueden agregar calificadores cv. Y no puede ser un tipo que sea simplemente convertible de X, excepto a través de una conversión de Base accesible.
Si Y es una referencia de valor, el resultado será una expresión de valor. Si Y no es una referencia de lvalue, el resultado será una expresión de rvalue (xvalue para ser precisos).
forward
puede tomar un argumento rvalue solo si Y no es una referencia lvalue. Es decir, no puede emitir un valor r a lvalue. Esto se debe a razones de seguridad, ya que esto generalmente lleva a referencias colgantes. Pero emitir un rvalue a rvalue está bien y está permitido.
Si intenta especificar Y a algo que no está permitido, el error se detectará en tiempo de compilación, no en tiempo de ejecución.