3

从 c++20 开始,我们可以使用说明符定义立即函数consteval。当一个函数被声明consteval时,对该函数的每次调用都必须产生一个编译时常量,否则程序是错误的。此外,由于 c++20 的 try-catch 块在常量评估上下文中是允许的,但仍然不允许抛出异常。正因为如此,我最初认为这consteval意味着inline它也暗示noexcept,因为禁止抛出任何异常。正如您在这一点上可以想象的那样,这是不正确的:除非您指定noexcept,否则立即函数是一个潜在的抛出函数,其所有负面都由此派生。这是我不知道的原因吗?

4

1 回答 1

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

于 2020-05-23T15:17:18.243 回答