How to Initialize a Static Const Member in C++

How to initialize a static const member in C++?

YES you can but only for int types.
If you want your static member to be any other type, you'll have to define it somewhere in a cpp file.

class A{
private:
static const int a = 4; // valid
static const std::string t ; // can't be initialized here
...
...
};

// in a cpp file where the static variable will exist
const std::string A::t = "this way it works";

Also, note that this rule have been removed in C++11, now (with a compiler providing the feature) you can initialize what you want directly in the class member declaration.

Can I initialize a static const member at run-time in C++?

I am sorry to disagree with the comments and answers saying that it is not possible for a static const symbol to be initialized at program startup rather than at compile time.

Actually this IS possible, and I used it many times, BUT I initialize it from a configuration file. Something like:

// GetConfig is a function that fetches values from a configuration file
const int Param1 = GetConfig("Param1");
const int MyClass::Member1 = GetConfig("MyClass.Member1");

As you see, these static consts are not necessarily known at compile time. They can be set from the environment, such as a config file.

On the other hand, setting them from argv[], seems very difficult, if ever feasible, because when main() starts, static symbols are already initialized.

Initializing static const member with other static const member

I suggest using a separate function to get a string to perform an initialization and avoid initialization order fiasco:

const std::string initialize() {
static const std::string initializer = "meow";
return initializer;
}

Then you might do the initialization as follows:

class A {
public:
static const std::string a;
};

const std::string A::a = initialize();

Can I initialize static const class member?

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.

static const member variable initialization

The syntax initializer in the class definition is only allowed with integral and enum types. For std::string, it must be defined outside the class definition and initialized there.

struct C {
static const int a = 42;
static const string b;
};

const string C::b = "hi"; // in one of the .cpp files

static members must be defined in one translation unit to fulfil the one definition rule. If C++ allows the definition below;

struct C {
static const string b = "hi";
};

b would be defined in each translation unit that includes the header file.

C++ only allows to define const static data members of integral or enumeration type in the class declaration as a short-cut. The reason why const static data members of other types cannot be defined is that non-trivial initialization would be required (constructor needs to be called).

Initialize a static const member with a template argument

Your code seems correct to me and compile without problems with my olds g++ (4.9.2) and clang++ (3.5).

But, according the error message, could be that your compiler doesn't correctly support the C++11 declaration/initialization of static data members

I suggest you to try in the following way

template <FooType FType>
class FooContainer
{
public:
static const unsigned int FooSize;

std::array<float, FooSize> fooArray;

};

template <FooType FType>
int unsigned const FooContainer<FType>::FooSize
= ((FType == FooType::ShortFoo) ? 32 : 64);

or (I suppose is better)

template <FooType FType>
class FooContainer
{
public:

static const unsigned int FooSize {(FType == FooType::ShortFoo) ? 32 : 64 };

std::array<float, FooSize> fooArray;

};

template <FooType FType>
int unsigned const FooContainer<FType>::FooSize;

You can also try defining FooSize as constexpr instead of const.

Another solution could be transform FooSize in a template parameter

template <FooType FType,
std::size_t FooSize = (FType == FooType::ShortFoo) ? 32 : 64 >
class FooContainer
{
public:
std::array<float, FooSize> fooArray;
};

C++ where to initialize static const

Anywhere in one compilation unit (usually a .cpp file) would do:

foo.h

class foo {
static const string s; // Can never be initialized here.
static const char* cs; // Same with C strings.

static const int i = 3; // Integral types can be initialized here (*)...
static const int j; // ... OR in cpp.
};

foo.cpp

#include "foo.h"
const string foo::s = "foo string";
const char* foo::cs = "foo C string";
// No definition for i. (*)
const int foo::j = 4;

(*) According to the standards you must define i outside of the class definition (like j is) if it is used in code other than just integral constant expressions. See David's comment below for details.

Static const member initialization outside class

This is how to initialize static class members outside of the class:

C.cpp

#include <string>

class C {
public:
C();

private:
static const int a;
static const std::string b;
};

C::C() = default;

const int C::a = 4;
const std::string C::b = "ba";

There is no other option to initialize a static class member outside of the class, other than all the various C++ ways to do initialization as variations on this same theme.



Related Topics



Leave a reply



Submit