Template shims

| 5 Comments

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?

5 Comments

RE: the double-spacing of code fragments...

Your code is enclosed in an HTML <pre> block, which will render all the line breaks in the source. In addition, the end of each line has a <br />, which will add another line break. Thus you get two line breaks in the display.

Remove the <br /> elements in your code fragments and it will show exactly as typed in...

Now, how do I do that with the css file that I have...

or is it that I need to adjust the <code> css element so that I can use that rather than <pre> and ... Hmm...

Try adding this to your style sheet:

pre br { display: none }

Matt, Seems to have done the trick, thanks!

Leave a comment