请参阅更新以获得更好的问题示例。原始代码有各种各样的问题混淆了图片:
此问题Why can I call a non-constexpr function inside a constexpr function?提供了以下代码
#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
允许它( see it live )。
但是,如果我们使用-fno-builtin
标记gcc
生成错误( see it live ):
error: call to non-constexpr function 'int printf(const char*, ...)'
return printf("a side effect!\n");
^
所以seems
gcc
正在考虑将printf
的内置版本作为常量表达式gcc
。 1.4
documents builtins here但未记录此情况,其中非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 ) ;
}
实施合规性段 8 说(强调我的):符合要求的实现可能具有扩展(包括其他库函数),前提是它们不会改变任何格式良好的程序的行为。 根据本国际标准诊断使用此类扩展的程序需要实施。但是,这样做之后,他们就可以编译和执行这些程序。
更新
正如凯西所指出的那样,原始问题中有一些事情发生,这使得它成为一个糟糕的例子。一个简单的例子是使用std::pow,它不是constexpr函数:
-fno-builtin
编译和构建时没有任何警告或错误( see it live )但添加error: call to non-constexpr function 'double pow(double, double)'
return std::pow( 2.0, 2.0 ) ;
^
会导致生成错误( see it live )。注意:why math functions are not constexpr in C++11:
{{1}}
答案 0 :(得分:6)
是的,gcc
正在考虑将某些builtin functions视为 constexpr ,即使标准没有明确标记它们。我们可以在cmath
错误报告[C++0x] sinh vs asinh vs constexpr中找到与gcc
中的数学函数相关的讨论,其中包含:
LWG 2013似乎确实允许GCC将这些功能视为constexpr。 所以,固定为4.7
指的是LWG issue 2013,其原始提议的解决方案是将以下内容添加到17.6.5.6
[constexpr.functions] 部分(强调我的前进 EM>):
[...]此外,实施可以声明任何功能 constexpr如果该函数的定义满足必要的 约束[...]
但是在C ++ 11之后,分辨率被颠倒了,最终的分辨率结束为:
[...]实现不得声明任何标准库函数 签名为constexpr,除非是明确的签名 必需的。[..]
所以这是目前(在C ++ 14 中)a explicitly non-conforming extension并且据我所知,这在C ++ 11中是不符合的,因为它改变了可观察的行为,因此不允许通过 as-if规则。
Jonathan Wakely指出libstdc++
邮件列表讨论:PR libstdc++/49813 revisited: constexpr on functions (and builtins)由于上述问题,我们重新讨论了上述错误报告:
我相信我们应该根据实际的分辨率重新打开这个错误 LWG 2013(禁止添加constexpr)。
富裕不应该将内含者视为严格一致的constexpr 模式。
我们应该从&lt; cmath&gt;中删除_GLIBCXX_CONSTEXPR。完全或 以__STRICT_ANSI __。
为条件
答案 1 :(得分:4)
GCC 不认为f()
是一个常量表达式。查看the first sample program you linked的诊断信息:
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);
}
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"); ^