请参阅更新以获得更好的问题示例。原始代码有混合问题,使图片变得混乱:
这个问题为什么我可以在 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 函数的内建函数可以被视为常量表达式。
如果确实如此:
- 允许编译器这样做吗?
- 如果他们被允许,他们是否不必记录它以使其符合要求?
- 这是否可以被视为扩展,如果是这样,这似乎需要一个警告,因为C++ 草案标准部分
1.4
实施合规性第8段说(强调我的):
一个符合规范的实现可以有扩展(包括额外的库函数),只要它们不改变任何格式良好的程序的行为。需要实现来诊断使用根据本国际标准格式错误的扩展的程序。然而,这样做之后,他们可以编译和执行这样的程序。
更新
正如凯西指出的那样,原始问题中发生了一些事情,使其成为一个糟糕的例子。一个简单的例子是使用不是 constexpr 函数的std::pow :
#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 ) ;
^