【问题标题】:Why immediate functions are not noexcept by default and why are they allowed to be noexcept(false)?为什么立即函数默认不是 noexcept,为什么它们允许为 noexcept(false)?
【发布时间】:2020-09-10 09:48:33
【问题描述】:

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

【问题讨论】:

  • 所有由此衍生的负面因素” 比如?
  • @JesperJuhl:您不能“语言律师”提出“为什么”的问题,因为规范没有说明“为什么”任何特定功能都是这样的。您不能要求对规范定义的内容进行规范引用。
  • 一些算法根据 noexcept 规范执行不同的操作(参见 std::vector::resize() )。此外,编译器可能会删除非抛出函数的异常处理代码
  • 为什么应该 consteval 函数是noexcept?像这样打破正交性还能获得什么好处?
  • @user7769147 确实如此,但它也没有回答问题。

标签: c++ c++20 noexcept consteval


【解决方案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!
  • 那些异常会导致编译时错误,它们无论如何都不会传播到函数之外。”我说的是未来的语言更改,它们会删除禁止编译时抛出异常。
  • @user7769147:“在这种情况下 bar() 不是 noexcept!” 是的。 noexcept 不会验证其中的代码是否不会导致发出异常。这只是一个声明,这个函数不会发出异常,如果它试图发出异常,std::terminate 将被调用。
  • “我说的是未来的语言变化,他们取消了对编译时异常抛出的禁止” 这根本没有任何意义,抛出一个编译时上下文中的异常应该像使用 static_assert 一样,编译应该停止而不是在运行时处理异常。 ""在这种情况下 bar() 不是 noexcept!" 是的,是"你是对的,我的错
  • @user7769147:并非所有异常都意味着世界已被破坏,应用程序必须终止。异常可以是可恢复的状态,异常传播允许将该信息传递到其目的地,而无需大量中间代码检查每个函数的返回值。
猜你喜欢
  • 2020-05-08
  • 2013-05-13
  • 1970-01-01
  • 2021-04-07
  • 2016-11-21
  • 1970-01-01
  • 2015-06-28
  • 2018-07-11
  • 2018-10-06
相关资源
最近更新 更多