作为
this question的后续,gcc和clang都认为这个程序格式不正确:
int main() { const int& ri = 0; constexpr int i = ri; }
该错误是关于ri在常量表达式中不可用的值. 0肯定是核心常量表达式,并且作为prvalue核心常量表达式似乎满足these constraints(通常,因为int不是类,指针或数组类型).所以不应该满足this criteria?
如果我使用类类型的prvalue文字,情况也是如此:
struct X { }; int main() { const X& rx = X{}; constexpr X x = rx; }
解决方法
在这个声明中:
const int& ri = 0;
0是prvalue,但ri未从该prvalue初始化. prvalue首先经历temporary materialization conversion并且参考被绑定到所得到的glvalue.由于ri绑定到这个物化的glvalue,而不是像你(I)怀疑的那样直接与prvalue绑定,相关的限制不是prvalue核心常量表达式限制(0确实满足),而是glvalue核心常量表达式限制 – 即实体是permitted result of a constant expression.这个限制,略有改进的清晰度,是:
either an object with static storage duration that is:
- not a temporary object,or
- a temporary object whose value satisfies the above constraints,
or it is a function.
我们的glvalue是一个临时对象,其值满足“上述约束”(这里指的是“上面”指的是prvalue核心常量限制,它通常很满足),但它没有静态存储持续时间.
没有静态存储持续时间→实体不是常量表达式的允许结果→glvalue表达式不是常量表达式→ri未使用常量表达式初始化→ri不能用于核心常量表达式→声明我是不正确的.
同样的论点也适用于适当的类类型.