是否是一个合格的编译器扩展来处理非constexpr标准库函数作为constexpr? [英] Is it a conforming compiler extension to treat non-constexpr standard library functions as constexpr?

查看:154
本文介绍了是否是一个合格的编译器扩展来处理非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函数,我们允许使用它们,其中需要一个常量表达式 www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf\">草案C ++ 11标准草案C ++ 14标准部分 7.1.5 [dcl.constexpr] :


[...]如果通过构造函数调用初始化,那么该调用应为
常数表达式(5.19)。否则,或者如果一个constexpr说明符是
用于一个引用声明,
中出现的每个完整表达式的初始化器应该是一个常量表达式。[...]


即使使用 -std = c ++ 14 -pedantic -std = c ++ 11 -pedantic 不生成警告( 查看实时 )。使用 -fno-builtin 会产生错误( see it live ),表示这些标准库函数的内置版本正在处理 constexpr



clang 任何我试过的标志的组合。



因此,这是一个 gcc 扩展,至少可以处理一些内置函数,如同它们是constexpr函数,即使标准没有明确要求他们。我希望至少在严格遵从模式下收到警告,这是否是一个合适的扩展?

解决方案

TL ; DR



在C ++ 14中,这是明确禁止的,虽然在 2011 像这种情况将被明确允许。目前尚不清楚,如果对于C ++ 11这是属于 as-if规则,我不会相信它,因为它改变了可观察的行为,但这一点在我下面提到的问题中没有澄清。



详细
$ b

这个问题的答案已经随着 LWG问题2013 ,其开头为:


假设某个函数未标记为constexpr在
标准中,但是,在某些特定的实现中,有可能
将其写入constexpr约束。如果实现者标记
这样的函数作为constexpr,是违反标准还是
是一个符合的扩展?


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



在2012年的协议,允许这种转移和提议改变,在C ++ 14这是一个不合格扩展。这反映在C ++ 14标准部分 17.6.5.6 [constexpr.functions] 草案中:


[...]一个实现不应该声明任何标准库函数
signature作为constexpr,除非那些显式
需要。 ..]


,虽然严格的读取这似乎留下了一些摆动的空间来处理内置隐式,就像是一个constexpr我们可以从问题中的以下引用看出,其目的是防止实现中的分歧,因为相同的代码在使用 SFINAE emphasis mine )时可能产生不同的行为: p>


向投票委员会提交全体委员会表示的一些关注
给WP的地位,这个问题已经解决不足
考虑到不同的库实现的后果,因为
用户可以使用SFINAE观察不同的行为,否则
相同的代码


我们可以从gcc错误报告 [C ++ 0x ] sinh vs asinh vs constexpr ,该小组依赖先前提出的 LWG 2013 a>其中:


[...]此外,一个实现可以声明任何函数为
constexpr定义满足必要的
约束[...]


符合模式。



据我所知,如果我们收到严格遵从模式的警告,即使用 -std = c ++ 11 -pedantic 或者在此模式下禁用。



注意,我在错误报告中添加了一条注释,



Jonathan Wakely 在另一个问题中指出最近的讨论,似乎很可能gcc错误报告将重新打开以解决此一致性问题。



什么about intrinsics



编译器内在性未涵盖通过标准,所以我可以告诉他们应该豁免这个规则,所以使用:

  static constexpr double a = __builtin_cos(3。);应该允许

。这个问题出现在bug报告中,DanielKrügler的意见是:


[...]库函数和其他内在函数可能是被视为
例外,因为它们不需要由
正常语言规则解释。



gcc compiles the following code without warning:

#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()
{
}

None of the standard library functions used above are constexpr functions, we are allowed to use them where a constant expression is required from both the draft C++11 standard and draft C++14 standard section 7.1.5 [dcl.constexpr]:

[...]If it is initialized by a constructor call, that call shall be a constant expression (5.19). Otherwise, or if a constexpr specifier is used in a reference declaration, every full expression that appears in its initializer shall be a constant expression.[...]

Even when using -std=c++14 -pedantic or -std=c++11 -pedantic no warnings are generated (see it live). Using -fno-builtin produces errors (see it live) which indicates that the builtin version of these standard library functions are being treated as if they where constexpr

While clang does not allow the code with any combination of flags I have tried.

So this is a gcc extension to treat at least some builtin functions as if they were constexpr functions even though the standard does not explicitly require them to be. I would have expected to at least receive a warning in strict conformance mode, is this a conforming extension?

解决方案

TL;DR

In C++14 this is explicitly not allowed, although in 2011 it appeared like this case would be explicitly allowed. It is unclear if for C++11 this fell under the as-if rule, I don't believe it does since it alters observable behavior but that point was not clarified in the issue I reference below.

Details

The answer to this question has shifted with the evolving status of LWG issue 2013 which opens with:

Suppose that a particular function is not tagged as constexpr in the standard, but that, in some particular implementation, it is possible to write it within the constexpr constraints. If an implementer tags such a function as constexpr, is that a violation of the standard or is it a conforming extension?

In C++11 it was unclear if the as-if rule permitted this but the orignal proposal would have explicitly allowed it once it was accepted and we can see below in the gcc bug report I reference, this was the assumption made by the gcc team.

The consensus to allow this shifted in 2012 and the proposal changed and in C++14 this is a non-conforming extension. This is reflected in the draft C++14 standard section 17.6.5.6 [constexpr.functions] which says:

[...]An implementation shall not declare any standard library function signature as constexpr except for those where it is explicitly required.[..]

and although a strict reading of this seems to leave some wiggle room for treating a builtin implicitly as if it were a constexpr we can see from the following quote in the issue that the intention was to prevent divergence in implementations since identical code could produce different behavior when using SFINAE (emphasis mine):

Some concern expressed when presented to full committee for the vote to WP status that this issue had been resolved without sufficient thought of the consequences for diverging library implementations, as users may use SFINAE to observe different behavior from otherwise identical code.

We can see from the gcc bug report [C++0x] sinh vs asinh vs constexpr that the team relied on the earlier proposed resolution of LWG 2013 which says:

[...]Additionally, an implementation may declare any function to be constexpr if that function's definition satisfies the necessary constraints[...]

when deciding whether this change for the math functions was allowed in strict conformance mode.

As far as I can tell this would become conforming if this we received a warning in strict conformance mode i.e. using -std=c++11 -pedantic or if it was disabled in this mode.

Note, I added a comment to the bug report explaining that the resolution changed since this issue was originally addressed.

Jonathan Wakely pointed out in another question a more recent discussion and it seems likely the gcc bug report will be reopened to address this conformance issue.

What about intrinsics

Compiler intrinsics are not covered by the standard and so as far as I can tell they should be exempt from this rule, so using:

static constexpr double a = __builtin_cos(3.);

should be allowed. This question came up in the bug report and opinion of Daniel Krügler was:

[...]Library functions and other intrinsics can probably be considered as exceptions, because they are not required to be "explainable" by normal language rules.

这篇关于是否是一个合格的编译器扩展来处理非constexpr标准库函数作为constexpr?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆