This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 109b. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2022-09-25


48. Definitions of unused static members

Section: 11.4.9.3  [class.static.data]     Status: TC1     Submitter: Bill Gibbons     Date: 23 Nov 1997

Also see section: 6.3 [basic.def.odr] .

Originally, all static data members still had to be defined outside the class whether they were used or not.

But that restriction was supposed to be lifted so that static data members need not be defined outside the class unless they are used in a manner which requires their definition, in the same manner as namespace-scope variables. In particular, if an integral/enum const static data member is initialized within the class, and its address is never taken, we agreed that no namespace-scope definition was required.

For example:

    struct A {
        static const int size = 10;
        int array[size];
    };

    int main() {
        A a;
        return 0;
    }
However, 11.4.9.3 [class.static.data] paragraph 4 says:
The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.
A narrow interpreration of "used" in this rule would make the example ill-formed because there is no namespace-scope definition of "size". A better wording for this rule would be:
The member shall still be defined in a namespace scope if it is used in the program in the manner described in 6.3 [basic.def.odr] . The namespace scope definition shall not contain an initializer.
Also, the wording in 6.3 [basic.def.odr] paragraph 2:
An expression is potentially evaluated unless either it is the operand of the sizeof operator (7.6.2.5 [expr.sizeof] ), or it is the operand of the typeid operator and does not designate an lvalue of polymorphic class type (7.6.1.8 [expr.typeid] ).
is incomplete because it does not mention the use of a compile-time constant as an array bound or template argument. It should say something like:
An expression is potentially evaluated unless it is the operand of the sizeof operator (7.6.2.5 [expr.sizeof] ), the operand of the typeid operator, an integral constant-expression used as an array bound or an integral constant-expression used as a template-argument for a non-reference template-parameter; and the expression does not designate an lvalue of polymorphic class type (7.6.1.8 [expr.typeid] ).

Proposed Resolution (04/99): Change the first sentence of 6.3 [basic.def.odr] paragraph 2 from:

An expression is potentially evaluated unless either it is the operand of the sizeof operator (7.6.2.5 [expr.sizeof] ), or it is the operand of the typeid operator and does not designate an lvalue of polymorphic class type (7.6.1.8 [expr.typeid] ).
to:
An expression is potentially evaluated unless it appears where an integral constant expression is required (see 7.7 [expr.const] ), is the operand of the sizeof operator (7.6.2.5 [expr.sizeof] ), or is the operand of the typeid operator and the expression does not designate an lvalue of polymorphic class type (7.6.1.8 [expr.typeid] ).