Search code examples
c++staticinitializationc++17inline

Can I initialize static const class member?


I want to run this code:

struct A {
    static const string d[] = {"1", "2"};    
};

And get an error:

error: in-class initialization of static data member ‘const string A::d []’ of incomplete type
     static const string d[] = {"1", "2"};
                         ^
error: non-constant in-class initialization invalid for non-inline static member ‘A::d’
     static const string d[] = {"1", "2"};
                                        ^
note: (an out of class initialization is required)

Here I find information that now I can initialize what I want. So what the problem?

If I add inline then it will work:

struct A {
    static const inline string d[] = {"1", "2"};    
};

UPD: I know the solves but why c++ works like that?


Solution

  • The standard explicitly states that non-inline static data members of a class are declaration only, and must be followed up by definition at namespace scope: class.static.data#3

    3: The declaration of a non-inline static data member in its class definition is not a definition and may be of an incomplete type other than cv void. The definition for a static data member that is not defined inline in the class definition shall appear in a namespace scope enclosing the member's class definition. In the definition at namespace scope, the name of the static data member shall be qualified by its class name using the ​::​operator. The initializer expression in the definition of a static data member is in the scope of its class ([basic.scope.class]).

    These rules are then refined further so that non-volatile non-inline const static data member of integral or enumeration type can be brace initialised (in effect defining the variable at the point of declaration): class.static.data#4

    4: If a non-volatile non-inline const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression ([expr.const]). The member shall still be defined in a namespace scope if it is odr-used ([basic.def.odr]) in the program and the namespace scope definition shall not contain an initializer. An inline static data member may be defined in the class definition and may specify a brace-or-equal-initializer.

    In non-standardese speak, this says that you must define static member variables separately from the definition except for the case of integers or enums, which explains why your example fails.