[英]Is gcc considering builtins of non-constant expression functions to be constant expressions
请参阅更新以获得更好的问题示例。 原始代码有各种各样的问题,使图片混乱 :
这个问题为什么我可以在constexpr函数中调用非constexpr函数? 提出了以下代码
#include <stdio.h>
constexpr int f()
{
return printf("a side effect!\n");
}
int main()
{
char a[f()];
printf("%zd\n", sizeof a);
}
我回答的是格式不正确但gcc 4.8.2
允许它( 现场直播 )。
但是,如果我们使用-fno-builtin
标志, gcc
生成错误( 请参见实时 ):
error: call to non-constexpr function 'int printf(const char*, ...)'
return printf("a side effect!\n");
^
所以seems
gcc
正在考虑将其内置版本的printf
作为一个常量表达式。 gcc
文件在这里构建,但没有记录这种情况,其中非constexpr函数的内置可以被认为是常量表达式。
如果确实如此:
1.4
节实施合规性第8段说( 强调我的 ): 符合条件的实现可能具有扩展(包括其他库函数),前提是它们不会改变任何格式良好的程序的行为。 需要实现来诊断使用根据本国际标准格式不正确的扩展的程序 。 但是,这样做之后,他们就可以编译和执行这样的程序。
更新
正如凯西所指出的那样,原始问题中有一些事情会使它成为一个糟糕的例子。 一个简单的例子是使用std :: pow ,它不是constexpr函数:
#include <cmath>
#include <cstdio>
constexpr double f()
{
return std::pow( 2.0, 2.0 ) ;
}
int main()
{
constexpr double x = f() ;
printf( "%f\n", x ) ;
}
编译和构建时没有任何警告或错误( 请参见实时 ),但添加-fno-builtin
会使其生成错误( 请参见实时 )。 注意: 为什么数学函数不是c ++ 11中的constexpr :
error: call to non-constexpr function 'double pow(double, double)'
return std::pow( 2.0, 2.0 ) ;
^
是的, gcc
正在考虑将一些内置函数作为constexpr,即使标准没有明确标记它们。 我们可以在gcc
错误报告[C ++ 0x] sinh vs asinh vs constexpr中找到与cmath
中的数学函数有关的讨论,其中说:
LWG 2013似乎确实允许GCC将这些功能视为constexpr。 所以,固定为4.7
这是指2013年的LWG问题,其最初提议的决议是将以下内容添加到第17.6.5.6
节[constexpr.functions] ( 强调我的未来 ):
[...]此外,如果该函数的定义满足必要的约束,则实现可以声明任何函数为constexpr [...]
但是在C ++ 11之后,分辨率被颠倒了,最终的分辨率结束为:
[...]实现不得将任何标准库函数签名声明为constexpr,除非明确要求它。[...]
所以这是( 在C ++ 14中 ) 一个显式不符合的扩展 ,据我所知,这在C ++ 11中是不符合的,因为它改变了可观察的行为,因此不允许通过as-if规则 。
Jonathan Wakely指出了一个libstdc++
邮件列表讨论: PR libstdc ++ / 49813重新访问:constexpr on functions(和builtins) ,由于上面列出的问题,讨论了重新打开上面提到的错误报告:
我相信我们应该根据LWG 2013的实际解决方案重新打开这个bug(禁止添加constexpr)。
FE不应该在严格一致性模式下将builtins视为constexpr。
我们应该完全从<cmath>中删除_GLIBCXX_CONSTEXPR,或者使其成为__STRICT_ANSI__的条件。
GCC 不考虑f()
是一个常量表达式。 查看您链接的第一个示例程序的诊断信息:
main.cpp: In function 'int main()': main.cpp:10:19: warning: ISO C++ forbids variable length array 'a' [-Wvla] char a[f()]; ^
编译器不认为f()
是一个常量表达式,程序实际上是使用GCC的扩展,它允许可变长度数组 - 具有非常量大小的数组。
如果更改程序以强制f()
为常量表达式:
int main() {
constexpr int size = f();
char a[size];
printf("%zd\n", sizeof a);
}
GCC报告错误 :
main.cpp: In function 'int main()': main.cpp:10:32: in constexpr expansion of 'f()' main.cpp:5:41: error: 'printf(((const char*)"a side effect!\012"))' is not a constant expression return printf("a side effect!\n"); ^
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.