C++ inline initialization of a static const char*

c

Why I cannot initialize a static const char* in the header file?
In my code I have in my Class header:

static const char* xml_ID_TAG;

and in the cpp:

const char* Class::xml_ID_TAG = "id";

The xml_ID_TAG variable contains the attribute string of an XML document.
Since it's static, const, primitive type (char*), etc… I can't figure out why the compiler forbid to write something like:

static const char* xml_ID_TAG = "id";

I'm using MSVC2013 compiler, giving for the example above the error: "Error: a member with an in-class initializer must be const"

Best Answer

Generally speaking you must define your static members in precisely one translation unit, and the language helps to enforce this by prohibiting you from writing an initialiser for such a member inside the surrounding class definition:

struct T
{
   static int x = 42;
   // ^ error: ISO C++ forbids in-class initialization of
   // non-const static member 'T::x'
};

However, a special exception is made for constants, for convenience:

struct T
{
   static const int x = 42;
   // ^ OK
};

Note that in most cases you still need to define the constant (in your .cpp file would be the best place):

const int T::x;

[C++11: 9.4.2/3]:] If a non-volatile 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 (5.19). A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. —end note ] The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program and the namespace scope definition shall not contain an initializer.


Now, your member is not an int and even a const char* const is not of an "integral type":

struct T
{
   static const char* const str = "hi";
   // ^ error: 'constexpr' needed for in-class initialization of
   // static data member 'const char* const T::str' of non-integral type
};

but it is of a "literal type"; the upshot for you is that if you write it like this:

static constexpr const char* const xml_ID_TAG = "id";
//     ^^^^^^^^^             ^^^^^

you should be okay. (Note that you will still need to define it, until C++17.)

This probably makes more sense anyway: why would you want to change the pointer?