Obie std::forwardi std::movesą niczym innym jak odlewami.
X x;
std::move(x);
Powyższe rzutuje wyrażenie l- xwartości typu X na wyrażenie r-wartości typu X (dokładnie xwartość). movemoże również akceptować wartość r:
std::move(make_X());
w tym przypadku jest to funkcja tożsamości: przyjmuje wartość r typu X i zwraca wartość r typu X.
Dzięki std::forwardniemu możesz w pewnym stopniu wybrać miejsce docelowe:
X x;
std::forward<Y>(x);
Rzuca wyrażenie l- xwartości typu X na wyrażenie typu Y. Istnieją ograniczenia dotyczące tego, czym może być Y.
Y może być dostępną bazą X lub odwołaniem do podstawy X. Y może oznaczać X lub odniesienie do X. Nie można odrzucać kwalifikatorów cv forward, ale można dodać kwalifikatory cv. Y nie może być typem, który można jedynie zamienić z X, z wyjątkiem dostępnej konwersji Base.
Jeśli Y jest odwołaniem do lwartości, wynik będzie wyrażeniem lwartości. Jeśli Y nie jest odniesieniem do lwartości, wynik będzie wyrażeniem rvalue (a dokładniej xvalue).
forwardmoże przyjąć argument rvalue tylko wtedy, gdy Y nie jest odniesieniem do lwartości. Oznacza to, że nie można rzutować wartości r na lwartość. Dzieje się tak ze względów bezpieczeństwa, ponieważ często prowadzi to do zawieszania się odniesień. Ale rzutowanie rvalue na rvalue jest w porządku i dozwolone.
Jeśli spróbujesz określić Y jako coś, co jest niedozwolone, błąd zostanie przechwycony w czasie kompilacji, a nie w czasie wykonywania.