First I'll write example to properly address the question.
First of all, I'll declare template to be used to create singleton object (not auto-created): singleton_base.h
template <class Derived>
class SingletonBase
{
public:
static Derived* instance() { assert(s_instance); return dynamic_cast<Derived*>(s_instance); }
protected:
SingletonBase() { assert(s_instance==0); s_instance=this; }
virtual ~SingletonBase() { assert(s_instance); s_instance=0; }
private:
static SingletonBase* s_instance;
};
template <class Derived>
SingletonBase<Derived>* SingletonBase<Derived>::s_instance = 0;
Now we can declare any class that derived from template, and each derived class should have its own s_instance. For example:
child1.h
class Child1 : public SingletonBase<Child1>
{
...
void doSomething();
static void staticInvokeOne();
};
child2.h
class Child2 : public SingletonBase<Child2>
{
...
void doSomethingElse();
static void staticInvokeBoth();
};
I also have Child's implementation in child1.cpp and child2.cpp respectively.
child1.cpp
void Child1::staticInvokeOne()
{
instance()->doSomething();
}
child2.cpp
void Child2::staticInvokeBoth()
{
Child1::instance()->doSomething();
instance()->doSomethingElse();
}
Now I have Child1
and Child2
having their own s_instance
and they will point to the only instance of that class at given moment.
The question is about storage for this static data member s_instance
. Unlike with regular static data members I have not specified where it should be allocated. I would, of course, like to have SingletonBase<Child1>::s_instance
and SingletonBase<Child2>::s_instance
in child1.o and child2.o respectively, but is that something I can expect or enforce?
The issue gets more complicated if I put Child1
and Child2
into two distinct libraries - lib1 and lib2. Inside Child2::staticInvokeBoth()
there is a call to Child1::instance()
. As far as I understand, default gcc's behaviour is to generate a copy of SingletonBase<Child1>::s_instance
in each compilation unit, thus one copy will be emitted in lib2.
Will it also generate a copy of SingletonBase<Child1>::s_instance
in lib2? Definitely, one copy of SingletonBase<Child1>::s_instance
should be in lib1. If those two libraries are later used together in one application, can I be sure that there is only one instance of SingletonBase<Child1>::s_instance
and that both Child1::staticInvokeOne()
and Child2::staticInvokeBoth()
are using it?
Is it generally safe to use this approach with statics wrapped in template, or are there any drawbacks?
Thank you in advance!