它是一个符合标准的编译器扩展,将非constexpr标准库函数视为constexpr吗?

它是一个符合标准的编译器扩展,将非constexpr标准库函数视为constexpr吗?

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功能,我们允许使用它们,其中一个常量表达式从两个需要草案C ++ 11标准草案C ++ 14标准7.1.5 [dcl.constexpr] 

[...]如果它是由构造函数调用初始化的,那么该调用应该是一个常量表达式(5.19)。否则,或者如果在引用声明中使用constexpr说明符,则其初始值设定项中出现的每个完整表达式都应为常量表达式。[...]

即使使用-std=c++14 -pedantic 或-std=c++11 -pedantic没有生成警告(请参见实时)。使用-fno-builtin产生错误(参见实时),表明这些标准库函数的内置版本被视为constexpr

虽然clang不允许使用任何标志组合的代码我尝试过。

所以这是一个gcc扩展来处理至少一些内置函数,好像它们是constexpr函数,即使标准没有明确要求它们。我本来期望至少在严格的一致性模式下收到警告,这是一个符合标准的扩展吗?


慕桂英4014372
浏览 686回答 2
2回答

拉风的咖菲猫

在C ++ 14中,这显然是不允许的,尽管在2011这种情况下似乎是明确允许的。目前还不清楚C ++ 11&nbsp;是否属于as-if规则,我不相信它会改变,因为它会改变可观察的行为,但这一点在我在下面引用的问题中并未澄清。细节这个问题的答案随着2013年LWG问题的演变而变化,该问题开始于:假设特定函数未在标准中标记为constexpr,但在某些特定实现中,可以在constexpr约束内编写它。如果实施者标记constexpr这样的功能,是违反标准还是符合标准的扩展?在C ++ 11中,不清楚as-if规则是否允许这样做,但是orignal提议一旦被接受就明确允许它,我们可以在下面的gcc bug报告中看到我引用,这是gcc做出的假设球队。允许这种转变的共识在2012年发生了变化并且提案发生了变化,而在C ++ 14中,这是一个不合规的扩展。这反映在草案C ++ 14标准部分17.6.5.6&nbsp;[constexpr.functions]中,该部分说:[...]实现不得将任何标准库函数签名声明为constexpr,除非明确要求它。[...]虽然严格阅读这个内容似乎留下了一些回避处理内置因素的余地,好像它是一个constexpr我们可以从问题中的以下引用中看出,目的是防止实现中的分歧,因为相同的代码可能会产生不同的行为使用SFINAE时(强调我的):当向完全委员会提交对WP状态的投票时表达了一些担忧,即在没有充分考虑图书馆实施不同的后果的情况下解决了这个问题,因为用户可能会使用SFINAE来观察其他相同代码的不同行为。我们可以从gcc bug报告[C ++ 0x] sinh vs asinh vs constexpr看到该团队依赖早先提出的LWG 2013决议,其中说:[...]此外,如果该函数的定义满足必要的约束,则实现可以声明任何函数为constexpr [...]在确定是否允许在严格一致性模式下对数学函数进行此更改时。据我所知,如果我们在严格的一致性模式下收到警告,即使用-std=c++11 -pedantic或者在此模式下被禁用,这将符合要求。请注意,我在错误报告中添加了一条评论,解释说自从此问题最初解决后,解决方案已更改。Jonathan Wakely&nbsp;在另一个问题中指出了一个更近期的讨论,似乎可能会重新打开gcc bug报告来解决这个一致性问题。本质上怎么样?编译器内在函数不在标准范围内,因此,据我所知,它们应该免于此规则,因此使用:static&nbsp;constexpr&nbsp;double&nbsp;a&nbsp;=&nbsp;__builtin_cos(3.);应该被允许。这个问题出现在错误报告中,DanielKrügler的意见是:[...]库函数和其他内在函数可能被视为异常,因为它们不需要通过常规语言规则“解释”。

RISEBY

我不认为谈论编译器内在函数是有帮助的。所有以名称开头的名称__都保留用于实现,并且实现定义了它们的语义。对于特定于实现的函数的语义是完全合理的,无论它们是否是内在的,都被定义为constexpr纯粹由实现者自行决定。
打开App,查看更多内容
随时随地看视频慕课网APP