Skip to main content
Email Password   helpLost your password?

Introduction

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:

Examples

1. Using delegates

#include "AcfDelegate.h"

using namespace Acf;

static void H() { ... }

class Foo {
public:
    void G() { ... }
};

class Foo2 {
public:
    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

a();
d(100);

// 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 {
public:
    Delegate<void ()> Click;
};

Button btn;
btn.Click += &F;
btn.Click += std::make_pair(&o, &MyObj::G);
btn.Click();
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 {
private:
    Delegate<void ()> click;
    Mutex mutex;

public:
    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;
    }

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

btn.add_Click(&F);
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

public:
    Delegate();
    template <class TFunctor>
    Delegate(const TFunctor& f);
    template <class TPtr, class TFunctionPtr>
    Delegate(const TPtr& obj, const TFunctionPtr& mfp);
    Delegate(const Delegate& d);
    ~Delegate();

// Properties

public:
    bool IsEmpty() const;
    bool IsMulticast() const;

// Methods

public:
    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

public:
    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>).

Notes

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
Generalbrilliant Pin
f2
8:38 2 Aug '08  
Generalstatuc member function [modified] Pin
delaneyj
22:21 26 Feb '07  
Generalcompile error with gcc Pin
zhangzq71
22:34 28 Jun '06  
GeneralEmpty delegates Pin
flapflap
2:36 14 Oct '05  
GeneralRe: Empty delegates Pin
Yingle Jia
17:26 15 Jan '06  
GeneralSome Remarks Pin
Roland Pibinger
11:50 5 Sep '05  
GeneralRe: Some Remarks Pin
Yingle Jia
16:46 5 Sep '05  
GeneralRe: Some Remarks Pin
Roland Pibinger
8:41 6 Sep '05  
GeneralRe: Some Remarks Pin
Zac Howland
21:51 11 Jan '06  
GeneralRe: Some Remarks Pin
Yingle Jia
15:50 12 Jan '06  
GeneralRe: Some Remarks Pin
Zac Howland
20:26 12 Jan '06  
GeneralRe: Some Remarks Pin
Yingle Jia
17:15 15 Jan '06  
GeneralVariable Template Parameters Pin
armentage
7:46 1 Sep '05  
GeneralRe: Variable Template Parameters Pin
Yingle Jia
16:19 1 Sep '05  
GeneralRe: Variable Template Parameters Pin
armentage
4:29 6 Sep '05  
GeneralRe: Variable Template Parameters Pin
Zac Howland
21:59 11 Jan '06  
Generalcool! Pin
Peifeng, Gu
0:23 29 Aug '05  
GeneralRe: cool! Pin
hashimsaleem
3:42 6 Jul '07  
GeneralBoost.Signals Pin
Uwe Keim
4:03 28 Aug '05  
GeneralRe: Boost.Signals Pin
Yingle Jia
4:50 28 Aug '05  
GeneralRe: Boost.Signals Pin
lxwde
16:35 28 Aug '05  
GeneralRe: Boost.Signals Pin
Anonymous
17:20 29 Aug '05  
GeneralRe: Boost.Signals Pin
John M. Drescher
3:14 30 Aug '05  


Last Updated 6 Jan 2006 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2009