Reputation: 81
int aaa;
int& v = aaa;
int& rf = v;
constexpr int& crf = rf;
int main(){
}
I'm wondering why all compilers do agree on this example is well-formed? Isn't a constexpr variable should have a value that can be known during compiler time? Since the value of aaa
has an Indeterminate value, why can this example be accepeted by compilers?
Upvotes: 3
Views: 102
Reputation: 7369
For this example, it appears to me it's equivalent to ask why the variable rf
could be used in a constant expression. As per [dcl.constexpr#10], the full-expression of the initialization of crf
should be a constant expression. According to [expr.const#11]
A constant expression is either a glvalue core constant expression that refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints
An entity is a permitted result of a constant expression if it is an object with static storage duration that either is not a temporary object or is a temporary object whose value satisfies the above constraints, or if it is a non-immediate function.
In this case, since the reference binding should be bound to a glvalue, hence rf
shall be a glvalue core constant expression; Since rf
refers to the object aaa
that has a static storage duration, hence we only should check whether rf
is core constant expression, which is determined by [expr.const#5]. Since rf
is an id-expression of reference type, hence it shall satisfy [expr.const#5.12]
an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization and either
- it is usable in constant expressions or
- its lifetime began within the evaluation of E;
Here it must satisfy that it is usable in a constant expression, which is determined by [expr.const#4]
A constant-initialized potentially-constant variable V is usable in constant expressions at a point P if V's initializing declaration D is reachable from P and
- V is constexpr,
- V is not initialized to a TU-local value, or
- P is in the same translation unit as D.
An object or reference is usable in constant expressions if it is
- a variable that is usable in constant expressions, or
Since rf
is a reference, hence it is potentially-constant due to [expr.const#3]
A variable is potentially-constant if it is constexpr or it has reference or const-qualified integral or enumeration type.
Whether it is constant-initialized is determined by [expr.const#2]
A variable or temporary object o is constant-initialized if
- [2.1] either it has an initializer or its default-initialization results in some initialization being performed, and
- [2.2] the full-expression of its initialization is a constant expression when interpreted as a constant-expression...
The declaration of rf
has an initializer, bullet 2.1 is true, as far as now, whether rf
is a constant expression has turned to examine whether its full-expression of the initialization is a constant expression. Again, v
shall be a constant expression; to judge whether v
is a constant expression is similar to the process of rf
as given in above. Which in turn is to judge whether the initializer aaa
is a constant expression, I say yes, since aaa
is a static storage duration object and evaluating it will not violate any rule defined in [expr.const#5], hence it's a glvalue core constant expression. Hence, v
is usable in constant expression, which means rf
is also usable in a constant expression. In short, the full-expression of the initialization of crf
is a constant expression.
In addition, regardless of rf
, v
, or aaa
, they are all used as glvalue core constant expression, hence its value is not significant in this example.
Upvotes: 7