I did a bit of reading around the topic of delegates after a brief discussion about signals and slots with Leeor.
Bjarne Stroustrup had a list of C++11 features, which included a section on
std::function. Of particular note is the section towards the end, it states a member function is treated the same as a free function with an extra argument (corresponding to
this). He called the function both explicitly passing
this, and using
std::bind to fix the
this pointer to a constant value, making it callable the same way as a free function:
struct X {
int foo(int);
};
function<int (X*, int)> f;
f = &X::foo;
Here's some reference info:
std::functionstd::bind
The
std::function type is general-purpose polymorphic function wrapper. It holds arbitrary references to callable types. What matters is the signature of the call, not the type of the underlying Callable target. It can be assigned from a free function, a member function, a member data variable, a functor (an object which overloads
operator()), and lambdas (which are really actually functors).
The
std::bind template creates a "forwarding call wrapper", which can fix argument values to some specified constant. This effectively reduces the number of arguments the new wrapped function now accepts. This is particularly useful for fixing the
this pointer for member functions.
auto twoParamFunction = std::bind(someFunction, 5, _1, _2);
twoParamFunction(x, y);
One oddity with
bind is the use of placeholder values
_1, _1, _3, .... This adds a bit of noise to the location where a method is bound, though does allow for some flexibility, such as rearranging argument order.
auto reversedParameters = std::bind(someFunction, _2, _1);
reversedParameters(x, y);
Putting this all together, here's how these components might be used to implement a click handler which could accept various types of callable objects:
#include <functional>
#include <iostream>
If instead the click handler were to accept two arguments, an x and y location, update the following lines: