Explicit instance of a static member of a template in a derived class

I am trying to implement a template class with a static member. Classes derived from the template class must be created without the need to write additional code.

Here is my naive (and not successful) approach:

Singleton.h:

template <class T> class Singleton { protected: Singleton(); static T instance_; } // explicit instantiation of 'instance_' ???, // where 'instance_' is an instance of the derived class template <class T> T Singleton<T>::instance_; 

ConcreteA.h:

 class ConcreteA : public Singleton<ConcreteA> { public: ConcreteA(); void foo(); } 

main.c:

 int main() { // an instance of ConcreteA should have been created (no extra code)!!! return 0; } 

Is there a way to force an instance of ConcreteA by simply pulling ConcreteA out of Singleton without writing any extra instance code?

A workaround is to call the instance_ method in the ConcreteA constructor, for example:

ConcreteA.c

 ConcrereA::ConcreteA { instance_.foo(); } 

Are there any better workarounds?

+6
source share
4 answers

Based on your own "dirty trick", this works in all tested compilers and does not require any code in the constructor of the derived class:

 #include <iostream> template <class T> class Singleton { protected: Singleton() { instptr_ = &instance_; } static T instance_; private: static T* instptr_; }; template<class T> T Singleton<T>::instance_; template<class T> T* Singleton<T>::instptr_; class ConcreteA : public Singleton<ConcreteA> { public: ConcreteA() { std::cout << "ConcreteA constructed.\n"; } void foo(); }; int main() { //Prints 'ConcreteA constructed.'. return 0; } 

My understanding of this is that using the address instance_ odr - uses it, forcing it to exist. I have to say that I am not 100% sure that this is guaranteed not to be optimized in future versions of some compiler (I tested it with -O2 everywhere).

EDIT: It seems like even writing a base class constructor like this

 Singleton() { (void)&instance_; } 

enough to instptr_ rid of instptr_ .

+4
source

Unfortunately this is not possible. Citation C ++ 11 14.7.1 / 2 (we are talking about implicit template creation):

If a class template member or member template has not been explicitly defined or explicitly specialized, a member specialization is implicitly created when the specialization is referenced in a context that requires a member definition; in particular, the initialization (and any associated side effects) of a static data member does not occur if the static data member itself is not used, which requires the definition of a static data member.

+2
source

this is done as follows:

 template <class T> class Singleton { protected: Singleton(); // note: static function contains static variable static T& instance() { static T _t; // c++11 guarantees that this is thread-safe return _t; } } class ConcreteA : public Singleton<ConcreteA> { ... }; auto& myA = ConcreteA::instance(); 
0
source

Initialization is guaranteed in a C ++ static object only if code was called from a file that was defined by the instance (the initialization order is not a guarantee).

because of this, it is better to make an instance of the object inside the function and call the function

 class A{ public: static A& getInstance(){ static A a; return a; } protected: A(){ } }; 
-2
source

Source: https://habr.com/ru/post/981056/


All Articles