Click here to Skip to main content
12,894,700 members (61,064 online)
Click here to Skip to main content
Add your own
alternative version


8 bookmarked
Posted 10 Jan 2014

Events and Delegates in Standard C++

, 10 Jan 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
Events and Delegates in Standard C++ implemented using Macro functions


An event (in C#, ActionScript...) is a mechanism for a class to provide notifications to listeners when something notably happens to an object.

Events are declared using delegates, which are basically very similar to a C/C++ function pointers. Delegates are method wrappers that can be passed to a code which can invoke wrapped method without any compile-time knowledge of which method will be invoked actually.

This tip explains an idea of implementing Events and Delegates in Standard C++, with focus on syntax.

Before going any further, you have to know that this is a tip/idea made by a C++ beginner. I have approximately 3 months of C++ professional experience and haven't implemented anything in CPP for quite a long time (5 years actually), so please, treat this tip just as an idea and as my desire to hear suggestions and comments from more experienced C++ developers on what are the positive and negative things with this approach.



  • Implement easy to use eventing mechanism
  • Obtain syntax similar to C#
  • Learn C++ :)

I've tried to keep the code small and simple because this is just an idea. So, the implementation contains only one header file named EvDelegates.h:


#include "stdafx.h"

	class EVENT_##DELEGATE{ \
	private:  \
		DELEGATE delegates[10]; \
		int current; \
	public: \
		EVENT_##DELEGATE(): current(0){} \
		EVENT_##DELEGATE & operator +=(DELEGATE func) { delegates[current++] = func; return *this; } \
		void invoke PARAMS { for (int __DELEGATE##INDEX = 0; 
		__DELEGATE##INDEX  < current; __DELEGATE##INDEX++) (*delegates[__DELEGATE##INDEX ])PARAM_NAMES; } \

#define delegate0(RET_TYPE, DELEGATE) \ 
    delegate(RET_TYPE, DELEGATE, (), ())
#define delegate1(RET_TYPE, DELEGATE, t, a) \
    delegate(RET_TYPE, DELEGATE, (t a), (a) )
#define delegate2(RET_TYPE, DELEGATE, t, a, t2, a2) \
    delegate(RET_TYPE, DELEGATE, (t a, t2 a2), (a, a2) )
#define delegate3(RET_TYPE, DELEGATE, t, a, t2, a2, t3, a3) \
    delegate(RET_TYPE, DELEGATE, (t a, t2 a2, t3 a3), (a, a2, a3) ) 
#define delegate4(RET_TYPE, DELEGATE, t, a, t2, a2, t3, a3, t4, a4) \
    delegate(RET_TYPE, DELEGATE, (t a, t2 a2, t3 a3, t4 a4), (a, a2, a3, a4) ) 
#define delegate5(RET_TYPE, DELEGATE, t, a, t2, a2, t3, a3, t4, a4, t5, a5) \
    delegate(RET_TYPE, DELEGATE, (t a, t2 a2, t3 a3, t4 a4, t5 a5), (a, a2, a3, a4, a5) ) 

#define event(DELEGATE, EVENT_NAME)   \


So, what we have here.

Macro functions:

  • delegate
  • delegateX (X = 0 .... )
  • event

The first macro function delegate is the most important.


  1. RET_TYPE - return type of a function referenced by the delegate
  2. DELEGATE - name of newly defined delegate type
  3. PARAMS - argument list with following format - (type arg, type2 arg2...)
  4. PARAM_NAMES - argument list without argument types - (arg, arg2)

This method basically does two things. First, it defines new type named DELEGATE, pointer to a function with return type RET_TYPE and function arguments passed as PARAMS argument. Second, it creates event class that contains logic for attaching multiple delegates of previously defined delegate type, and invoke method with the same argument list as attached delegates.

Class created using this method gets class name created as concatenation of string EVENT_ and value of argument DELEGATE.

There are a lot of Delegate-Event C++ implementations, vast majority is using templates classes, type trairs and so on... many of this mechanisms can be found inside boost library. The goal which I tried to achieve is to reduce manual declaration of template event classes for various argument lists, so I left that job to a macro function.

Second group of macro functions are just wrappers around function delegate, and have nicer and easier to use syntax.

Macro function event is used for declaring instance of an event for given delegate name.

Using the Code

To try this out, you should create header file containing code listed in previous section. This code was developed using Microsoft Visual Studio 2010.

Declaring delegates using first macro function - Weird way:

delegate (void, WIERD_DELEGATE_WITHOUT_PARAMS, (), ());
delegate (void, WIERD_DELEGATE, (int k, User & user), (k, user));

event(WIERD_DELEGATE, e2);

e2.invoke(666, user);

A bit more user friendly delegate declaration - not so weird way:

delegate0(void, ZERO_ARGUMENT_DELEGATE);
delegate3(int, THREE_ARGUMENT_DELEGATE, long, l, char*, str, User *, ptrUser);

EVENT_THREE_ARGUMENT_DELEGATE threeArgEvent; //this is correct too, class is declared by macro function delegate

threeArgEvent.invoke(667, "Breaking bad", new User());

Attach multiple delegates:

#include "stdafx.h"  
#include "EvDelegates.h"
//Test model

struct User{
	int id;
	char * name;
	long years;

//User repository mock

class UsersDb
	delegate3(void, USER_ADDED_DELEGATE, int , 
	id, char *, sName, long, years);  //declare delegate with three arguments

	EVENT_USER_ADDED_DELEGATE onUserAdded;  //actual event to which listeners will be attached

	//add new user, notify listeners

	void addUser(User u) { 
		//TODO: add user to db, yeah right!

		//notify all

		onUserAdded.invoke(,, u.years);

void userDbListener1(int id, char * str, long years)
	cout << "Id: " << id << endl;
	cout << "Name: " << str << endl;
	cout << "Years: " << years << endl;

void userDbListener2(int id, char * str, long years)
	cout << "User [" << str << "] with id 
	[" << id << "] is ["<< years << "] years old." <<  endl;

int _tmain(int argc, _TCHAR* argv[])
	UsersDb te;  //users repository

	//add listeners 

	te.onUserAdded += UsersDb::USER_ADDED_DELEGATE(&userDbListener1);
	te.onUserAdded += &userDbListener2;

	User u = {1, "Slavisa", 29};
	User u1 = {2, "Marija", 19};
	User u2 = {3, "Viktor", 44};

	//add users, and notify listeners

	return 0;

This should be the output:

Id: 1
Name: Slavisa
Years: 29
User [Slavisa] with id [1] is [29] years old.
Id: 2
Name: Marija
Years: 19
User [Marija] with id [2] is [19] years old.
Id: 3
Name: Viktor
Years: 44
User [Viktor] with id [3] is [44] years old. 


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Software Developer (Senior)
Serbia Serbia
6 Years of development in various programming languages. Recently focused on Flex/Java development.

You may also be interested in...

Comments and Discussions

GeneralRight Idea for a Valuable Construct - More robust solutions are possible Pin
Paul Watt13-Jan-14 11:41
mentorPaul Watt13-Jan-14 11:41 
GeneralRe: Right Idea for a Valuable Construct - More robust solutions are possible Pin
Slavisa13-Jan-14 13:54
memberSlavisa13-Jan-14 13:54 
QuestionI'm not sure ... Pin
Florian Rappl10-Jan-14 3:13
mvpFlorian Rappl10-Jan-14 3:13 
AnswerRe: I'm not sure ... Pin
Member 1036533112-Jan-14 1:32
memberMember 1036533112-Jan-14 1:32 
GeneralRe: I'm not sure ... Pin
Slavisa12-Jan-14 3:02
memberSlavisa12-Jan-14 3:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    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 | Terms of Use | Mobile
Web01 | 2.8.170424.1 | Last Updated 10 Jan 2014
Article Copyright 2014 by Slavisa
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid