Entrambi std::forward
e std::move
non sono altro che cast.
X x;
std::move(x);
Quanto sopra lancia l'espressione lvalue x
di tipo X su un'espressione rvalue di tipo X (un valore x per essere esatti). move
può anche accettare un valore:
std::move(make_X());
e in questo caso è una funzione di identità: prende un valore di tipo X e restituisce un valore di tipo X.
Con std::forward
te puoi selezionare la destinazione in una certa misura:
X x;
std::forward<Y>(x);
Lancia l'espressione lvalue x
di tipo X su un'espressione di tipo Y. Esistono vincoli su ciò che Y può essere.
Y può essere una base accessibile di X o un riferimento a una base di X. Y può essere X o un riferimento a X. Non è possibile eliminare qualificatori cv con forward
, ma è possibile aggiungere qualificatori cv. Y non può essere un tipo che è semplicemente convertibile da X, tranne tramite una conversione Base accessibile.
Se Y è un riferimento lvalue, il risultato sarà un'espressione lvalue. Se Y non è un riferimento lvalue, il risultato sarà un'espressione rvalue (xvalue per essere precisi).
forward
può accettare un argomento rvalue solo se Y non è un riferimento lvalue. Cioè, non puoi lanciare un valore in valore. Questo per motivi di sicurezza in quanto ciò porta comunemente a riferimenti sospesi. Ma lanciare un valore in valore è ok e permesso.
Se si tenta di specificare Y su qualcosa che non è consentito, l'errore verrà rilevato al momento della compilazione, non in fase di esecuzione.