History

Jan 31, 2014 - Corrected code for Mikhail Semenov's approach.

Introduction

The following is for you who are curious about how Sergey Ryazanov's Impossibly Fast C++ Delegates compares to a C++11 lambda/function pointer approach. This is not meant to put one down, nor is it even close to comprehensive, which is why 'quick and dirty' is included in the title.

As a background my Windows API wrapper incorporated Ryazanov's delegates to implement the member function callbacks. My curiosity got the better of me, and I wanted to play around with the new C++11 lambda functions and see how delegates created with them compared to the existing approach in both usage and performance.

Usage

In order to create a usable callback in DWinLib 3.01 it had to have a function signature of:

The reason for only allowing one specific signature had to do with historical items including being influenced by Borland Builder's syntax, and the fact that Builder 4.0 couldn't compile all of Ryazanov's code, so this aspect was hard coded.

In C++11 using lamdba functions, it is fairly easy to overcome this limitation. But because this is a quick and dirty comparison, such won't be done. The existing method will be recreated in Microsoft Visual Studio Express 2012.

As expected, semantic differences exist between the two methods. Using the same function signature for both approaches, in the existing DWinLib solution a delegate had to be created like so:

DwlDelegate del1(CreateDelegate(Controller, delegate1, this, this));

Then that delegate needed to be somehow stored in the containing object:

DwlDelegate delegateC = del1;

And finally it was executed from within the containing object as a response to some event:

delegateC();

Not too bad, all things considered. Now let's look at the new lambda/callback solution. In it the containing class contains a std::function object rather than a DwlDelegate:

Also, in order to compare apples to apples, we must add a DwlWinObject pointer to the containing class and have the caller register the appropriate value. See the code for the details. It is worth noting that we are not directly comparing apples to apples at this point in the release code because the subsequent calls to dwlWinObject are probably optimized out by the compiler for the lambda approach. In the real world the DwlWinObject pointer is seldom needed, and it should be possible to eliminate this in most cases.

And finally, the containing class executes the callback via:

callbackFuncC(ptrC);

Results

On my computer, the lambda/callback approach took about four times as long as the 'Impossibly Fast Delegates' technique in release mode. Even though this not incredibly impressive as far as performance, I will add it as an option in the next iteration of DWinLib.

* Jan 31, 2014 edit: Now that Visual Studio 2013 Express is available, access to variadic templates is within reach and I was able to get Mikhail Semenov's approach working. A guess at the code was in the previous version of this article, but it required some modification. Interestingly, it is about 35% faster than Ryazanov's approach. But the hard coding of the template parameters in the 'setSemenovDelegate' routine is unacceptable, as it the template member pointer I resorted to in order to execute the callback from within the button code. If you have an improvement to the following method, please leave a comment.

Notes

As stated earlier, this is simply a quick and dirty comparison.

The lambda/callback routine is easier to modify variable function signatures than the hard-coded approach used in DWinLib, although Ryazanov's full 'Impossibly Fast Delegates' code can be used with variable signatures if desired.

The code to compare with Mikhail Semenov's Implementation of Delegates in C++11 has been included in the source. If you are using a compiler without variadic template support, simply comment out the #define VARIADIC_TEMPLATES line. As noted above, my hacks feel far from optimum, so leave an improvement in the comments.

Even though the C++11 method is about 400% slower than the Impossibly Fast Delegate one, the end cost is still acceptable for my usage. If this was used in an inner loop of a high performance routine, such wouldn't be the case.

The main reason for going with the lambda/delegate solution is the awkwardness of the constructing method when using the Impossibly Fast Delegates. Without macro help, the existing method requires remembering: create<ClassName, &ClassName::FunctionName>(Instance, WinObjectPtr). Ungh! Although lambdas aren't much better, they are still an improvement.

The Code Listing

The following is the complete code used for my test. Feel free to modify it however you wish.

In about 1994 I began studying and documenting the astronomy of our ancestors. A hint lead to many years of partial understanding, before a profound breakthrough occurred and some old myths finally made sense.

The greatest of my discoveries is the celestial observations behind the biblical tale of Samson, which was created 3,000 years ago. That find casts a profound new light on the roots of Western religion, as well as the foundation of modern science. To learn more, visit my website.

Trained as a mechanical engineer, I learned C++ programming on my own in order to create a MIDI program. I am delighted to say I also succeeded in that goal. Happy coding, everybody!

Comments and Discussions

hello i remark that the semenov approach do not comply with the no intrusive type design for a delegate:
the button must know the controller (it's why you have a forward declaration of the class Controller) then for your button class you have to forward and make a setsemenov function for each Controller you have ...

i have tested 7 approach of the delegate on vs2013 :
1) the std::function approach with std::bind that is the most general version
2) the lambda expression approach
3) the Elbert May approach wich is a variant of SR :[^]
4) the Don Clugston approach (2004):[^]
and 3 version of mine by interface, by making preprocessors macros, by making Template with non-type Template parameter for the class delegate
my measurement are done on a q6600 (only one core is used) the results are for 100 Mo loops of a call for a simple callback fonction:
void OnTemplateVirtual( ButtonByTemplateVirtual*, int b) {_b=(_a+b)/2.0f;}

all the version are doing delegate job (passed to a button wich use it to call a window method or base class of window method or any class method, the button (the caller) know nothing about the callee (window or other class)
only the Interface version is intrusive type and is not really a delegate.

Thank you. Unless I am missing something major, using interfaces still requires storing a pointer to the called class in the callee. For example, a button handler must call into a potentially totally unrelated object to have it do something the button itself knows nothing about. How do you store the necessary information in the button code? I have done it before with void pointers, but it is painful, and the delegate approach vastly simplified the process. Another solution is a Signals and Slots mechanism. I have never played with them.

If you know a way to solve this problem in another manner, or are aware of something I'm missing with abstract classes and interfaces, please illuminate further.

exactly, Delegates are deadly easy and simple, but interfaces have an advantage over delegates and that is they have n signature, and it will be very useful when they combine with event/handler approach, as Java uses, I always follow the Java approach because I sometimes just get confused to much about ^&* !!! , but overall thanks for the tutorial, maybe I'm going to use delegates for one-sign event approach

Actually, your terminology is a bit confused. Interfaces are not the mechanism Java uses to perform the magic lookup(s). Under the hood it is probably iterating through a list of pointers and calling them. Classes which listen and respond have to have a certain interface defined in order to do so. But the trick isn't the interface - it is the code behind the interface which knows how to use it. I hope that makes sense.

Or, to put it another way (and not necessarily the Java way, and it isn't a delegate; instead is is closer to a signal/slot approach), a button can be viewed as an event creator. Event creators have a list of event listeners which they post the event to. The code to iterate through the registered listeners and send them a message IS NOT an interface. It is simply code. But it takes advantage of a defined interface. The interface by itself can't route the messages - the program needs an engine to take advantage of the interface.

I see what you mean, Interface is just a signature, nothing actually, it's act like a bridge between the host and the client, all I want to mention is, if a component has some events (click, hover, exit,...) so for each one you need to define a delegate while you would do it as an interface, for example in java you track every mouse-related events just by one interface, there is no need delegates for each event, while here interface may increase the code a little but it could be done by an abstract class as adapter. but here another advantage in delegates that they just mention the signature the method, and you would add more than method to a delegate, that this is not possible directly by interfaces.

and the button you mentioned, I agree, but in some systems they separate the even from a component, it's a little hard to explain, but suppose that a button is really a button(an UI component), when OS get and pass the fired event to the application, here button doesn't handle the event itself(for firing listener), instead a event manager get the event and handle it in its manner, it's a little complex approach but has many advantage over default (as Win32/User32) uses. well I'm thinking I will destroyed if we had some challenge, you are a very well-formed (knowledgeable) dev guy, nice, my pleasure.