What is a C++ delegate?

C++DelegatesDelegation

C++ Problem Overview


What is the general idea of a delegate in C++? What are they, how are they used and what are they used for?

I'd like to first learn about them in a 'black box' way, but a bit of information on the guts of these things would be great too.

This is not C++ at its purest or cleanest, but I notice that the codebase where I work has them in abundance. I'm hoping to understand them enough, so I can just use them and not have to delve into the horrible nested template awfulness.

These two The Code Project articles explain what I mean but not particularly succinctly:

C++ Solutions


Solution 1 - C++

You have an incredible number of choices to achieve delegates in C++. Here are the ones that came to my mind.


Option 1 : functors:

A function object may be created by implementing operator()

struct Functor
{
     // Normal class/struct members

     int operator()(double d) // Arbitrary return types and parameter list
     {
          return (int) d + 1;
     }
};

// Use:
Functor f;
int i = f(3.14);

Option 2: lambda expressions (C++11 only)

// Syntax is roughly: [capture](parameter list) -> return type {block}
// Some shortcuts exist
auto func = [](int i) -> double { return 2*i/1.15; };
double d = func(1);

Option 3: function pointers

int f(double d) { ... }
typedef int (*MyFuncT) (double d);
MyFuncT fp = &f;
int a = fp(3.14);

Option 4: pointer to member functions (fastest solution)

See Fast C++ Delegate (on The Code Project).

struct DelegateList
{
     int f1(double d) { }
     int f2(double d) { }
};

typedef int (DelegateList::* DelegateType)(double d);

DelegateType d = &DelegateList::f1;
DelegateList list;
int a = (list.*d)(3.14);

Option 5: std::function

(or boost::function if your standard library doesn't support it). It is slower, but it is the most flexible.

#include <functional>
std::function<int(double)> f = [can be set to about anything in this answer]
// Usually more useful as a parameter to another functions

Option 6: binding (using std::bind)

Allows setting some parameters in advance, convenient to call a member function for instance.

struct MyClass
{
    int DoStuff(double d); // actually a DoStuff(MyClass* this, double d)
};

std::function<int(double d)> f = std::bind(&MyClass::DoStuff, this, std::placeholders::_1);
// auto f = std::bind(...); in C++11

Option 7: templates

Accept anything as long as it matches the argument list.

template <class FunctionT>
int DoSomething(FunctionT func)
{
    return func(3.14);
}

Solution 2 - C++

A delegate is a class that wraps a pointer or reference to an object instance, a member method of that object's class to be called on that object instance, and provides a method to trigger that call.

Here's an example:

template <class T>
class CCallback
{
public:
	typedef void (T::*fn)( int anArg );

	CCallback(T& trg, fn op)
		: m_rTarget(trg)
		, m_Operation(op)
	{
	}

	void Execute( int in )
	{
		(m_rTarget.*m_Operation)( in );
	}

private:

	CCallback();
	CCallback( const CCallback& );

	T& m_rTarget;
	fn m_Operation;

};

class A
{
public:
	virtual void Fn( int i )
	{
	}
};


int main( int /*argc*/, char * /*argv*/ )
{
	A a;
	CCallback<A> cbk( a, &A::Fn );
	cbk.Execute( 3 );
}

Solution 3 - C++

The need for C++ delegate implementations are a long lasting embarassment to the C++ community. Every C++ programmer would love to have them, so they eventually use them despite the facts that:

  1. std::function() uses heap operations (and is out of reach for serious embedded programming).

  2. All other implementations make concessions towards either portability or standard conformity to larger or lesser degrees (please verify by inspecting the various delegate implementations here and on codeproject). I have yet to see an implementation which does not use wild reinterpret_casts, Nested class "prototypes" which hopefully produce function pointers of the same size as the one passed in by the user, compiler tricks like first forward declare, then typedef then declare again, this time inheriting from another class or similar shady techniques. While it is a great accomplishment for the implementers who built that, it is still a sad testimoney on how C++ evolves.

  3. Only rarely is it pointed out, that now over 3 C++ standard revisions, delegates were not properly addressed. (Or the lack of language features which allow for straightforward delegate implementations.)

  4. With the way C++11 lambda functions are defined by the standard (each lambda has anonymous, different type), the situation has only improved in some use cases. But for the use case of using delegates in (DLL) library APIs, lambdas alone are still not usable. The common technique here, is to first pack the lambda into a std::function and then pass it across the API.

Solution 4 - C++

Very simply, a delegate provides functionality for how a function pointer SHOULD work. There are many limitations of function pointers in C++. A delegate uses some behind-the-scenes template nastyness to create a template-class function-pointer-type-thing that works in the way you might want it to.

ie - you can set them to point at a given function and you can pass them around and call them whenever and wherever you like.

There are some very good examples here:

Solution 5 - C++

An option for delegates in C++ that is not otherwise mentioned here is to do it C style using a function ptr and a context argument. This is probably the same pattern that many asking this question are trying to avoid. But, the pattern is portable, efficient, and is usable in embedded and kernel code.

class SomeClass
{
    in someMember;
    int SomeFunc( int);

    static void EventFunc( void* this__, int a, int b, int c)
    {
        SomeClass* this_ = static_cast< SomeClass*>( this__);

        this_->SomeFunc( a );
        this_->someMember = b + c;
    }
};

void ScheduleEvent( void (*delegateFunc)( void*, int, int, int), void* delegateContext);

    ...
    SomeClass* someObject = new SomeObject();
    ...
    ScheduleEvent( SomeClass::EventFunc, someObject);
    ...

Solution 6 - C++

Windows Runtime equivalent of a function object in standard C++. One can use the whole function as a parameter (actually that is a function pointer). It is mostly used in conjunction with events. The delegate represents a contract that event handlers much fulfill. It facilitate how a function pointer can work for.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDollarsliceView Question on Stackoverflow
Solution 1 - C++J.N.View Answer on Stackoverflow
Solution 2 - C++Grimm The OpinerView Answer on Stackoverflow
Solution 3 - C++BitTicklerView Answer on Stackoverflow
Solution 4 - C++DollarsliceView Answer on Stackoverflow
Solution 5 - C++JoeView Answer on Stackoverflow
Solution 6 - C++nmserveView Answer on Stackoverflow