<cmath> 函数在 C++17 中必须是 `noexcept` 吗?

Are <cmath> functions required to be `noexcept` in C++17?

在优化代码的某些部分时,我决定检查是否可以将某些方法声明为 noexcept,这归结为我对 <cmath>.[=24 中的数学函数的不完整了解=]

因此,我决定检查我使用的 sin()asin()(作为示例)是否实际上是 noexcept

static_assert(noexcept(asin(1)));
static_assert(noexcept(sin(1)));

顺利通过,所以他们其实是noexcept。我也在标准库实现中查看了相应的定义:

template <class _A1>
inline _LIBCPP_INLINE_VISIBILITY
typename std::enable_if<std::is_integral<_A1>::value, double>::type
asin(_A1 __lcpp_x) _NOEXCEPT {return ::asin((double)__lcpp_x);}

这证实了它们的 noexceptness,至少在我目前使用的实现中是这样。

但是,我无法找到如果那是有保证的行为,比如说,标准要求的。所以,我想知道它是否是必需的行为。如果不是,那么不要求他们 noexcept 的动机是什么?

我的usual reference cppreference.com does not list noexcept for those functions (see this, in comparison)。可能,这里有些混乱来自与 C 的兼容性;但是,我找不到令人信服的逻辑,因为 <cmath> 显然使用 C++ headers,而不是 C-compatibility。

[res.on.exception.handling]/5 状态:

An implementation may strengthen the exception specification for a non-virtual function by adding a non-throwing exception specification.

它们不需要成为noexcept,但是允许实施来标记它们noexcept .您所看到的是您的实现选择将它们标记为这样,但 cppreference 没有标记它们,因为它们不是必需的。

And if it is not, what is the motivation of not requiring them to be noexcept?

通常的 Lakos 规则适用 - 其中一些函数具有狭窄的契约,因此实现可以假设地选择抛出契约等。