从 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
将产生重大变化。