]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright 2015-2016 Klemens D. Morgenstern |
2 | // | |
3 | // Distributed under the Boost Software License, Version 1.0. | |
4 | // (See accompanying file LICENSE_1_0.txt | |
5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | ||
7 | #ifndef BOOST_DLL_DETAIL_IMPORT_MANGLED_HELPERS_HPP_ | |
8 | #define BOOST_DLL_DETAIL_IMPORT_MANGLED_HELPERS_HPP_ | |
9 | ||
10 | ||
11 | #include <boost/type_traits/conditional.hpp> | |
12 | #include <boost/type_traits/is_same.hpp> | |
13 | #include <boost/type_traits/is_class.hpp> | |
14 | #include <boost/type_traits/is_function.hpp> | |
15 | #include <boost/type_traits/remove_cv.hpp> | |
16 | ||
17 | ||
18 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
19 | # pragma once | |
20 | #endif | |
21 | ||
22 | namespace boost { namespace dll { namespace experimental { namespace detail { | |
23 | ||
24 | //the following could be done by fusion, though it's simple enough to just declare it here. | |
25 | template<class ...Args> | |
26 | struct sequence {}; | |
27 | ||
28 | template<class Value, class Seq> struct push_front; | |
29 | template<class Value, class ...Args> | |
30 | struct push_front<Value, sequence<Args...>> | |
31 | { | |
32 | typedef sequence<Value, Args...> type; | |
33 | }; | |
34 | ||
35 | template<class Lhs, class Rhs> | |
36 | struct unqalified_is_same : | |
37 | boost::is_same< | |
38 | typename boost::remove_cv<Lhs>::type, | |
39 | typename boost::remove_cv<Rhs>::type | |
40 | > | |
41 | { | |
42 | }; | |
43 | ||
44 | /* ********************************** function sequence type traits ******************************/ | |
45 | ||
46 | //determine if it's a sequence of functions. | |
47 | template<class T> struct is_function_seq; | |
48 | ||
49 | //type-trait for function overloads | |
50 | template<class Class, class...Args> struct is_function_seq<sequence<Class, Args...>> | |
51 | : boost::conditional< | |
52 | boost::is_function<Class>::value, | |
53 | is_function_seq<sequence<Args...>>, | |
54 | boost::false_type>::type | |
55 | {}; | |
56 | ||
57 | template<class Class> | |
58 | struct is_function_seq<sequence<Class>> : boost::is_function<Class> | |
59 | { | |
60 | }; | |
61 | ||
62 | template<> | |
63 | struct is_function_seq<sequence<>> : boost::false_type | |
64 | { | |
65 | }; | |
66 | ||
67 | /* ********************************* Function Tuple *************************** */ | |
68 | ||
69 | //a tuple of plain functions. | |
70 | template <class ...Ts> | |
71 | struct function_tuple; | |
72 | ||
73 | template <class Return, class...Args, class T2, class ...Ts> | |
74 | struct function_tuple<Return(Args...), T2, Ts...> : function_tuple<T2, Ts...> | |
75 | { | |
76 | constexpr function_tuple(Return(* t)(Args...), T2* t2, Ts* ... ts) : function_tuple<T2, Ts...>(t2, ts...), _f(t) {}; | |
77 | Return(*_f)(Args...); | |
78 | ||
79 | Return operator()(Args...args) | |
80 | { | |
81 | return (*_f)(static_cast<Args>(args)...); | |
82 | } | |
83 | using function_tuple<T2, Ts...>::operator(); | |
84 | ||
85 | }; | |
86 | ||
87 | template <class Return, class...Args> | |
88 | struct function_tuple<Return(Args...)> | |
89 | { | |
90 | constexpr function_tuple(Return(* t)(Args...)) : _f(t) {}; | |
91 | Return(*_f)(Args...); | |
92 | ||
93 | Return operator()(Args...args) | |
94 | { | |
95 | return (*_f)(static_cast<Args>(args)...); | |
96 | } | |
97 | }; | |
98 | ||
99 | ||
100 | /* ********************************** MemFn sequence type traits ******************************/ | |
101 | ||
102 | template<class Class, class Func> | |
103 | struct mem_fn_def | |
104 | { | |
105 | typedef Class class_type; | |
106 | typedef Func func_type; | |
107 | typedef typename boost::dll::detail::get_mem_fn_type<Class, Func>::mem_fn mem_fn; | |
108 | }; | |
109 | ||
110 | template<class ...Args> | |
111 | struct make_mem_fn_seq; | |
112 | ||
113 | // B: is T1 another version of T0? | |
114 | template<bool, class T0, class T1, class T2> | |
115 | struct make_mem_fn_seq_getter; | |
116 | ||
117 | template<class T0, class T1, class T2> | |
118 | struct make_mem_fn_seq_getter<true, T0, T1, T2> | |
119 | { | |
120 | typedef mem_fn_def<T1, T2> type; | |
121 | }; | |
122 | ||
123 | template<class T0, class T1, class T2> | |
124 | struct make_mem_fn_seq_getter<false, T0, T1, T2> | |
125 | { | |
126 | typedef mem_fn_def<T0, T1> type; | |
127 | }; | |
128 | ||
129 | template<class Class, class Signature> | |
130 | struct make_mem_fn_seq<Class, Signature> | |
131 | { | |
132 | typedef mem_fn_def<Class, Signature> mem_fn; | |
133 | typedef sequence<mem_fn> type; | |
134 | }; | |
135 | ||
136 | template<class Class> | |
137 | struct make_mem_fn_seq<Class> | |
138 | { | |
139 | typedef sequence<> type; | |
140 | }; | |
141 | ||
142 | template<class T0, class T1, class T2, class ... Args> | |
143 | struct make_mem_fn_seq<T0, T1, T2, Args...> | |
144 | { | |
145 | /* Since we might have ovls, it might be : | |
146 | * Class, void(int), void(int, int) //--> just us class for both | |
147 | * Class, const Class, void(int)//--> ovl class. | |
148 | * | |
149 | */ | |
150 | static_assert(boost::is_object<T0>::value, ""); | |
151 | typedef typename make_mem_fn_seq_getter< | |
152 | unqalified_is_same<T0, T1>::value, T0, T1, T2>::type mem_fn_type; | |
153 | ||
154 | typedef typename boost::conditional< | |
155 | unqalified_is_same<T0, T1>::value, | |
156 | make_mem_fn_seq<T1, Args...>, | |
157 | make_mem_fn_seq<T0, T2, Args...>> ::type next; | |
158 | ||
159 | typedef typename push_front<mem_fn_type, typename next::type>::type type; | |
160 | }; | |
161 | ||
162 | ||
163 | ||
164 | ||
165 | /* Ok, this needs to be documented, so here's some pseudo-code: | |
166 | * | |
167 | * @code | |
168 | * | |
169 | * bool unqalified_is_same(lhs, rhs) | |
170 | * { | |
171 | * return remove_cv(lhs) == remove_cv(rhs); | |
172 | * } | |
173 | * | |
174 | * mem_fn make_mem_fn_seq_getter(b, cl, T2, T3) | |
175 | * { | |
176 | * if (b) //b means, that T2 is another version of cl, i.e. qualified | |
177 | * return get_mem_fn_type(T2, T3); | |
178 | * else //means that T2 is a function. | |
179 | * return get_mem_fn_type(cl, T2); | |
180 | * } | |
181 | * | |
182 | * sequence make_mem_fn_seq(type cl, type T2, type T3, types...) | |
183 | * { | |
184 | * mem_fn = make_mem_fn_seq_getter( | |
185 | * unqalified_is_same(cl, T2), cl, T2, T3); | |
186 | * | |
187 | * next = unqalified_is_same(cl, T2) ? | |
188 | * make_mem_fn_seq(T2, types...) //because: T2 is another version of cl, hence i use this. T3 was already consumed. | |
189 | * : | |
190 | * make_mem_fn_seq(Class, T3, types...) //because: T2 was a function, hence it is consumed and class remains unchanged. | |
191 | * ; | |
192 | * return push_front(mem_fn, next) ; | |
193 | * }; | |
194 | * @endcode | |
195 | */ | |
196 | ||
197 | ||
198 | ||
199 | template<class T, class U, class ...Args> | |
200 | struct is_mem_fn_seq_impl | |
201 | { | |
202 | typedef typename boost::conditional< | |
203 | boost::is_function<U>::value || boost::dll::experimental::detail::unqalified_is_same<T, U>::value, | |
204 | typename is_mem_fn_seq_impl<T, Args...>::type, | |
205 | boost::false_type>::type type; | |
206 | }; | |
207 | ||
208 | template<class T, class U> | |
209 | struct is_mem_fn_seq_impl<T, U> | |
210 | { | |
211 | typedef typename boost::conditional< | |
212 | boost::is_function<U>::value && boost::is_object<T>::value, | |
213 | boost::true_type, boost::false_type>::type type; | |
214 | }; | |
215 | ||
216 | template<class T, class U, class Last> | |
217 | struct is_mem_fn_seq_impl<T, U, Last> | |
218 | { | |
219 | typedef typename boost::conditional< | |
220 | (boost::is_function<U>::value || boost::dll::experimental::detail::unqalified_is_same<T, U>::value) | |
221 | && boost::is_function<Last>::value, | |
222 | boost::true_type, boost::false_type>::type type; | |
223 | }; | |
224 | ||
225 | template<class T> struct is_mem_fn_seq : boost::false_type {}; | |
226 | ||
227 | //If only two arguments are provided at all. | |
228 | template<class T, class U> | |
229 | struct is_mem_fn_seq<sequence<T, U>> : boost::conditional< | |
230 | boost::is_object<T>::value && boost::is_function<U>::value, | |
231 | boost::true_type, boost::false_type>::type | |
232 | { | |
233 | }; | |
234 | ||
235 | ||
236 | template<class T, class Func, class ...Args> | |
237 | struct is_mem_fn_seq<sequence<T, Func, Args...>> : | |
238 | boost::conditional< | |
239 | boost::is_class<T>::value && boost::is_function<Func>::value, | |
240 | typename is_mem_fn_seq_impl<T, Args...>::type, | |
241 | boost::false_type>::type {}; | |
242 | ||
243 | ||
244 | /* ********************************** mem fn sequence tuple ******************************/ | |
245 | ||
246 | /* A tuple of member functions | |
247 | * Unlike for plain functions a sequence here might contain classes as well as functions. | |
248 | */ | |
249 | template <class ...Ts> | |
250 | struct mem_fn_tuple; | |
251 | ||
252 | template <class Class, class Return, class...Args, class T2, class ...Ts> | |
253 | struct mem_fn_tuple<mem_fn_def<Class, Return(Args...)>, T2, Ts...> : mem_fn_tuple<T2, Ts...> | |
254 | { | |
255 | typedef typename boost::dll::detail::get_mem_fn_type<Class, Return(Args...)>::mem_fn mem_fn; | |
256 | ||
257 | constexpr mem_fn_tuple(mem_fn f, typename T2::mem_fn t2, typename Ts::mem_fn ... ts) | |
258 | : mem_fn_tuple<T2, Ts...>(t2, ts...), _f(f) {}; | |
259 | mem_fn _f; | |
260 | ||
261 | Return operator()(Class* const cl, Args...args) | |
262 | { | |
263 | return (cl->*_f)(static_cast<Args>(args)...); | |
264 | } | |
265 | using mem_fn_tuple<T2, Ts...>::operator(); | |
266 | ||
267 | }; | |
268 | ||
269 | template <class Class, class Return, class...Args> | |
270 | struct mem_fn_tuple<mem_fn_def<Class, Return(Args...)>> | |
271 | { | |
272 | typedef typename boost::dll::detail::get_mem_fn_type<Class, Return(Args...)>::mem_fn mem_fn; | |
273 | ||
274 | constexpr mem_fn_tuple(mem_fn f) : _f(f) {}; | |
275 | mem_fn _f; | |
276 | ||
277 | Return operator()(Class * const cl, Args...args) | |
278 | { | |
279 | return (cl->*_f)(static_cast<Args>(args)...); | |
280 | } | |
281 | }; | |
282 | ||
283 | }}}} | |
284 | #endif /* BOOST_DLL_DETAIL_IMPORT_MANGLED_HELPERS_HPP_ */ |