Template shims

I needed to implement the same interface twice in one object today. It took me a while to remember how I do this kind of thing so I thought it was worth a blog posting so that a) I can find it at a later date, b) other people can tell me of better ways to do this, and, c) other people can use the technique if they want to…

We’re in C++ land by the way…

I have an interface IHandleEvents that needs to be implemented by an object that actually needs to be able to get events from more than one place and needs to know which events came from which place. I could use an object for each instance of the interface but that gets messy quickly so what I tend to do is use a template shim like this:

class IHandleEvents
{
   public :
      virtual void OnEvent() = 0;
};

template <size_t instance>
class THandleEventsImpl : public IHandleEvents
{
   public :
      virtual void OnEvent(const size_t instance) = 0;
   private :
      virtual void OnEvent()
      {
         OnEvent(instance);
      }
};

The template implements the event interface and defines a version of the interface that is identical to the implemented interface but adds a instance indicator to each call. I can now do something like this:

typedef THandleEventsImpl<1> LocalEvents;
typedef THandleEventsImpl<2> RemoteEvents;

class CEventHandler : private LocalEvents, private RemoteEvents
{
   public :
      virtual void OnEvent(const size_t instance);
};

This class can now hand out its LocalEvents base and its RemoteEvents base to different objects and get all of its event notifications routed through to OnEvent. The local events will pass a 1 as the instance and the remote events a 2.

I find it useful to add a couple of other things to the template shim.

template <size_t instance>
class THandleEventsImpl : public IHandleEvents
{
   public :
      virtual void OnEvent(const size_t instance) = 0;

   protected:
      bool IsInstance(const size_t theInstance)
      {
         return theInstance == instance;
      }
      IHandleEvents *GetInterface() 
      {
         return this;
      }
   private :
      virtual void OnEvent()
      {
         OnEvent(instance);
      }
};

This allows the code that derives from the shim to do things like this:

CEventHandler::OnEvent(const size_t instance)
{
   if (LocalEvents:IsInstance(instance))
   {
      // handle local events here
   }
}

CEventHandler::Foo()
{
   CBalloney balloney(RemoteEvents::GetInterface());
}

and if there are any CSS wizards out there; how do I remove those extra line breaks in the preformatted code above?