根据C++标准,C++标准库的实现是否允许加强由标准定义的方法和其他函数的noexcept
规范?
例如,如果C++标准将某个函数std::f
指定为void f();
,那么标准库的实现是否允许将其实现为void f() noexcept;
?
根据C++标准,C++标准库的实现是否允许加强由标准定义的方法和其他函数的noexcept
规范?
例如,如果C++标准将某个函数std::f
指定为void f();
,那么标准库的实现是否允许将其实现为void f() noexcept;
?
标准答案是肯定的:
§ 17.6.5.12.1 异常处理限制 [res.on.exception.handling]
- C++标准库中定义的任何函数都可以通过抛出Throws:段描述的异常类型来报告失败。实现可能通过添加一个非抛出的noexcept-specification来加强非虚函数的异常规范。
[...]
- C++标准库中定义的析构函数不得引发异常。C++标准库中的每个析构函数都应该表现得像它有一个非抛出的异常规范一样。C++标准库中没有显式exception-specification的其他函数,除非另有规定,否则可能会引发实现定义的异常。实现可能通过添加显示的exception-specification来增强这个隐式的exception-specification。
(第4点似乎只是允许明确指定异常规范,并警告缺少显式异常规范意味着实现允许抛出任何东西)。
说实话,我不明白为什么这是允许的而添加constexpr
不是(§ 17.6.5.6)。它们看起来像同一枚硬币的两面——通过使用类型特征和SFINAE,您可以编写显示不同行为的代码,具体取决于您使用哪个标准库实现(如果它标记某些函数为noexcept
/constexpr
或如果它没有),这就打败了首先制定标准的目的...
constexpr float f = std :: sin(32.5f);
。如果编译成功,则已经意外地将代码绑定到实现细节上。” - Nicol Bolasstatic_assert(noexcept(std::some::function ()),"nope")
。我认为这取决于实现,它是否会编译是值得怀疑的,因为(根据我的理解)禁止添加 constexpr
的原则是相同的。 - peppe
noexcept
关键字更多地关注于如果栈中的某个调用者对编译器撒谎时该怎么做。 - Richard Hodgesnoexcept
只是一个函数契约,可以在代码内部进行检查。 “非抛出”函数的概念一直存在,但现在我们可以在代码中验证它,如果我们想要编写一些“异常不安全但更快”的代码。低级代码生成对我来说几乎无关紧要。 - KABoissonneault