n 4527 5.20[表达式常数]p2
条件表达式 e 是核心常量表达式,除非按照抽象机器 (1.9) 的规则对 e 进行计算,否则将计算以下表达式之一:
(2.7) — 左值到右值的转换 (4.1),除非它应用于
(2 . 7 . 1)-整数或枚举类型的非易失性glvalue,它引用一个完整的非易失性const对象,该对象具有一个在先初始化,用常量表达式初始化,或
(2.7.2) — 引用字符串文本 (2.13.5) 的子对象的非易失性 gl值,或
(2.7.3)-非易失性glvalue,指用constexpr定义的非易失对象,或指此类对象的不可变子对象,或
(2.7.4) — 文字类型的非易失性 gl值,指的是其生命周期始于 e 评估的非易失性对象;
5.20[expr.const]p5
常量表达式是一个glvalue核心常量表达式,其值引用的实体是常量表达式(定义如下)的允许结果,或者是一个prvalue核心常量表达,其值是一个对象,对于该对象及其子对象:
— 引用类型的每个非静态数据成员都引用一个实体,该实体是常量表达式的允许结果,并且
-如果对象或子对象是指针类型,则它包含具有静态存储持续时间的对象的地址、超过该对象结尾的地址(5.7)、函数的地址或空指针值。
如果实体是具有静态存储持续时间的对象,不是临时对象,或者是其值满足上述约束的临时对象,或者它是一个函数,则该实体是常量表达式的允许结果。
void foo(){
const int a = 1;//a has automatic storage duration
int b[a]{};
}
在intb[a]{}
,a
是一个id表达式,a
这是对glvalue积分常量表达式是常量表达式吗?
可以是prvalue核心常量表达式,但不能是glvalue核心常量,这也不可能。你已经在标准中找到了措辞,所以也许最好解释一下为什么规则是这样的。
void foo(){
const int a = 1;//a has automatic storage duration
static constexpr const int &ra = a;// cannot possibly be valid
}
这是无效的,因为它要求在调用foo
之前知道a的地址,然后才有任何
a
。
你的int b[a]{};
很好,因为它使用a作为prvalue核心常量表达式:它不关心
a
存储在哪里,它只关心它有什么值。