I was going to write about Ireland, but then I got a clean compile on the following piece of code and felt so dirty that I’ve decided to put it off for a while:
#include <iostream>
template <typename T>
class SingletonPolicy
{
private:
static T* instance;
protected:
SingletonPolicy() {}
public:
static T* getInstance()
{
if (instance)
return instance;
else
return (instance = new T());
}
};
template <typename T>
class MultipleInstancePolicy
{
public:
static T* getInstance()
{
return new T();
}
};
template< template <class> class InstancePolicy>
class MyClass : public InstancePolicy< MyClass<InstancePolicy> >
{
public:
void aMethod() { std::cout << “BaseMyClass::aMethod – ” << this << std::endl; }
};
typedef MyClass<SingletonPolicy> MySingleton;
MyClass<SingletonPolicy>* SingletonPolicy<MyClass<SingletonPolicy> >::instance = 0;
typedef MyClass<MultipleInstancePolicy> MyMultiple;
int main(void)
{
MySingleton *myS = MySingleton::getInstance();
MySingleton *myOtherS = MySingleton::getInstance();
MyMultiple *myM = MyMultiple::getInstance();
MyMultiple *myOtherM = MyMultiple::getInstance();
myS->aMethod();
myOtherS->aMethod();
myM->aMethod();
myOtherM->aMethod();
}
The Curiously Recurring Template idiom is quite well known (defining a derived class in terms of a base class specialised on the derived class) as a way of providing the base class with full access to the derived class’s namespace, with static, compile-time checking on the access. What I’ve done above (in the MyClass definition) is take this one step further and combine this with template template parameters, making the derived class a template itself. This presents the additional complication that the templated base class is being specialised on a templated derived class, hence the wonderful class MyClass : public InstancePolicy< MyClass<InstancePolicy> > line – specialisations of the MyClass template are derived from a specialisation of the InstancePolicy template specialised on MyClass which is, of course, a template specialised on InstancePolicy. It all gets a bit recursive and will hurt your head if you think about it too much. Fortunately, the compiler is able to spot the co-dependency and work out what should happen here, rather than create an infinite chain of template specialisations.
The only thing I’m a bit unhappy about is the MyClass<SingletonPolicy>* SingletonPolicy<MyClass<SingletonPolicy> >::instance = 0; line, which just looks a bit inelegant.
Anyway, I’m sure Alexandrescu would be proud (and could probably write it much better, actually).