C++标准库实现是否允许加强noexcept规范?

16

根据C++标准,C++标准库的实现是否允许加强由标准定义的方法和其他函数的noexcept规范?

例如,如果C++标准将某个函数std::f指定为void f();,那么标准库的实现是否允许将其实现为void f() noexcept;


所有实现都会在能够证明不会发生异常的情况下删除异常处理代码。noexcept 关键字更多地关注于如果栈中的某个调用者对编译器撒谎时该怎么做。 - Richard Hodges
对我来说,noexcept只是一个函数契约,可以在代码内部进行检查。 “非抛出”函数的概念一直存在,但现在我们可以在代码中验证它,如果我们想要编写一些“异常不安全但更快”的代码。低级代码生成对我来说几乎无关紧要。 - KABoissonneault
1
@KABoissonneault 我想我们的意思是一样的 - 而且你说得比我好 :) - Richard Hodges
1个回答

12

标准答案是肯定的:

§ 17.6.5.12.1 异常处理限制 [res.on.exception.handling]

  1. C++标准库中定义的任何函数都可以通过抛出Throws:段描述的异常类型来报告失败。实现可能通过添加一个非抛出的noexcept-specification来加强非虚函数的异常规范。

[...]

  1. C++标准库中定义的析构函数不得引发异常。C++标准库中的每个析构函数都应该表现得像它有一个非抛出的异常规范一样。C++标准库中没有显式exception-specification的其他函数,除非另有规定,否则可能会引发实现定义的异常。实现可能通过添加显示的exception-specification来增强这个隐式的exception-specification

(第4点似乎只是允许明确指定异常规范,并警告缺少显式异常规范意味着实现允许抛出任何东西)。


说实话,我不明白为什么这是允许的而添加constexpr不是(§ 17.6.5.6)。它们看起来像同一枚硬币的两面——通过使用类型特征和SFINAE,您可以编写显示不同行为的代码,具体取决于您使用哪个标准库实现(如果它标记某些函数为noexcept/constexpr或如果它没有),这就打败了首先制定标准的目的...


2
@peppe:“说实话,我不明白为什么允许这样做而添加constexpr却不被允许(§ 17.6.5.6)。与noexcept相比,无意中依赖于constexpr要容易得多。在后一种情况下,您必须使用类型特征和/或SFINAE来依赖异常规范。在前一种情况下,只需键入constexpr float f = std :: sin(32.5f);。如果编译成功,则已经意外地将代码绑定到实现细节上。” - Nicol Bolas
1
@KABoissonneault:简化到最简单的例子:static_assert(noexcept(std::some::function ()),"nope")。我认为这取决于实现,它是否会编译是值得怀疑的,因为(根据我的理解)禁止添加 constexpr 的原则是相同的。 - peppe
@peppe:有些人似乎认为,对于包含模板的任何源代码集,只应该考虑一个正确的扩展。我个人认为,更有帮助的做法是允许在某些情况下可能存在多个正确的扩展,编译器可以随意选择其中之一(在这种情况下,是否有些扩展被某些编译器视为有效而其他编译器则不重要,只要每个编译器选择了一个有效的扩展)。如果从程序员的角度来看,在某些情况下所有扩展都同样好,但是... - supercat
编译器可能有理由偏爱其中一种,让编译器使用最有利的版本可以启用比程序员猜测更有用的优化。 - supercat
1
注意,他们最初打算允许在 constexpr 中使用此功能。 - Shafik Yaghmour
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接