Les deux std::forward
et std::move
ne sont que des moulages.
X x;
std::move(x);
Ce qui précède convertit l'expression lvalue x
de type X en une expression rvalue de type X (une valeur x pour être exacte). move
peut également accepter une rvalue:
std::move(make_X());
et dans ce cas c'est une fonction d'identité: prend une rvalue de type X et retourne une rvalue de type X.
Avec std::forward
vous pouvez sélectionner la destination dans une certaine mesure:
X x;
std::forward<Y>(x);
Convertit l'expression lvalue x
de type X en une expression de type Y. Il existe des contraintes sur ce que Y peut être.
Y peut être une base accessible de X, ou une référence à une base de X. Y peut être X, ou une référence à X. On ne peut pas rejeter les qualificatifs cv avec forward
, mais on peut ajouter des qualificatifs cv. Y ne peut pas être un type simplement convertible à partir de X, sauf via une conversion de base accessible.
Si Y est une référence lvalue, le résultat sera une expression lvalue. Si Y n'est pas une référence lvalue, le résultat sera une expression rvalue (xvalue pour être précis).
forward
peut prendre un argument rvalue uniquement si Y n'est pas une référence lvalue. Autrement dit, vous ne pouvez pas convertir une rvalue en lvalue. Ceci est pour des raisons de sécurité car cela conduit généralement à des références pendantes. Mais le cast d'une rvalue en rvalue est correct et autorisé.
Si vous essayez de spécifier Y pour quelque chose qui n'est pas autorisé, l'erreur sera interceptée au moment de la compilation, pas au moment de l'exécution.