So if you're somewhat familiar with C++ you know you can't easily implement a nice generic delegate that works for both static classes and member functions of all classes. However, with some research and thought, you will realize it's not as hard as you think!

First, I would like to share this article that inspired me and caused me to gain hope in that delegates are possible in a nice flexible way! Here it is, on: Code Project.

Okay, let's first think about this, we want a delegate to hide away the C++ syntax so we can call any kind of function, pass in certain parameters and get something back. To make this flexible, it makes sense to have the base delegate class be a template, so you can define what types you want to use. So here is the base class, which I'll call IDelegate, as in Interface Delegate.

// Interface for a Delegate class, for dispatching a lookup function call.
// R is the return type
// P is the parameter type
template <typename R,typename P>
class IDelegate
{
public:
virtual ~IDelegate(){}

virtual R Invoke(P) = 0;
};

You could also just as easily use an operator overload instead of Invoke:

virtual R operator()(P) = 0;

Now we just need to worry about creating a subclass so we can use these Delegates! So, we'll start with the Static Delegate since it'll be the simplest to create. To create a Static Delegate, we'll need a StaticDelegate class that accepts a static function pointer, and that's all it needs. So we have that below:

// This class is for attaching a Static Function Pointer to an IDelegate
// R is the return type
// P is the parameter type
template <typename R,typename P>
class StaticDelegate<typename R,typename P>
    : public IDelegate<R,P>
{
    typedef R (*funcPtr)(P);

protected:
    funcPtr _funcPtr;

public:
    StaticDelegate(funcPtr functionPointer)
        : _funcPtr( functionPointer )
    {
    }

    R Invoke(P param)
    {
        return _funcPtr(param);
    }
};

For those of you who don't know, this is a Static Function Pointer:

typedef R (*funcPtr)(P);

And also in case you didn't know, you can in fact define functions with parenthesis around the name, it is valid syntax.

Okay, so what we have here is really simple to use:

void PrintInt(int num)
{
    std::cout << num << endl;
}
typdef StaticDelegate<void,int> SDelegate;

IDelegate<void,int> delegate = SDelegate(&PrintInt);

I do encourage you to use typedefs to make your life easier, this becomes more obvious why you might want to do that when you're working with Class Member Function Pointers. In an event system, to be as flexible as possible, I do suggest trying to stick with one type of delegate.

Okay, the above shows you what you need to do to get a Static Function working with an IDelegate, now we need to get something to encapsulate a Member Function Pointer. For lack of a better name, I'll be using Type Delegate, as you do have to specify a class type that the member function belongs to.

// This class is for attaching a Member Function Pointer to an IDelegate
// R is the return type
// T is the Class of this Member Function Pointer
// P is the parameter type
template <typename R,typename T,typename P>
class TypeDelegate
    : public IDelegate<R,P>
{
    typedef R (T::*funcPtr)(P);// this is a function pointer definition
protected:
    funcPtr _funcPtr;
    T&amp; _objPtr;

public:
    TypeDelegate(T& objPtr, funcPtr functionPointer)
        : _objPtr( objPtr )
        , _funcPtr( functionPointer )
    {
    }

    R Invoke(P param)
    {
        return (_objPtr.*_funcPtr)(param);
    }
};

Okay, so to create a TypeDelegate you need to pass in an object of the class you specified, and a function pointer to the class. So you can try this:

class Object1
{
public:
    typedef TypeDelegate<void,PhysicsObject,Object_Event::ENUM> TDelegate;

    Object1(){}

    void CatchEvent(Object_Event::ENUM eventID)
    {
        //...
    }
};
//  Somewhere in your code...
Object1 obj1 = Object1();

IDelegate delegate = TDelegate(&obj1, &Object1::CatchEvent);

//or inside of obj1:
delegate = TDelegate(*this, &Object1::CatchEvent);

Again, please feel free to use typedefs as it'll leave you with less code to type. I also suggest using this one system for all your delegate needs, no matter if you need parameters or not. I think this system is beautiful as it is because it's so simple, flexible, and it's not hard to tell what it does and didn't require a mess to get working like I thought might have to happen. If you want to use this type of delegate with no params, you can define an empty class like this:

// use as a Parameter type instead of void inside of IDelegate, as you'll get a compiler error
class Void
{
public:
    Void(){}
};

Yes, as I indicated in the comment, if you try to use "void" as the parameter type for the IDelegate sub classes, you will get a compiler error. So, as an alternative, use "Void", and pass in Void() as the args for the delegate; or, just use a "void" and set it to NULL I guess (or a Void or whatever you want); just make it obvious to functions using the delegate know that it's a void type.

So, as I suggested for keeping the delegate system simple, when you want to use multiple parameters, just use a struct with them defined. One reason I prefer this: if you didn't use a single struct, you'd have to expect every function variable to be properly named to know what it does. In this case, if you're using a struct, the variables names are what you define them to be, so this will help for documentation purposes when someone wants to find out what it does, they just need to look in one place: the struct definition.

 

[UPDATE:] Source Files: C++ Delegates.

Add a comment

Comments

You actually make it seem so easy with your prtesntaeion but I find this matter to be really something that I think I would never understand. It seems too complicated and very broad for me. I am looking forward for your next post, I will try to get the hang of it!
Written on Sun, 15 May 2016 11:05:48 by Ranessa
I am really grateful to the holder of this web site who has shared this fantastic post at at this time.
Written on Sat, 10 Jan 2015 06:06:45 by Sac Vanessa Bruno Pas cher
Hi there my mates, how is everything? Here it is really good YouTube video lessons collection. i enjoyed a lot.
Written on Sat, 03 Jan 2015 03:36:03 by sacs à main longchamp
My grand father constantly used to watch YouTube comical video lessons, hehehehehe, since he desires to be glad always.
Written on Fri, 26 Dec 2014 15:04:14 by Replica Oakley Ten, Fake Oakleys
Great article, just what I needed.
Written on Sun, 21 Dec 2014 19:50:56 by Moncler jassen
Into YouTube video embed code you can also stipulate parameters matching to your hope like width, height or even border colors.
Written on Wed, 17 Dec 2014 08:53:09 by Sac Vanessa Bruno Pas cher
C# Delegates in C - leetNightshade Cheap Snapback Caps http://snapbackcaps.nitejars.us/
Written on Tue, 25 Nov 2014 21:31:01 by Cheap Snapback Caps
I read this paragraph completely about the resemblance of most up-to-date and preceding technologies, it's amazing article.
Written on Sun, 14 Sep 2014 06:51:45 by vanessabruno-pascher
Hello to every one, its genuinely a good for me to visit this web site, it consists of important Information.
Written on Sat, 06 Sep 2014 19:45:55 by www.pavillonmargaux.fr
YouTube is world's biggest video sharing web site, no one can defeat it. Every one upload video lessons at YouTube then obtain embed code and post anywhere.
Written on Thu, 28 Aug 2014 11:52:05 by Sac Longchamp

Next Post Previous Post