-
Notifications
You must be signed in to change notification settings - Fork 0
/
Delegate.h
136 lines (106 loc) · 2.48 KB
/
Delegate.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//
// Created by Víctor Navarro on 2/26/2019.
//
#ifndef DELEGATE_H
#define DELEGATE_H
#include <functional>
#include <vector>
#include <algorithm>
#include <type_traits>
// Helper to get the address of a std::function.
template<typename T, typename... U>
static size_t getAddress(std::function<T(U...)> f)
{
typedef T(fnType)(U...);
auto fnPointer = f.template target<fnType *>();
return (size_t) *fnPointer;
}
template<typename T>
struct function_traits;
template<typename R, typename ...Args>
struct function_traits<std::function<R(Args...)>>
{
static const size_t nargs = sizeof...(Args);
typedef R result_type;
template<size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
};
};
template<class T>
class Delegate
{
protected:
using Function = std::function<T>;
std::vector<Function> functions;
using ResultType = typename Function::result_type;
std::vector<ResultType> results;
public:
Delegate() = default;
~Delegate() = default;
Delegate(const Delegate &delegate)
{
functions = delegate.functions;
}
template<typename ... Params>
auto Invoke(Params ... params)
{
results.clear();
for (const auto &function : functions)
{
results.push_back(function(params...));
}
return results;
}
void operator+=(const Function &rhs)
{
functions.push_back(rhs);
}
void operator+=(const std::vector<Function> &rhs)
{
functions.insert(functions.end(), rhs.begin(), rhs.end());
}
void operator-=(const Function &rhs)
{
auto found = std::find_if(functions.begin(), functions.end(),
[rhs](auto function) { return getAddress(function) == getAddress(rhs); });
if (found != functions.end()) functions.erase(found);
}
void Clear()
{
results.clear();
}
};
template<class ... Args>
class Delegate<void(Args...)>
{
protected:
using Function = std::function<void(Args...)>;
std::vector<Function> functions;
public:
Delegate() = default;
~Delegate() = default;
void Invoke(Args ... args)
{
for (const auto &function : functions)
{
function(args...);
}
}
void operator+=(const Function &rhs)
{
functions.push_back(rhs);
}
void operator+=(const std::vector<Function> &rhs)
{
functions.insert(functions.end(), rhs.begin(), rhs.end());
}
void operator-=(const Function &rhs)
{
auto found = std::find_if(functions.begin(), functions.end(),
[rhs](auto function) { return getAddress(function) == getAddress(rhs); });
if (found != functions.end()) functions.erase(found);
}
};
#endif