b1s*_*sub 13 c++ language-lawyer c++17
b此代码中的表达式应为核心常量表达式
int main()
{
constexpr int a = 10;
const int &b = a;
constexpr int c = b; // here
return 0;
}
Run Code Online (Sandbox Code Playgroud)
由于标准说(8.20,第2段[expr.const]在N4700)
表达式
e是核心常量表达式,除非评估e将评估以下表达式之一:
...
除非适用,否则左值 - 右值转换(7.1)
...
非易失性glvalue,引用constexpr定义的非易失性对象,或引用此类对象的不可变子对象,或者
首先,b上面代码中的表达式是一个左值(也是一个glvalue),因为它是一个引用,因此是一个变量(8.1.4.1,第1段[expr.prim.id.unqual]):
如果实体是函数,变量或数据成员,则表达式是左值 ,否则为prvalue; 如果标识符指定位字段(11.5),则它是位字段.
其次,变量b表示的对象是a,并且声明了它constexpr.但是,gcc抱怨道
./hello.cpp: In function ‘int main()’:
./hello.cpp:6:20: error: the value of ‘b’ is not usable in a constant expression
constexpr int c = b;
^
./hello.cpp:5:13: note: ‘b’ was not declared ‘constexpr’
const int &b = a;
Run Code Online (Sandbox Code Playgroud)
据我所知,引用不是一个对象,所以上面的子弹显然表明a应该声明constexpr.我错过了什么吗?我不同意gcc的原因是gcc将其b视为一个对象,因此需要将其声明为constexpr.但是,b不是一个对象!
Bar*_*rry 13
核心常量表达式的一个规则是我们无法评估:
一个id-expression,引用引用类型的变量或数据成员,除非引用具有先前的初始化和任何一个
- 它是用常量表达式初始化的
- 它的生命始于e的评价范围内;
b是一个id-expression,它引用具有前面初始化的引用类型的变量.但是,它是从初始化a.是a一个不变的表达?来自[expr.const]/6:
甲常量表达式可以是一个glvalue芯常量表达式指的是一个常量表达式的结果允许的实体(如下面所定义),或一个prvalue芯常数表达式,其值满足以下约束条件:[...]
如果实体是具有静态存储持续时间的对象,则该实体是常量表达式的允许结果,该对象不是临时对象,或者是其值满足上述约束的临时对象,或者它是函数.
a是glvalue核心常量表达式(它没有达到expr.const/2中的任何限制),但它不是具有静态存储持续时间的对象.它也不是一种功能.
因此,a不是一个恒定的表达.并且b,作为结果,不从常量表达式初始化,并且因此不能在核心常量表达式被使用.因此c,初始化是不正确的,因为它不是一个恒定的表达式.声明a为a static constexpr int,gcc和clang都接受该程序.
C++,你是神奇的野兽.
| 归档时间: |
|
| 查看次数: |
1211 次 |
| 最近记录: |