What Is a C++ Delegate

What is a C++ delegate?

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);
}

When & why to use delegates?

I agree with everything that is said already, just trying to put some other words on it.

A delegate can be seen as a placeholder for a/some method(s).

By defining a delegate, you are saying to the user of your class, "Please feel free to assign any method that matches this signature to the delegate and it will be called each time my delegate is called".

Typical use is of course events. All the OnEventX delegate to the methods the user defines.

Delegates are useful to offer to the user of your objects some ability to customize their behavior.
Most of the time, you can use other ways to achieve the same purpose and I do not believe you can ever be forced to create delegates. It is just the easiest way in some situations to get the thing done.

What is the best way to deal with optional delegates in a c# constructor?

The only way I could get this working was by getting it working ugly (in my own opinion).

You have to deliver a static method, but that static method could use a reference to this to get the actual method out.

This is what I came up with.

public Foo(Action onEventOne) : this(onEventOne, self => self.DefaultEventTwo)
{
//CS0120 An object reference is required for the non-static field, method, or property 'Foo.DefaultEventTwo()
}

public Foo(Action onEventOne, Action onEventTwo = null) : this(onEventOne, self => onEventTwo)
{ }

// private constructor, just for the sake of getting it working
private Foo(Action onEventOne, Func<Foo, Action> onEventTwo = null)
{
_memberVariable = 0;

_onEventOne = onEventOne;
_onEventTwo = onEventTwo(this); // <--

_onEventOne();
}

self => self.DefaultEventTwo is the static function to get the action. That function is used in the call to onEventTwo(this) to get the default event of this instance.

Can I get the signature of a C# delegate by its type?

    MethodInfo method = delegateType.GetMethod("Invoke");
Console.WriteLine(method.ReturnType.Name + " (ret)");
foreach (ParameterInfo param in method.GetParameters()) {
Console.WriteLine("{0} {1}", param.ParameterType.Name, param.Name);
}

Make a C# method implement a delegate

C# does not support this.

However, you can simulate it by simply putting the method into a delegate:

static readonly ComputationMethod _ForceCompliance = ComputeAverage;
private static int ComputeAverage(int termA, int termB, int termC, int termD) { ... }

Changing the method or delegate signature would result in a compiler error one line above the method.

(doing this with instance methods would require a constructor call)

For added efficiency, you could do this in an unused nested class and/or in #if DEBUG.

Either way, make sure to leave an explanatory comment.

What it means to have body in delegates declaration?

That's not an Action delegate with its body declared. That's a static method of the X class called Ac(), with a return type of Action; that is, it's a class method that returns an Action delegate. The body presumably creates an Action object to return from the method.

To put it another way: it is a regular static method, which happens to return Action instead of something like string or int.

How are delegates linked to events?

Addressing your questions as briefly as possible, to avoid making your question "too broad"…

•What do 'Object obj' and 'EventArgs e' in the delegate declaration represent? For learning is seems these are quite often empty. What might be an example of where these might need to be different?

obj should always be non-null, and should be set to the reference of the object raising the event. e should be the instance of the EventArgs or derived class, containing information related to the event.

It is important to note that this pattern is strictly conventional. I.e. not enforced by anyone, and not required. A C# event can use any delegate type. The EventHandler delegate type is simply the basis for the standard way to implement events in .NET.

•When you create an event based on a delegate, does the event now store all the pointers to methods or is it still the delegate? I've heard terminology used about adding subscribers to an event. Are these 'subscribers' just methods in the same way you would add methods to delegates?

Most events are implemented implicitly by the compiler. But it's important to understand that when you use the event keyword, you are declaring both an add and a remove method for the event. These are analogous to the get and set methods for a property. The default implementation simply takes the delegate instance passed in and either appends it to or removes it from the existing value for the event's backing field (also implicitly generated for you), for the add and remove methods respectively.

The default implementation for an event stores this in a single, simple delegate type field. There are implementations of events that are more complicated, such as putting the event handler reference in a dictionary, or using weak references.

•Apparently the OnDrive() method is 'raising' the event. Is 'raising' an event the same as executing the event? So executing all the subscribers attached to the event?

Yes, raising an event is simply a matter of invoking the delegates that were added (subscribed) to the event. The .NET delegate types are all "multi-cast" delegates, so a single delegate instance can represent multiple invocation targets. Invoking the one delegate instance will automatically call all of the individual invocation targets.

By convention, a method named OnXXX() where XXX is the name of some event will always raise that event. But there's no requirement to do so. One obvious exception is when the event field is null, i.e. there are no handers subscribed to the event. In that case, obviously the event isn't raised. Another, more specific, real-world example would be various events exposed by the Control objects in the Winforms API, which have several exceptions to the rule (for events pertaining to changes in visual state, like the current font, background color, enabled state, etc.), short-cutting the event-raising logic and returning without raising the event if the object or any of its ancestor objects (i.e. parents, grandparents, etc.) are in the process of being disposed.

•Why when your raising an event does it have to conform to the delegate input parameters? (this, EventArgs.Empty). Isn't it the subscribers only that need to match this format?

To invoke a delegate, the code must pass the necessary parameters to it, just as when you call any method you are required to pass the necessary parameters to it (even if there are default values, the compiler generates the code necessary to ensure all of the parameter values are provided).

If the invoker of the delegate didn't pass the parameter values, where would the values that are eventually passed to the target method come from?

Passing a C# delegate to a C++/CLI wrapper

You seem to be missing the managed part of the instruction:

#pragma managed

public delegate void keyCallback(int, int, int, int);

void Window::setKeyCallback(keyCallback^ fp) {
csharpKeyCallback = fp;
}

In order to pass a reference to a function instance (delegate) from C# to C++\CLI you need to declare it i.e. declare a managed delegate. This can be done either in C# or in C++\CLI.

In your code the KEY_CALLBACK is an unmanaged function declaration. Thus it is "Not supported by the language". C# side cannot use it as a delegate declaration.

In order to avoid such a mess I myself always keep my C++\CLI projects clear of any managed declarations and provide those in an additional C# class library that is referenced from both the C++\CLI wrapper and the C# side.

Edit: Do not forget to put the ^ sign after the managed reference type in the managed method declaration or the compiler is going to bust you with an error 'A delegate type is not allowed here'.



Related Topics



Leave a reply



Submit