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 standarddraft 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的意见是:

08-27 22:04
查看更多