И std::forward
, и std::move
- не что иное, как приведение.
X x;
std::move(x);
Выше приведено выражение lvalue x
типа X к выражению rvalue типа X (точнее xvalue). move
также может принимать значение:
std::move(make_X());
и в этом случае это функция тождества: принимает значение типа X и возвращает значение типа X.
С помощью std::forward
вы можете выбрать пункт назначения до некоторой степени:
X x;
std::forward<Y>(x);
Приводит выражение lvalue x
типа X к выражению типа Y. Существуют ограничения на то, что может быть Y.
Y может быть доступной Базой X или ссылкой на Базу X. Y может быть X, или ссылкой на X. Нельзя отбрасывать cv-квалификаторы с помощью forward
, но можно добавлять cv -qualifiers. Y не может быть типом, который просто конвертируется из X, кроме как через доступное базовое преобразование.
Если Y является ссылкой lvalue, результатом будет выражение lvalue. Если Y не является ссылкой lvalue, результатом будет выражение rvalue (точнее xvalue).
forward
может принимать аргумент rvalue, только если Y не является ссылкой lvalue. То есть вы не можете привести значение к значению lvalue. Это из соображений безопасности, поскольку это обычно приводит к висящим ссылкам. Но приведение rvalue к rvalue возможно и разрешено.
Если вы попытаетесь указать Y для чего-то, что не разрешено, ошибка будет обнаружена во время компиляции, а не во время выполнения.