首页 > 解决方案 > constexpr 上下文中的 constexpr 函数内的所有函数都必须是 constexpr 函数吗?

问题描述

在 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
}

但在以下测试中:

int main()
{
    int a2[foo(1)];  //no compile error
}

这里, bar 是非常量表达式函数。我想知道为什么在 constexpr 上下文中允许使用非 constexpr 函数,尽管在这个测试中它没有被调用。

标签: c++

解决方案


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)


推荐阅读