Introduction
Many programming languages natively offers some kind of event handling inclusive or delegates. There are many great solutions out on the web like Member Function Pointers and the Fastest Possible C++ Delegates [^] which is still one of my most favourite codeproject articles, or Boost [^] and Loki [^] which are the first libraries which come into my mind.
The provided source code offers a basic solution to declare and define multicast event sources and event sinks in C++.
Background
The provided solution heavily uses macros to
- define templated base classes which can be used to declare and define event sources;
- define base classes which can be used to declare and define event sinks.
One of the few positive points of approaching the problem using macros and inheritance is that easy readable method names can be generated for the event getters.
All negative aspects of macros on the other side, especially fancy ones, are well known. The new C++ language features also offers plenty of opportunities for new approaches.
The solution also doesn't provide means to specify return types in signatures. It could be added easily, but I think this would need additional treatment to be really consistent as I tried to show in this C# tip [^], so it might be part of a follow up.
Using the code
The attached source contains the header file MulticastEvent.h which is the only one needed to included to use the library.
#include "MultiCastEvent.h"
Event signatures then can be defined like this:
#define MULTICAST_EVENT_CALLED_A (ClassExposingEvents, MethodACalledEvent, int, x, int, y)
#define MULTICAST_EVENT_CALLED_B (ClassExposingEvents, MethodBCalledEvent)
Event sources then can be defined using the event signatures like this:
class ClassExposingEvents
{
public:
ClassExposingEvents()
: MULTICAST_EVENT_VAR_DEF(MULTICAST_EVENT_CALLED_A)
, MULTICAST_EVENT_VAR_DEF(MULTICAST_EVENT_CALLED_B)
{};
~ClassExposingEvents() {};
public:
DECLARE_MULTICAST_EVENT(MULTICAST_EVENT_CALLED_A);
DECLARE_MULTICAST_EVENT(MULTICAST_EVENT_CALLED_B);
public:
void a(int x, int y) { getMethodACalledEvent().invoke(x, y); };
bool b() { getMethodBCalledEvent().invoke(); return true; };
};
And event sinks can be defined similarly:
class ClassImplementingEventHandlers
: public DECLARE_MULTICAST_EVENT_TARGET_SUPERCLASS(MULTICAST_EVENT_CALLED_A)
, public DECLARE_MULTICAST_EVENT_TARGET_SUPERCLASS(MULTICAST_EVENT_CALLED_B)
{
public:
ClassImplementingEventHandlers() {};
~ClassImplementingEventHandlers() {};
public:
DECLARE_MULTICAST_EVENT_TARGET(MULTICAST_EVENT_CALLED_A) ;
DECLARE_MULTICAST_EVENT_TARGET(MULTICAST_EVENT_CALLED_B) ;
};
DEFINE_MULTICAST_EVENT_TARGET(ClassImplementingEventHandlers, MULTICAST_EVENT_CALLED_A)
{
}
DEFINE_MULTICAST_EVENT_TARGET(ClassImplementingEventHandlers, MULTICAST_EVENT_CALLED_B)
{
}
After instantiating, sources and sinks can be routed like shown here:
ClassExposingEvents eventSource;
ClassImplementingEventHandlers eventSink;
eventSource.getMethodACalledEvent().addListener(eventSink);
Points of Interest
The provided source code is very basic and does only provide the bare minimum to serve as a starting point for further development. Neither thread safety, nor performance, memory usage or other aspects are covered.
History
- 2014/01/08: First version submitted.