1

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?

3
  • The information you found most certainly did not imply you can do it without inline. The accepted answer very clearly states integers are a special case. Commented Oct 2, 2020 at 16:34
  • 1
    Even if it was allowed, clearly this compiler is saying you can't do it, and at the end of the day the compiler is always right. Commented Oct 2, 2020 at 16:39
  • 1
    C++11 don't have inline variables. This is C++17 Commented Oct 2, 2020 at 17:09

2 Answers 2

1

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.

1

As you noticed you can either use inline or the following:

struct A {
    static const string d[];    
};

and

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

in a dedicated compilation unit (once only).

Live Demo

2
  • 1
    @dasfex Because it's defined like that in the c++ standard. The reason probably is to force the One Definition Rule (ODR). Commented Oct 2, 2020 at 20:38
  • but it doesn't work with inline if you use variable in the middle. Commented Nov 20, 2020 at 4:29

Not the answer you're looking for? Browse other questions tagged or ask your own question.