Cả hai std::forward
và std::move
không có gì ngoài phôi.
X x;
std::move(x);
Các biểu thức trên đưa biểu thức giá trị x
của loại X thành biểu thức giá trị của loại X (chính xác là một giá trị xvalue). move
cũng có thể chấp nhận một giá trị:
std::move(make_X());
và trong trường hợp này, nó là một hàm nhận dạng: lấy một giá trị của loại X và trả về một giá trị của loại X.
Với std::forward
bạn có thể chọn đích đến một mức độ nào đó:
X x;
std::forward<Y>(x);
Chuyển biểu thức giá trị x
của loại X thành biểu thức của loại Y. Có các ràng buộc về những gì Y có thể.
Y có thể là Cơ sở X có thể truy cập hoặc tham chiếu đến Cơ sở X. Y có thể là X hoặc tham chiếu đến X. Người ta không thể bỏ qua vòng loại cv forward
, nhưng người ta có thể thêm vòng loại cv. Y không thể là loại chỉ có thể chuyển đổi từ X, ngoại trừ thông qua chuyển đổi Cơ sở có thể truy cập.
Nếu Y là tham chiếu giá trị, kết quả sẽ là biểu thức giá trị. Nếu Y không phải là tham chiếu giá trị, kết quả sẽ là biểu thức giá trị (xvalue chính xác).
forward
chỉ có thể lấy một đối số giá trị nếu Y không phải là tham chiếu giá trị. Đó là, bạn không thể đưa ra một giá trị cho lvalue. Điều này là vì lý do an toàn vì làm như vậy thường dẫn đến các tài liệu tham khảo lơ lửng. Nhưng đúc một giá trị thành rvalue là ok và được phép.
Nếu bạn cố gắng chỉ định Y cho một cái gì đó không được phép, lỗi sẽ được bắt gặp tại thời gian biên dịch, không phải thời gian chạy.