constexpr上下文中constexpr函数内的所有函数都必须是constexpr函数吗?

cam*_*ino 5 c++

在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函数,尽管在这个测试中它不会被调用.

Jan*_*ans 6

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).