If x declares a reference,
that reference is a constituent reference of x.
For any constituent reference r of a variable x,
if r is bound to a temporary object or subobject thereof
whose lifetime is extended to that of r,
the constituent values and references of that temporary object
are also constituent values and references of x, recursively.
[Example 1: struct A {int m;
constint& r;
};
void f(){staticint sx;
thread_localint tx; // tx is never constexpr-referenceableint ax;
A aa ={1, 2};
static A sa ={3, 4};
// The objects sx, ax, and aa.m, sa.m, and the temporaries to which aa.r and sa.r are bound, are constexpr-referenceable.auto lambda =[]{int ay;
// The objects sx, sa.m, and ay (but not ax or aa), and the// temporary to which sa.r is bound, are constexpr-referenceable.};
} — end example]
An object or reference x is
constexpr-representable at a point P if,
for each constituent value of x that points to or past an object o,
and for each constituent reference of x that refers to an object o,
o is constexpr-referenceable from P.
the full-expression of its initialization is a constant expression
when interpreted as a constant-expression
with all contract assertions
using the ignore evaluation semantic ([basic.contract.eval]),
The initialization, when evaluated,
can still evaluate contract assertions
with other evaluation semantics,
resulting in a diagnostic or ill-formed program
if a contract violation occurs.
if x has static or thread storage duration,
x is constexpr-representable at the nearest point
whose immediate scope is a namespace scope
that follows the initializing declaration of v.
[Example 2: void f(){int ax =0; // ax is constant-initializedthread_localint tx =0; // tx is constant-initializedstaticint sx; // sx is not constant-initializedstaticint& rss = sx; // rss is constant-initializedstaticint& rst = tx; // rst is not constant-initializedstaticint& rsa = ax; // rsa is not constant-initializedthread_localint& rts = sx; // rts is constant-initializedthread_localint& rtt = tx; // rtt is not constant-initializedthread_localint& rta = ax; // rta is not constant-initializedint& ras = sx; // ras is constant-initializedint& rat = tx; // rat is not constant-initializedint& raa = ax; // raa is constant-initialized} — end example]
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
a temporary object of non-volatile const-qualified literal type
whose lifetime is extended ([class.temporary])
to that of a variable that is usable in constant expressions at P,
An object or reference is usable in constant expressions at point P
if it is an object or reference
that is potentially usable in constant expressions at P and
is constexpr-representable at P.
[Example 3: struct A {int*const& r;
};
void f(int x){constexpr A a ={&x};
static_assert(a.r ==&x); // OK[&]{static_assert(a.r !=nullptr); // error: a.r is not usable in constant expressions at this point}();
} — end example]