There are many folks out there that claim their singleton implementation to be robust and general because it uses metaprogramming constructs.
My goal is to enforce a singleton policy onto a derived class so that I do not have to explicitly (manually) declare the derived class’ constructors as private. I think there’s a way to naively add the instance static variable and the getter as a policy by making the templated singleton a friend of the class you derive. But that’s not at all elegant.
I started with this code, that, among other things, is given as being a correct (i.e. complete) design of a singleton, while it is clearly allowing for multiple instances:
template <class CWrappedClass>
class CSingleton
{
protected:
static CWrappedClass* ms_instance;
private:
CSingleton(){}
CSingleton(const CSingleton& ) {}
CSingleton& operator = (const CSingleton&) {}
public:
static CWrappedClass& GetInstance()
{
if (ms_instance == NULL)
ms_instance = new CWrappedClass;
return *ms_instance;
}
};
template <class CWrappedClass>
CWrappedClass* CSingleton<CWrappedClass>::ms_instance = NULL;
And a singleton client of this “policy”, using CRTP:
class CThing : public CSingleton<CThing>
{
// friend class CSingleton<CThing>; // only if ctor is private!
public:
void DoNothing()
{
std::cout<<" Nothing \n";
}
CThing()
{
std::cout<<" single ";
}
};
NOTE this is not a correct implementation of a CRTP Singleton policy, it’s merely part of the question!
The code won’t compile as is. The base singleton policy class has its constructor declared private, so it can’t support derived instances unless the child is a friend of this class. People usually make the constructors protected, which means there’s nothing to keep a user from making derived class non-singletonian.
Problem/Question: Is there any mechanism to enforce a singleton policy without having to make the derived class’ constructors private manually?
In case you do wish to use this pattern:
Constructor of the template should be protected, not private, so that the derived class has access to it. Otherwise its own constructor cannot construct the base class.
Derived class can make the template (which is its base class) a friend and have a private constructor.
Alternatively, have a macro that you implement that actually constructs the instance from the derived class in its compilation unit. When I did use a similar model (by force, fixing code that used singletons and I coudn’t change that, only the way the actual singleton was implemented), I went for this option, which actually went through a
boost::onceconstruct in its .cpp file.