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

时间:2018-10-24 01:49:47

标签: 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
}

但是在以下测试中:

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

在这里,bar是非constexpr函数。 我想知道为什么constexpr上下文中允许使用非constexpr函数,尽管在此测试中未调用该函数。

2 个答案:

答案 0 :(得分: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)的调用并不如此。

答案 1 :(得分:-1)

使用c ++ 14标准来编译代码:

$ 
$ g++ main.cpp -std=c++14
$ ./a.out
1
$ cat main.cpp
//
//  main.cpp
//
//
//  Created by myhaspl on 2018/10/24.
//  myhaspl@myhaspl.com.
//

#include <iostream>
using namespace std;

void bar(){}

constexpr int foo(int a)
{
    if (a <=0 )
        bar();

    return 1;
}

int main()
{
    int a1[2]={0,1};

    cout<<a1[foo(-1)]<<endl;
}