Ambos std::forwardy std::moveno son más que moldes.
X x;
std::move(x);
Lo anterior xconvierte la expresión lvalue de tipo X en una expresión rvalue de tipo X (un valor x para ser exactos). moveTambié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::forwardusted puede seleccionar el destino hasta cierto punto:
X x;
std::forward<Y>(x);
Convierte la expresión lvalue xde 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).
forwardpuede 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.