-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinterface_wrapper.cpp
185 lines (143 loc) · 5.11 KB
/
interface_wrapper.cpp
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include <functional>
#include <type_traits>
namespace detail {
template <typename... ts>
struct any_true;
template <typename t, typename... ts>
struct any_true<t, ts...> {
static const bool value = t::value || any_true<ts...>::value;
};
template <typename t>
struct any_true<t> {
static const bool value = t::value;
};
template<typename> struct type_eraser { using type = int; };
template<typename t, typename... ts> struct type_getter { using type = t; };
template <typename ct>
struct interface_helper {
// TODO: figure out how to pass multiple arguments not using tuples (might not be possible)
// Possible fix: helper struct template with just the arguments
// <template <typename... Args> typename>
template <typename... Ignored>
static ct* create(typename ct::Args arg, Ignored... rest) {
static_assert(std::is_constructible<ct, typename ct::Args>::value, "One of the interfaces could not be creates using provided arguments");
return new ct(arg);
}
};
template <bool B, typename T = void>
struct disable_if {
using type = T;
};
template <typename T>
struct disable_if<true,T> {
};
struct multi_wrapper_trait {};
} // detail
template <typename interface>
struct _interface {
private:
interface* _impl;
public:
_interface(interface* t): _impl(t) {}
_interface(std::function<interface*(void)> f): _impl(f()) {}
interface* operator->() { return _impl; }
const interface* const operator->() const { return _impl; }
template <typename RV, typename... Args>
typename std::enable_if<!std::is_base_of<detail::multi_wrapper_trait, interface>::value, std::function<RV(Args...)>>::type
call(RV (interface::*func)(Args...)) {
return [this, func](Args... args) { (_impl->*func)(args...); };
}
template <typename RV, typename... Args>
typename std::enable_if<std::is_base_of<detail::multi_wrapper_trait, interface>::value, std::function<RV(Args...)>>::type
call(RV (interface::*func)(Args...)) {
return [this, func](Args... args) { return _impl->operator[](func); };
}
};
#include <vector>
template <typename IF>
struct multi_interface: IF, detail::multi_wrapper_trait {
template <typename... cts>
multi_interface(cts*... args): ifs(args...) {}
template <typename... cts>
struct concrete_creator {
template <typename... Args>
static multi_interface<IF>* create(Args... args) {
return new multi_interface<IF>(detail::interface_helper<cts>::create(args...)...);
}
};
template <typename RV, typename IT, typename... Args>
auto operator[](RV (IT::*func)(Args...)) -> std::function<RV(Args...)> {
// The interface better not be deleted!
// we cannot afford passing the vector by value every time
return [this, func](Args... args) {
for (auto i: ifs) {
(i->*func)(args...);
}
};
}
private:
std::vector<IF*> ifs;
};
template <typename... ts> // interfaces
struct interface_wrapper: virtual _interface<ts>... {
interface_wrapper(ts*... args): _interface<ts>(args)... {}
interface_wrapper(std::function<ts*(void)>... fns): _interface<ts>(fns)... {}
template <typename... cts>
struct concrete_creator {
template <typename... Args>
static interface_wrapper<ts...>* create(Args... args) {
return new interface_wrapper<ts...>(detail::interface_helper<cts>::create(args...)...);
}
};
template <typename RV, typename IT, typename... Args>
auto call(RV (IT::*func)(Args...), Args... args) -> RV {
return static_cast<_interface<IT>*>(this)->call(func)(args...);
}
template <typename RV, typename IT, typename... Args>
auto operator()(RV (IT::*func)(Args...), Args... args) -> RV {
return static_cast<_interface<IT>*>(this)->call(func)(args...);
}
template <typename RV, typename IT, typename... Args>
auto operator[](RV (IT::*func)(Args...)) -> std::function<RV(Args...)> {
return static_cast<_interface<IT>*>(this)->call(func);
//IT* iface = get<IT>().operator->();
//return [iface, func](Args... args){ (iface->*func)(args...); };
}
template <typename it>
_interface<it>& get() {
static_assert(std::is_base_of<_interface<it>, interface_wrapper<ts...>>::value, "Non-exsitent interface requested");
return *static_cast<_interface<it>*>(this);
}
};
struct interface1 {
virtual void test() = 0;
virtual void test2(int i) = 0;
};
struct interface2 {
virtual void test() = 0;
virtual void test2(bool i) = 0;
};
#include <iostream>
struct c_handler1: interface1 {
using Args = int;
c_handler1(int i) {}
void test() { std::cout << "Test 1" << std::endl; }
void test2(int i) { std::cout << "Test 1 " << i << std::endl; }
};
struct c_handler2: interface2 {
using Args = double;
c_handler2(double d) {}
void test() { std::cout << "Test 2" << std::endl; }
void test2(bool i) { std::cout << "Test 1 " << i << std::endl; }
};
int main() {
auto i = *interface_wrapper<interface1, interface2>::concrete_creator<c_handler1, c_handler2>::create(3.23, 1);
auto c1 = new c_handler1(3);
auto c2 = new c_handler2(3.3);
auto i2 = interface_wrapper<interface1, interface2>(c1, c2);
i[&interface1::test]();
i[&interface2::test]();
i[&interface1::test2](4);
i[&interface2::test2](true);
return 0;
}