gcc
编译以下代码而不会发出警告:
#include <cmath>
struct foo {
static constexpr double a = std::cos(3.);
static constexpr double c = std::exp(3.);
static constexpr double d = std::log(3.);
static constexpr double e1 = std::asin(1.);
static constexpr double h = std::sqrt(.1);
static constexpr double p = std::pow(1.3,-0.75);
};
int main()
{
}
上面使用的标准库函数都不是constexpr函数,在the draft C++11 standard和draft C++14 standard部分
7.1.5
[dcl.constexpr]中都需要常量表达式的地方,我们可以使用它们:即使使用
-std=c++14 -pedantic
或-std=c++11 -pedantic
,也不会生成警告(see it live)。使用-fno-builtin
会产生错误(see it live),这表明这些标准库函数的builtin版本将被视为constexpr虽然
clang
不允许代码与我尝试过的标志进行任何组合。因此,这是一个
gcc
扩展名,即使标准没有明确要求它们,也至少会将某些内置函数视为constexpr函数。我本来希望至少在严格一致性模式下收到警告,这是否是一致性扩展? 最佳答案
TL; DR
在C++ 14中,这是明确不允许的,尽管在2011
中看起来像是这种情况将被明确允许。目前尚不清楚对于C++ 11是否属于as-if rule,我不相信,因为它改变了可观察的行为,但是我在下面引用的问题中没有阐明这一点。
细节
这个问题的答案随着LWG issue 2013的发展状态而发生了变化,其开头是:
在C++ 11中,尚不清楚as-if规则是否允许这样做,但是原始提议一旦被接受便会明确允许它,我们可以在下面我引用的gcc bug报告中看到,这是gcc所做的假设球队。
允许这样做的共识在2012年发生了变化,提案也发生了变化,而在C++ 14中,这是一个不一致的扩展。这在C++ 14标准草案17.6.5.6
[constexpr.functions]中得到反射(reflect),其中说:
尽管对此进行严格的阅读似乎为隐式地将内置函数当作constexpr留下了一些摆动的空间,但我们可以从以下引文中看到,该问题的目的是防止实现中的差异,因为相同的代码可能会产生不同的行为使用SFINAE(强调我的)时:
从gcc错误报告[C++0x] sinh vs asinh vs constexpr中我们可以看到,该团队依赖于较早提出的LWG 2013解决方案,其中指出:
决定在严格一致性模式下是否允许对数学函数进行此更改。
据我所知,如果这是在严格符合性模式下收到的警告,即使用-std=c++11 -pedantic
或在此模式下已禁用,则将变为符合性。
注意,我在错误报告中添加了一条注释,解释说自最初解决此问题以来,解决方案已更改。
Jonathan Wakely pointed out在另一个问题中是最近的discussion,看来gcc错误报告可能会重新打开以解决此一致性问题。
那内在函数呢
Compiler intrinsics不在标准范围之内,据我所知,应免除此规则,因此请使用:
static constexpr double a = __builtin_cos(3.);
应该被允许。这个问题出现在错误报告中,DanielKrügler的意见是: