我从这个页面注意到,C++11中的数学函数似乎都没有使用constexpr,而我认为它们所有的函数都可以使用constexpr。那么这就让我有两个问题,一个是他们为什么选择不将函数定义为constexpr。第二个对于像sqrt
这样的函数,我可能可以编写自己的constexpr版本,但对于sin或cos之类的函数会更加困难,所以是否有其他方法解决。
实际上,由于旧有且烦人的遗留问题,几乎所有数学函数都不能被constexpr
化,因为它们都会在各种错误条件下产生副作用,通常是域错误,并设置errno
。
errno
确实不是一个好的理由。 - Marc Glisseerrno
是两种非常不同的东西。C标准数学函数的规定是修改errno
,而不是抛出异常。因此,我不明白你的观点。 - Sebastian Redl来自B. Stroustrup的《C++编程语言(第4版)》描述C++11:
"要在编译时进行评估,函数必须足够简单:constexpr函数必须由单个返回语句组成;不允许循环和局部变量。此外,constexpr函数可能没有副作用。"
这意味着它必须是内联的,不能有for、while和if语句以及局部变量。副作用也是被禁止的(例如更改errno)。另一个问题是大多数数学函数都是FPU指令,而这些指令在纯c/c++中没有表示(它们是用汇编代码编写的)。这就是为什么没有任何cmath函数被声明为constexpr的原因。
errno
是主要原因,不确定你的回答是否添加了其他重要信息。 - aaronmanawsome::sqrt(3e13)
。你尝试过实现sin、cos、tanh或类似的函数吗?我知道有算法可以实现这些函数,但你认为 constexpr_sin(x) == sin(x)
吗? - Adam Szajsmath::cos(20.)
。余弦值大于3……实现一个像样的非constexpr
三角函数已经很难了,更不用说constexpr
了。 - Ruslan<stdexcept>
,因此需要进行调整才能编译;2)似乎只做了微不足道的范围缩减,因此例如 compile_time::cos(200.)
在 x86_64 gcc 上与 std::cos(200.)
差别很大,而对于参数为 2.
的情况结果则更或多或少相同。对于 long double
来说更糟糕。但是,它确实至少尝试进行范围缩减,不像 static_math
。 - Ruslan2 ** 17
ULP的误差,这对于IEEE754 64位double
不太好。 - Ruslan
constexpr
函数高效地实现。至少在C++11中对constexpr
函数的限制下是如此。另一方面,数学函数是一个非常著名的有限函数集,编译器可以很容易地提供它们作为内置函数并在编译时进行求值。这种核心语言特性和库函数的混合可能被认为是丑陋的,但也值得一试。另请参见Alisdair Meredith在CppCon 2014上的演讲。 - 5gon12eder