Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force a static member to be initialized?

Tags:

Consider this example code:

template<class D> char register_(){     return D::get_dummy(); // static function }  template<class D> struct Foo{     static char const dummy; };  template<class D> char const Foo<D>::dummy = register_<D>();  struct Bar     : Foo<Bar> {     static char const get_dummy() { return 42; } }; 

(Also on Ideone.)

I'd expect dummy to get initialized as soon as there is a concrete instantiation of Foo, which I have with Bar. This question (and the standard quote at the end) explained pretty clear, why that's not happening.

[...] in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.

Is there any way to force dummy to be initialized (effectively calling register_) without any instance of Bar or Foo (no instances, so no constructor trickery) and without the user of Foo needing to explicitly state the member in some way? Extra cookies for not needing the derived class to do anything.


Edit: Found a way with minimal impact on the derived class:

struct Bar     : Foo<Bar> {   //                              vvvvvvvvvvvv     static char const get_dummy() { (void)dummy; return 42; } }; 

Though, I'd still like the derived class not having to do that. :|

like image 742
Xeo Avatar asked Jun 21 '11 06:06

Xeo


People also ask

How do you initialize a static member?

The initializer for a static data member is in the scope of the class declaring the member. 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 static members of a class get initialized?

A static member is shared by all objects of the class. All static data is initialized to zero when the first object is created, if no other initialization is present.

Why do static members need to be initialized C++?

Because it is a static variable the compiler needs to create only one copy of it.

Is it mandatory to initialize static variable?

Initialization of Instance variables But if you declare an instance variable static and final Java compiler will not initialize it in the default constructor therefore, it is mandatory to initialize static and final variables.


2 Answers

Consider:

template<typename T, T> struct value { };  template<typename T> struct HasStatics {   static int a; // we force this to be initialized   typedef value<int&, a> value_user; };  template<typename T> int HasStatics<T>::a = /* whatever side-effect you want */ 0; 

It's also possible without introducing any member:

template<typename T, T> struct var { enum { value }; }; typedef char user;  template<typename T> struct HasStatics {   static int a; // we force this to be initialized   static int b; // and this    // hope you like the syntax!   user :var<int&, a>::value,        :var<int&, b>::value; };  template<typename T> int HasStatics<T>::a = /* whatever side-effect you want */ 0;  template<typename T> int HasStatics<T>::b = /* whatever side-effect you want */ 0; 
like image 142
Johannes Schaub - litb Avatar answered Oct 12 '22 10:10

Johannes Schaub - litb


We can use a simple trick based on a declaration that must be instantiated with the class:

template<…> struct Auto {   static Foo foo;   static_assert(&foo); }; template<…> Foo Auto::foo=…; 

Note that some compilers warn about the comparison to null; that can be avoided with &foo==&foo, (bool)&foo, or ((void)&foo,true) if needed.

Note also that GCC 9.0–9.2 don’t count this as an odr-use.

like image 38
Davis Herring Avatar answered Oct 12 '22 11:10

Davis Herring