在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函数,尽管在此测试中未调用该函数。
答案 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;
}