为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C++
慕桂英4014372 2019-08-28 14:11:25
它是一个符合标准的编译器扩展,将非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函数,即使标准没有明确要求它们。我本来期望至少在严格的一致性模式下收到警告,这是一个符合标准的扩展吗?
查看完整描述

2 回答

?
拉风的咖菲猫

TA贡献1995条经验 获得超2个赞

在C ++ 14中,这显然是不允许的,尽管在2011这种情况下似乎是明确允许的。目前还不清楚C ++ 11 是否属于as-if规则,我不相信它会改变,因为它会改变可观察的行为,但这一点在我在下面引用的问题中并未澄清。

细节

这个问题的答案随着2013年LWG问题的演变而变化,该问题开始于:

假设特定函数未在标准中标记为constexpr,但在某些特定实现中,可以在constexpr约束内编写它。如果实施者标记constexpr这样的功能,是违反标准还是符合标准的扩展?

在C ++ 11中,不清楚as-if规则是否允许这样做,但是orignal提议一旦被接受就明确允许它,我们可以在下面的gcc bug报告中看到我引用,这是gcc做出的假设球队。

允许这种转变的共识在2012年发生了变化并且提案发生了变化,而在C ++ 14中,这是一个不合规的扩展。这反映在草案C ++ 14标准部分17.6.5.6 [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 在另一个问题中指出了一个更近期的讨论,似乎可能会重新打开gcc bug报告来解决这个一致性问题。

本质上怎么样?

编译器内在函数不在标准范围内,因此,据我所知,它们应该免于此规则,因此使用:

static constexpr double a = __builtin_cos(3.);

应该被允许。这个问题出现在错误报告中,DanielKrügler的意见是:

[...]库函数和其他内在函数可能被视为异常,因为它们不需要通过常规语言规则“解释”。


查看完整回答
反对 回复 2019-08-28
?
RISEBY

TA贡献1856条经验 获得超5个赞

我不认为谈论编译器内在函数是有帮助的。所有以名称开头的名称__都保留用于实现,并且实现定义了它们的语义。对于特定于实现的函数的语义是完全合理的,无论它们是否是内在的,都被定义为constexpr纯粹由实现者自行决定。

查看完整回答
反对 回复 2019-08-28
  • 2 回答
  • 0 关注
  • 685 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信