在ubuntu gcc 8.0中:
void bar(){}
constexpr int foo(int a)
{
if (a <=0 )
bar();
return 1;
}
int main()
{
int a1[foo(-1)]; //will give a compile error, which is expected,
//since non-constexpr function is not allowd in constexpr context
}
Run Code Online (Sandbox Code Playgroud)
但在以下测试中:
int main()
{
int a2[foo(1)]; //no compile error
}
Run Code Online (Sandbox Code Playgroud)
这里,bar是非constexpr功能.我想知道为什么在constexpr上下文中允许非constexpr函数,尽管在这个测试中它不会被调用.
constexpr上下文中constexpr函数内的所有函数都必须是constexpr函数吗?
这取决于.
在函数中允许调用非constexpr函数的事实constexpr并不意味着对constexpr函数的所有可能调用都必须导致常量表达式,但对于需要常量表达式的上下文(如数组边界),调用到constexpr函数的值必须为常量表达式
本案标准的相关部分是:
[dcl.constexpr]/5
对于既不是默认也不是模板的constexpr函数或constexpr构造函数,如果不存在参数值,则函数或构造函数的调用可以是核心常量表达式的评估子表达式(8.20),或者对于构造函数,某些对象的常量初始化程序(6.6.2),程序格式错误,无需诊断.
[expr.const]/2
表达式e是核心常量表达式,除非根据抽象机器(4.6)的规则评估e将评估以下表达式之一:
- (2.2)为一个文字类,一个constexpr函数或一个简单的析构函数的隐式调用调用一个constexpr构造函数以外的函数[...]
这意味着一个constexpr函数可以在其体上调用非constexpr函数,只要存在一些参数,它们将其计算为常量表达式或子表达式,这就是为什么可以将其foo(1)用作数组绑定的值的原因,因为对它的评价并不涉及到呼叫bar()这是不是情况foo(-1).