Obie std::forward
i std::move
są niczym innym jak odlewami.
X x;
std::move(x);
Powyższe rzutuje wyrażenie l- x
wartości typu X na wyrażenie r-wartości typu X (dokładnie xwartość). move
moż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::forward
niemu możesz w pewnym stopniu wybrać miejsce docelowe:
X x;
std::forward<Y>(x);
Rzuca wyrażenie l- x
wartoś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).
forward
moż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.