1
+ #pragma once
2
+
3
+ #include < memory>
4
+
5
+ // instead of passing function pointer, passing wrapper
6
+ template <typename T>
7
+ class Delegate ;
8
+
9
+ template <typename Ret, typename ... Args>
10
+ class Delegate <Ret(Args...)>
11
+ {
12
+ using CallbackType = Ret (*)(std::shared_ptr<void >, Args...);
13
+
14
+ public:
15
+ // object member function
16
+ template <typename T, Ret (T::*funcPtr)(Args...)>
17
+ static Delegate create (std::shared_ptr<T> obj)
18
+ {
19
+ return Delegate{obj, &memberCaller<T, funcPtr>};
20
+ }
21
+
22
+ template <Ret (*funcPtr)(Args...)>
23
+ static Delegate create ()
24
+ {
25
+ // global function has no class, hence it is nullptr
26
+ return Delegate{nullptr , &globalCaller<funcPtr>};
27
+ }
28
+
29
+ // can be functors, lambdas, std::function objects.
30
+ template <typename T>
31
+ static Delegate create (std::shared_ptr<T> t)
32
+ {
33
+ return Delegate{t, &functorCaller<T>};
34
+ }
35
+
36
+ Ret operator ()(Args... args)
37
+ {
38
+ return callback (callee, args...);
39
+ }
40
+
41
+ bool operator ==(const Delegate &other)
42
+ {
43
+ return callee == other.callee && callback == other.callback ;
44
+ }
45
+
46
+ private:
47
+ std::shared_ptr<void > callee{nullptr };
48
+ CallbackType callback{nullptr };
49
+
50
+ private:
51
+ Delegate (std::shared_ptr<void > obj, CallbackType funcPtr) : callee{obj}, callback{funcPtr}
52
+ {
53
+ }
54
+
55
+ template <typename T, Ret (T::*funcPtr)(Args...)>
56
+ static Ret memberCaller (std::shared_ptr<void > callee, Args... args)
57
+ {
58
+ return (static_cast <T *>(callee.get ())->*funcPtr)(args...);
59
+ }
60
+
61
+ template <Ret (*funcPtr)(Args...)>
62
+ static Ret globalCaller (std::shared_ptr<void >, Args... args)
63
+ {
64
+ return funcPtr (args...);
65
+ }
66
+
67
+ template <typename T>
68
+ static Ret functorCaller (std::shared_ptr<void > functor, Args... args)
69
+ {
70
+ return (*static_cast <T *>(functor.get ()))(args...);
71
+ }
72
+ };
0 commit comments