Начиная с C ++ 20, мы можем определять немедленные функции, используя спецификатор consteval
. Когда функция объявляется consteval
, каждый вызов этой функции должен создавать константу времени компиляции, в противном случае программа имеет неправильный формат. Кроме того, поскольку в C ++ 20 блоки try-catch разрешены в контекстах с постоянной оценкой, но создание исключений по-прежнему запрещено. Из-за этого я сначала подумал, что, поскольку consteval
подразумевает inline
, это также подразумевает noexcept
, поскольку создание любого исключения запрещено. Как вы сейчас можете себе представить, это неверно: если вы не укажете noexcept
, немедленная функция будет потенциально бросающей функцией со всеми вытекающими отсюда отрицательными сторонами. Есть ли причина для этого, о которой я не знаю?
Почему немедленные функции не имеют значения noexcept по умолчанию и почему им разрешено быть noexcept (false)?
Ответы (1)
Некоторые алгоритмы выполняют разные действия в зависимости от спецификации noexcept (см. Std :: vector :: resize ()). Также компилятор может удалить код обработки исключений для функции, не вызывающей выброса.
Непосредственные функции вызываются во время компиляции. Хотя в C ++ 20 действительно есть контейнеры времени компиляции, их производительность не имеет отношения к коду времени выполнения. И им было бы достаточно просто использовать различные внутренние реализации на основе if(is_constant_evaluated)
, что принесло бы больше, чем просто noexcept
запросы.
Но даже в этом случае одна из целей кодирования constexpr - сделать код времени компиляции похожим на код времени выполнения. Итак, если у вас есть класс, который должен существовать только во время компиляции и имеет consteval
конструктор перемещения, то пользователь должен думать о нем точно так же, как о классе времени выполнения. Поэтому, если они сделают конструктор перемещения noexcept
в классе времени выполнения, он также должен быть в классе времени компиляции.
И это вдвойне важно, поскольку это сохраняет способность кода времени компиляции генерировать исключения в будущих версиях языка. Это возможно, в частности, если P0709: Статические исключения попадает в стандарт.
Кроме того, немедленные функции существуют только во время компиляции, а это контекст, в котором нет обработки исключений. Итак, что бы ни делал компилятор для создания кода для функции constexpr, он не задействует механизмы обработки исключений. Поэтому делать их неявно noexcept
для целей генерации кода не имеет смысла.
Наконец, consteval
в конечном итоге построен как незначительное изменение по сравнению с объявлениями функций constexpr
. Даже неявное inline
происходит от consteval
, означающего constexpr
, а не от самого consteval
. Добавление новой семантики в consteval
внесет значительные изменения.
consteval int foo() {return 42; } void bar(int = foo()) noexcept;
в этом случае bar () не noexcept!
- person user7769147; 23.05.2020
noexcept
не проверяет, не может ли содержащийся в нем код вызвать исключение. Это просто заявление о том, что эта функция не будет генерировать исключения, и если она попытается это сделать, будет вызываться std::terminate
.
- person Nicol Bolas; 23.05.2020
consteval
функциям выдавать ошибки, используя стандартные механизмы, вместо того, чтобы возвращать optional
, который вы должны явно проверить.
- person Nicol Bolas; 23.05.2020
if(condition) throw "....";
в немедленной функции остановит компиляцию тогда и только тогда, когда condition
истинно
- person user7769147; 23.05.2020
consteval
функция бытьnoexcept
? Какие преимущества вы получили бы даже от такого нарушения ортогональности? - person Barry   schedule 23.05.2020constexpr
подразумевалconst
для функций-членов. Посмотрите, чем это закончилось. - person T.C.   schedule 23.05.2020