Initial D
Initial D

Reputation: 81

Why can a reference declared with constexpr be bound to an Indeterminate value variable?

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

Answers (1)

xmh0511
xmh0511

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

Related Questions