In this statement:
const int& ri = 0;
0
is a prvalue, but ri
isn't initialized from that prvalue. The prvalue first undergoes a temporary materialization conversion and the reference is bound to the resulting glvalue. Since ri
is bound to this materialized glvalue, and not directly to the prvalue like you (I) suspected, the relevant restrictions are not the prvalue core constant expression restrictions (which 0
does satisfy) but rather the glvalue core constant expression restrictions - that the entity be a permitted result of a constant expression. That restriction, spelled with slightly improved clarity, is:
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.
Our glvalue is a temporary object whose value satisfies "the above constraints" ("above" here referring to the prvalue core constant restrictions, which int
trivially satisfies), but it does not have static storage duration.
Not having static storage duration → the entity is not a permitted result of a constant expression → the glvalue expression not a constant expression → ri
wasn't initialized with a constant expression → ri
can't be used in a core constant expression → the declaration of i
is ill-formed.
The same argument holds for appropriate class types as well.