Consider the following program:
struct Empty { };
struct NonEmpty { int x{}; };
struct S {
static const Empty e; // declaration
static const NonEmpty n; // declaration
static const int a; // declaration
static const int b{}; // declaration and initializer
};
Empty ge; // declaration & definition
NonEmpty gn; // declaration & definition
int ga; // declaration & definition
int main() {
auto le1 = S::e; // OK
auto ln1 = S::n; // #1 error: undefined reference
auto la1 = S::a; // #2 error: undefined reference
auto lb1 = S::b; // OK
auto le2 = ::ge; // OK
auto ln2 = ::gn; // OK
auto la2 = ::ga; // OK
}
None of the static data members of S are defined, but of the two integral type static data members S::a and S::b the latter specifies a brace-or-equal-initializer at its in-class declaration, as it may, as per [class.static.data]/4. S::e and S::n may not specify brace-or-equal-initializer:s at their in-class declaration.
All these static data members of S have, like their global namespace-scope counterpart variables ge, gn and ga, static storage duration. As per [basic.start.static]/2 they all thus undergo zero initialization as part of static initialization.
The program above is, however, rejected by GCC and Clang (various language versions, various compiler versions) at #1 and #2, when trying to copy-initialize local variables from the S::n and S::a static data members.
I'm assuming the compilers are correct, but I cannot find the normative section which supports this rejection, or maybe rather, why the program accept the case with the empty class static data member S::e. That the case of S::b is accepted "makes sense", but again I can't sort this out normatively (odr-use, conv.lval, basic.life, ... ?).
Question
- What normative text explains why the program above rejects reading the value of
S::eandS::aas ill-formed, whilst it accepts read the values ofS::e(empty) andS::b(initialized)? Say, in N4868.