Urgh

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&gt* 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).

Comments are closed.