Click here to Skip to main content
13,549,045 members
Click here to Skip to main content
Add your own
alternative version


74 bookmarked
Posted 27 Aug 2005

Yet Another C#-style Delegate Class in Standard C++

, 6 Jan 2006
Rate this:
Please Sign up or sign in to vote.
This article describes a C#-style delegate class completely written in standard C++.


Delegates and events are definitely cool features of .NET/C# and there are already many attempts to simulate them in standard C++. The Delegate class described in this article tries to provide a complete and easy to use solution for using delegates in standard C++. Your feedback is welcome.

Design Goals

There are already several good delegate implementations on CodeProject. However, there is still no solution good enough for broad developers. For example, some implementations do not support multicast delegates (which is a must for events), some implementations do not support function objects (functors), some implementations are hard to use (syntax). So the design goals of my Deletgate class are:

  • Support all C++ callable entities, including static functions, member functions and functors.
  • Support single-cast and multicast in one Delegate class, so users don't have to implement multicast functionalities themselves.
  • Easy to understand and use.


1. Using delegates

#include "AcfDelegate.h"
using namespace Acf;

static void H() { ... }

class Foo {
    void G() { ... }

class Foo2 {
    void operator()(int n) { ... }

// Create delegate a which attaches to a static function
Delegate<void ()> a(&H);
assert(a == &H);

// Create delegate b which attaches
// to an instance and a member function
Foo foo;
Delegate<void ()> b(&foo, &Foo::G);
assert(b == std::make_pair(&foo, &Foo::G);

// Create delegate c from a
Delegate<void ()> c = a;
assert(c == &H);

// Create delegate d which attaches to a function object
Delegate<void (int)> d(Foo2());

// Call delegates

// Combine/remove delegates
d += &H;
d += std::make_pair(&foo, &Foo::G);
d -= std::make_pair(&foo, &Foo::G);
d -= &H;

2. Using events

class Button {
    Delegate<void ()> Click;

Button btn;
btn.Click += &F;
btn.Click += std::make_pair(&o, &MyObj::G);
btn.Click -= std::make_pair(&o, &MyObj::G);

3. Using events (advanced)

You may want more control on how event handlers are managed and fired, for example, you care about thread safety.

class Button {
    Delegate<void ()> click;
    Mutex mutex;

    template <class T>
    void add_Click(const T& h) {
        ScopedLock lock(this->mutex);
        this->click += h;
    template <class T>
    void remove_Click(const T& h) {
        ScopedLock lock(this->mutex);
        this->click -= h;

    void OnClick() { if (this->click) this->click(); }

btn.add_Click(std::make_pair(&o, &MyObj::G));

Delegate Class

namespace Acf {

template <class TSignature>
class Delegate; // no body

template <class R, class T1, class T2, ..., class TN>
class Delegate<R (T1, T2, ..., TN)> {
// Constructor/Destructor
    template <class TFunctor>
    Delegate(const TFunctor& f);
    template <class TPtr, class TFunctionPtr>
    Delegate(const TPtr& obj, const TFunctionPtr& mfp);
    Delegate(const Delegate& d);

// Properties
    bool IsEmpty() const;
    bool IsMulticast() const;

// Methods
    template <class TFunctor>
    void Add(const TFunctor& f);
    template <class TPtr, class TFunctionPtr>
    void Add(const TPtr& obj, const TFunctionPtr& mfp);

    template <class TFunctor>
    bool Remove(const TFunctor& f);
    template <class TPtr, class TFunctionPtr>
    bool Remove(const TPtr& obj, const TFunctionPtr& mfp);

    void Clear();

// Operators
    operator bool() const;
    bool operator!() const;

    template <class TFunctor>
    Delegate& operator=(const TFunctor& f);
    Delegate& operator=(const Delegate& d);

    template <class TFunctor>
    Delegate& operator+=(const TFunctor& f);

    template <class TFunctor>
    friend Delegate operator+(const Delegate& d, const TFunctor& f);
    template <class TFunctor>
    friend Delegate operator+(const TFunctor& f, const Delegate& d);

    template <class TFunctor>
    Delegate& operator-=(const TFunctor& f);

    template <class TFunctor>
    Delegate operator-(const TFunctor& f) const;

    template <class TFunctor>
    friend bool operator==(const Delegate& d, const TFunctor& f);
    template <class TFunctor>
    friend bool operator==(const TFunctor& f, const Delegate& d);

    template <class TFunctor>
    friend bool operator!=(const Delegate& d, const TFunctor& f);
    template <class TFunctor>
    friend bool operator!=(const TFunctor& f, const Delegate& d);

    R operator()(T1, T2, ..., TN) const;

} // namespace Acf

The TFunctor template parameter in the Delegate class supports static functions, member functions (via std::pair class that wraps an object pointer and a member function pointer) and functors. The TPtr template parameter for member functions support plain pointers (e.g. Foo*) and smart pointers (e.g. boost::shared_ptr<Foo>).


  • You must enable runtime type information (RTTI) in your project in order to use the Delegate class.
  • The current implementation supports up to six function parameters, which should be enough for most applications (and in general it's a bad practice to have more than six parameters).
  • There are no operators == and != for comparing delegates, because they are impossible to implement correctly for functors (see boost.function).
  • The current implementation is not optimized for performance. However, it should be OK for most applications.


  • 12/24/2005: changed the exception behavior when an empty delegate is called - if the delegate return type is void, then no exception will be thrown, otherwise an InvalidCallException will be thrown.
  • 8/28/2005: initial release.


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

Yingle Jia
Web Developer
China China
Yingle Jia is a software engineer located in Beijing, China. He currently works at IBM CSDL (China Software Development Lab). His interests include C++/COM/C#/.NET/XML, etc. He likes coding and writing.

He is the creator of ACF (Another C++ Framework) project. See

He also has a blog at

You may also be interested in...

Comments and Discussions

QuestionA correct fix for GNU C++ compiler? Pin
Matt HK Lo13-Aug-13 1:16
memberMatt HK Lo13-Aug-13 1:16 
GeneralMy vote of 5 Pin
KenB228-Jun-10 4:49
memberKenB228-Jun-10 4:49 
Generalbrilliant Pin
f22-Aug-08 7:38
memberf22-Aug-08 7:38 
Generalstatuc member function [modified] Pin
delaneyj26-Feb-07 21:21
memberdelaneyj26-Feb-07 21:21 
Generalcompile error with gcc Pin
zhangzq7128-Jun-06 21:34
memberzhangzq7128-Jun-06 21:34 
GeneralEmpty delegates Pin
flapflap14-Oct-05 1:36
memberflapflap14-Oct-05 1:36 
I would find it very handy if the delegate had at least an option to not throw an exception when a delegate that has never been assigned is nonetheless invoked. This would avoid having to check .IsEmpty() each time one wants to signal an event and doesn't know if anyone is subscribed. One could add a dummy subscriber to each delegate but not being able to add a default value in the delegate declaration (as is possible in C#) you would have to add it in the containing class constructor and that would complicate matters unnecessarily.
I've modified operator() for my personal use in the way listed below.
Thanks for a great library.


R OnEmptyDelegate() const
return R();
R OnEmptyDelegate() const
throw InvalidOperationException();
if (this->_last == NULL)

if (this->_last->Previous != NULL)
InvokeDelegateList(this->_last->Previous ACF_DELEGATE_COMMA ACF_DELEGATE_FUNCTION_ARGS);
return this->_last->Invoke(ACF_DELEGATE_FUNCTION_ARGS);
GeneralRe: Empty delegates Pin
Yingle Jia15-Jan-06 16:26
memberYingle Jia15-Jan-06 16:26 
GeneralSome Remarks Pin
Roland Pibinger5-Sep-05 10:50
memberRoland Pibinger5-Sep-05 10:50 
GeneralRe: Some Remarks Pin
Yingle Jia5-Sep-05 15:46
sussYingle Jia5-Sep-05 15:46 
GeneralRe: Some Remarks Pin
Roland Pibinger6-Sep-05 7:41
memberRoland Pibinger6-Sep-05 7:41 
GeneralRe: Some Remarks Pin
Zac Howland11-Jan-06 20:51
memberZac Howland11-Jan-06 20:51 
GeneralRe: Some Remarks Pin
Yingle Jia12-Jan-06 14:50
memberYingle Jia12-Jan-06 14:50 
GeneralRe: Some Remarks Pin
Zac Howland12-Jan-06 19:26
memberZac Howland12-Jan-06 19:26 
GeneralRe: Some Remarks Pin
Yingle Jia15-Jan-06 16:15
memberYingle Jia15-Jan-06 16:15 
GeneralVariable Template Parameters Pin
armentage1-Sep-05 6:46
memberarmentage1-Sep-05 6:46 
GeneralRe: Variable Template Parameters Pin
Yingle Jia1-Sep-05 15:19
sussYingle Jia1-Sep-05 15:19 
GeneralRe: Variable Template Parameters Pin
armentage6-Sep-05 3:29
memberarmentage6-Sep-05 3:29 
GeneralRe: Variable Template Parameters Pin
Zac Howland11-Jan-06 20:59
memberZac Howland11-Jan-06 20:59 
Generalcool! Pin
Peifeng, Gu28-Aug-05 23:23
sussPeifeng, Gu28-Aug-05 23:23 
GeneralRe: cool! Pin
hashimsaleem6-Jul-07 2:42
memberhashimsaleem6-Jul-07 2:42 
GeneralBoost.Signals Pin
Uwe Keim28-Aug-05 3:03
sitebuilderUwe Keim28-Aug-05 3:03 
GeneralRe: Boost.Signals Pin
Yingle Jia28-Aug-05 3:50
sussYingle Jia28-Aug-05 3:50 
GeneralRe: Boost.Signals Pin
lxwde28-Aug-05 15:35
memberlxwde28-Aug-05 15:35 
GeneralRe: Boost.Signals Pin
Anonymous29-Aug-05 16:20
sussAnonymous29-Aug-05 16:20 
GeneralRe: Boost.Signals Pin
John M. Drescher30-Aug-05 2:14
memberJohn M. Drescher30-Aug-05 2:14 

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
Web04 | 2.8.180515.1 | Last Updated 6 Jan 2006
Article Copyright 2005 by Yingle Jia
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid