Почему немедленные функции не имеют значения noexcept по умолчанию и почему им разрешено быть noexcept(false)?
Начиная с C++20, мы можем определять немедленные функции, используя consteval
спецификатор. Когда функция объявленаconsteval
каждый вызов этой функции должен производить константу времени компиляции, иначе программа будет некорректной. Кроме того, поскольку в C++20 блоки try-catch разрешены в постоянных оцениваемых контекстах, но создание исключений по-прежнему запрещено. Из-за этого я изначально думал, что какconsteval
подразумевает inline
это также подразумевает noexcept
так как исключение запрещено. Как вы можете себе представить, это неверно: если вы не укажетеnoexcept
, немедленная функция - это потенциально вызывающая функция со всеми вытекающими отсюда отрицательными сторонами. Есть ли причина этого, о которой я не знаю?
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
внесет значительные изменения.