Approximation of C# Delegates, Funcs and Actions on C++
Even though the three different classes (Delegate, Func and Action) store functions to use them in the future, they serve different purposes. Let's explain them one by one.
His purpose is to store functions whose return type is always void with 0 parameters.
void foo() { std::cout << "Something funny"; }
Action action;
action += foo;
The operator +=
adds the functions to later be called using the Invoke method.
action.Invoke();
// Prints: Something funny
All of the three classes support function removal by using '-='
action -= foo;
action.Invoke();
// Prints: Nothing.
His purpose is to store functions whose return type is always void with 0 or more parameters.
void print(int x, char a) { std::cout << x << a; }
Func<int, char> func;
func += print;
func += print;
func.Invoke(5, 'A');
// Prints: 5A5A
His purpose is to store functions whose return type could be whatever, with 0 or more parameters.
Delegate<int()> delegate;
delegate += []() { return 1; };
delegate += []() { return 2; };
delegate += []() { return 3; };
A nice feature of the Delegate is that the Invoke method returns a std::vector storing the return values of the functions.
for (const auto &item : delegate.Invoke()) std::cout << item;
// Prints: 123
As with Funcs, you can also pass parameters to the Invoke method.
int square(int x) { return x * x; }
Delegate<int(int)> delegate;
delegate += square;
std::cout << delegate.Invoke(2)[0];
// Prints: 4
Yes! Perhaps is not in the most beautiful way, but still does the trick. You just need to use lambdas like this.
Object obj;
action += [&]() { obj.something(); } // You can even instantiate the object inside the lambda.
Again lambdas. Don't ask me, they do anything. You could use std::bind
but clang-tidy advices against it.
action += []() { print(5, 'A'); };
action += []() { print(6, 'B'); };
action.Invoke();
// Prints: 5A6B
Thanks for asking. The operator +=
is overloaded to accept a vector.
delegate += { foo, bar };
At difference of C#, delegates can be copied by value.
Delegate<int> delegate(copyMePls); // This is possible.
You can also reset or clear the delegate with delegate.Clear()