Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ inline initialization of a static const char*

Tags:

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"

like image 903
ABCplus Avatar asked Jul 04 '14 10:07

ABCplus


People also ask

How do you initialize static constant characteristics of a class?

To initialize the const value using constructor, we have to use the initialize list. This initializer list is used to initialize the data member of a class.

What is a static const char * in C++?

const char* is a pointer to a constant char, meaning the char in question can't be modified. char* const is a constant pointer to a char, meaning the char can be modified, but the pointer can not (e.g. you can't make it point somewhere else).

Can a static data member be const?

A static data member can be of any type except for void or void qualified with const or volatile . You cannot declare a static data member as mutable . You can only have one definition of a static member in a program.

How do you declare a char constant?

A "character constant" is formed by enclosing a single character from the representable character set within single quotation marks (' ').


1 Answers

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?

like image 149
Lightness Races in Orbit Avatar answered Sep 18 '22 21:09

Lightness Races in Orbit