#ifndef DELEGATE_HPP_INCLUDED
#define DELEGATE_HPP_INCLUDED
#include <functional>
#include <vector>
// general case
template<typename R, typename... Args>
class delegate
{
public:
using DelegateFunc = std::function<R(Args...)>;
template<typename U>
delegate& operator += (const U &func)
{
funcs.emplace_back(std::function<R(Args...)>(func));
return *this;
}
std::vector<R> operator () (Args... params)
{
std::vector<R> ret;
for (auto f : funcs)
{
ret.push_back(f(params...));
}
return ret;
}
// template<typename U>
// delegate& operator -= (const U &func)
// {
// funcs.remove(std::function<R(Args...)>(func));
// return *this;
// }
// template<typename U>
// void register(const U &func) {
// funcs.push_back(std::function<R(Args...)>(func));
// }
private:
std::vector<std::function<R(Args...)>> funcs;
};
// specialization when return type is void
template<typename... Args>
class delegate<void, Args...>
{
public:
template<typename U>
delegate& operator += (const U &func)
{
funcs.push_back(std::function<void(Args...)>(func));
return *this;
}
void operator () (Args... params)
{
for (auto f : funcs)
{
f(params...);
}
}
private:
std::vector<std::function<void(Args...)>> funcs;
};
#endif // DELEGATE_HPP_INCLUDED
#include <iostream>
#include "delegate.hpp"
using namespace std;
void func1(int x, int y) {
cout << "from func1 " << x + y << endl;
}
void func2(int x, int y) {
cout << "from func2 " << x * y << endl;
}
class A {
public:
void func1(int x, int y) {
cout << "from class A::func1 " << x + y << endl;
}
void func2(int x, int y) {
cout << "from class A::func2 " << x * y << endl;
}
};
int main()
{
// delegate with Lambda functions without return value
delegate<void, int, int> d1;
d1 += [](int x, int y){cout << x + y << endl;};
d1 += [](int x, int y){cout << x * y << endl;};
d1(3, 5);
delegate<int, int, int> d2;
d2 += [](int x, int y){return x + y;};
d2 += [](int x, int y){return x * y;};
for (auto ret : d2(3, 5))
{
cout << ret << endl;
}
// delegate with normal functions without return value
delegate<void, int, int> d3;
d3 += func1;
d3 += func2;
d3(3, 5);
// delegate with class member functions without return value
A a = A();
using delegateFunc = std::function<void(int, int)>;
delegateFunc delegateFunc1 = std::bind(&A::func1, a, std::placeholders::_1, std::placeholders::_2);
delegateFunc delegateFunc2 = std::bind(&A::func2, a, std::placeholders::_1, std::placeholders::_2);
delegate<void, int, int> d4;
d4 += delegateFunc1;
d4 += delegateFunc2;
d4(3, 5);
return 0;
}