Почему нет std:: move_if_noexcept для std:: forward в С++ 11/14?

Я смотрел рассказ Скотта Мейерса о GoingNative2013 "Эффективный С++ 11/14 Sampler", и он объяснил использование std::move_if_noexcept.

Итак, на мой взгляд, должен быть std::forward_if_noexcept, чтобы гарантировать безопасность исключений для forward? Почему в стандартной библиотеке нет ничего подобного? Есть ли еще возможность гарантировать это?

Ответ 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));
}

Конечно, это "ранние дни" для многих из них, так что это может измениться.