Ответ 1
Перспективная семантика уже является условной, т.е. сохраняет категорию значений своего аргумента. С другой стороны, этот шаг безоговорочно меняет (от значения l до r-value) категорию значения своего аргумента на r-значение (ссылку), std::move_if_noexcept
получает результирующую категорию значений на основе того, конструктор перемещения не исключает исключений, что также делает его условным.
Короче говоря, std::forward
ничего не меняет, он сохраняет категорию значений. std::move
, с другой стороны, меняет категорию значений. Итак, std::move_if_noexcept
вводится, чтобы сказать, что если std::move
изменение может вызвать исключение, то ничего не меняйте; не двигайте его.
Я думаю, что обоснование здесь также относится к предполагаемому идиоматическому использованию всех вещей std::move
и std::forward
соответственно. В одном из других разговоров Скотта (возможно, на С++ и Beyond 2012), посвященных "универсальным ссылкам", пересылке и перемещении, он был весьма решительно настроен на идиоматическое использование форварда, и я думаю, что это лежит в основе того, что std::forward
есть и как Это использовано. Это может быть просто так просто, как никогда не рассматривалось.
Я бы сказал, что нет необходимости или, по крайней мере, существует меньшая потребность, когда выполняется std::forward
.
Учитывая, что для него может быть использован прецедент, реализация не будет слишком сложной; но я не уверен в общем прецеденте. Можно утверждать, что условия, связанные с возможными исключениями и необходимыми исключениями, должны быть проверены и обработаны вне функции, выполняющей переадресацию.
template <class U, class T>
U wrapper(T&& arg)
{
return U(forward<T>(arg));
}
template <class U, class T>
U method()
{
T t;
// work with t
return wrapper<U>(move_if_noexcept(t));
}
Конечно, это "ранние дни" для многих из них, так что это может измениться.