Click here to Skip to main content
Licence 
First Posted 18 Dec 2004
Views 39,140
Bookmarked 25 times

Event Driven Programming using Template Specialization

By | 18 Dec 2004 | Article
Template specializations can be used as call-backs instead of functors or function pointers to create an event-driven framework.

Introduction

Template specializations provide a mechanism by which we can create an event-driven framework, instead of using function pointers.

Template specializations are alternative definitions of a template for specific parameter values. They are sometimes known as user-defined specializations. For more information, I recommend reading The C++ Programming Language, 3rd Edition by Bjarne Stroustrup.

There are two advantages of this approach, first no function pointer registration step is needed like in typical event-driven frameworks, and secondly, the compiler can do a far better job of optimizing the call.

Event-Driven Programming

Event-driven code is useful when writing a library and we want the library to provide default behavior in response to certain events, but to allow library users to provide custom behavior to one or more events. This occurs frequently in the implementation of GUI libraries. A message loop has to dispatch events to user-defined functions. This is typically done either through virtual-functions or through function-pointers. Using template specializations is an easy to use and efficient alternative.

The Code

Here is a sample program, which demonstrates the usage of template specializations for callbacks:

  const int RED_PILL = 0;
  const int BLUE_PILL = 1; 

  template<int T>
  struct EventHandler {
    static void Event() { };
  }; 

  template<typename Dummy_T = void>
  struct Dispatcher {
    static bool EventDispatch(char ch) {
      switch (ch) {
        case 'a': {
          EventHandler<RED_PILL>::Event();
          return true;
        }
        case 'b': {
          EventHandler<BLUE_PILL>::Event();
          return true;
        }
        default : {
          return false;
        }
      }
    }
  }; 

  template<>
  struct EventHandler<BLUE_PILL> {
    static void Event() { puts("Welcome to the matrix!"); };
  }; 

  int main() {
    puts("press a for the red-pill, b for the blue-pill");
    char ch = getchar();
    Dispatcher<>::EventDispatch(ch);
    return 0;
  }

Explanation

This code represents how an event-driven library could be created. The basic EventHandler and Dispatcher classes represent what would be found in the library. The specializations and the main() function represent what would be defined by the user of the library.

The first EventHandler class is a template which contains empty function definitions. This is the class which is specialized. The other EventHandler classes are the template specializations defined by the user of a library. The programmer simply needs to provide implementations of the Event() function and can do whatever else they want inside of it.

The Dispatcher class houses a Dispatch() function which triggers the appropriate user-defined event. The template parameter is ignored, but is provided to make sure that the class is constructed by the compiler after the specializations are defined by the programmer.

Notice that there is no explicit specialization EventHandler<RED_PILL>. The default handler is called in this case, which does nothing. The call should be entirely removed by the optimizer.

Why is EventDispatch inside of a template?

This is a drawback of the technique due to compilation order dependencies. Typically, in an event-driven framework, we will want to define the specializations in code after the code where the specialization is used. As soon as the compiler sees a usage of the template, it is too late for us to define a specialization. What I do then is define the usage within a template. This allows me to put off compilation of the usage until after the definition of the specializations.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Christopher Diggins

Architect
Autodesk
Canada Canada

Member

Follow on Twitter Follow on Twitter
I've been programming personal computers since my I got my first Atari 400 in 1980. I currently work at Autodesk as an SDK specialist.
 
One of my passions is the design and implementation of programming languages. My current project is the Jigsaw library which includes a parsing engine and other utilities for implementing programming languages in C#.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
Questionis multi-thread safe? Pinmemberf27:21 5 Jul '06  
Generalhard to detect err PinmemberLvYou15:58 23 Dec '04  
If I wrote a handler in another cpp file,it will not be called,and will not cause any errror.
in real projects,handlers only can be write in header files,and these header files must be included in cpp which fires that event.seems illogical.OMG | :OMG:
 

QuestionAdvantage? PinmemberChristof Schardt11:37 18 Dec '04  
AnswerRe: Advantage? PinsussJohn_ Boy_12:30 18 Dec '04  
AnswerRe: Advantage? PinmemberTweety18:12 18 Dec '04  
GeneralRe: Advantage? Pinmemberjmoritz15:29 25 Dec '04  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120528.1 | Last Updated 18 Dec 2004
Article Copyright 2004 by Christopher Diggins
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid