Bar*_*rry 7 c++ language-lawyer c++17
作为这个问题的后续,gcc和clang都认为这个程序格式不正确:
int main() {
const int& ri = 0;
constexpr int i = ri;
}
Run Code Online (Sandbox Code Playgroud)
该错误是关于ri
在常量表达式中不可用的值.0
肯定是一个核心常量表达式,并且作为一个prvalue核心常量表达似乎满足这些约束(int
通常,因为不是类,指针或数组类型).所以不应该ri
满足这个标准?
如果我使用类类型的prvalue文字,情况也是如此:
struct X { };
int main() {
const X& rx = X{};
constexpr X x = rx;
}
Run Code Online (Sandbox Code Playgroud)
在这个声明中:
const int& ri = 0;
Run Code Online (Sandbox Code Playgroud)
0
是一个prvalue,但ri
没有从该prvalue初始化.prvalue首先进行临时实现转换,并且引用绑定到生成的glvalue.由于ri
绑定到这个物化的glvalue,而不是像你(I)所怀疑的那样直接与prvalue绑定,相关的限制不是prvalue核心常量表达式限制(它0
确实满足)而是glvalue核心常量表达式限制 - 实体是持续表达的允许结果.这种限制,略微提高了清晰度,是:
具有静态存储持续时间的对象是:
- 不是临时对象,或
- 一个临时对象,其值满足上述约束条件,
或者它是一个功能.
我们glvalue 是一个临时的对象,其值满足"上述约束"("以上",这里指的是prvalue核心不变的限制,这int
平凡的满足),但它并没有具有静态存储持续时间.
没有静态存储持续时间→实体不是常量表达式的允许结果→glvalue表达式不是常量表达式→ ri
没有用常量表达式初始化→ ri
不能用于核心常量表达式→声明i
是病态的.
同样的论点也适用于适当的类类型.
小智 1
正如您所指出的,2.11 规定核心常量表达式不得计算为:
引用引用类型的变量或数据成员的 id 表达式,除非引用具有前面的初始化并且
- 它用常量表达式初始化或
进一步的 expr.const#6:
常量表达式可以是泛左值核心常量表达式,它引用作为常量表达式(如下定义)允许的结果的实体,也可以是纯右值核心常量表达式,其值满足以下约束:
...
如果实体是具有静态存储持续时间的对象,并且不是临时对象或者是值满足上述约束的临时对象,或者是函数,则该实体是常量表达式的允许结果。
从我的阅读来看,这意味着(用 X 代替某种类型)的 RHSconst X& r =
必须是具有静态存储持续时间的对象或满足上述条件的临时对象。由于 anint
不适合类类型、指针类型或类/数组类型的对象,因此它不符合条件。
归档时间: |
|
查看次数: |
228 次 |
最近记录: |