Line data Source code
1 : /****************************************************************************
2 : **
3 : ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 : ** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
5 : ** Contact: http://www.qt-project.org/legal
6 : **
7 : ** This file is part of the QtCore module of the Qt Toolkit.
8 : **
9 : ** $QT_BEGIN_LICENSE:LGPL$
10 : ** Commercial License Usage
11 : ** Licensees holding valid commercial Qt licenses may use this file in
12 : ** accordance with the commercial license agreement provided with the
13 : ** Software or, alternatively, in accordance with the terms contained in
14 : ** a written agreement between you and Digia. For licensing terms and
15 : ** conditions see http://qt.digia.com/licensing. For further information
16 : ** use the contact form at http://qt.digia.com/contact-us.
17 : **
18 : ** GNU Lesser General Public License Usage
19 : ** Alternatively, this file may be used under the terms of the GNU Lesser
20 : ** General Public License version 2.1 as published by the Free Software
21 : ** Foundation and appearing in the file LICENSE.LGPL included in the
22 : ** packaging of this file. Please review the following information to
23 : ** ensure the GNU Lesser General Public License version 2.1 requirements
24 : ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 : **
26 : ** In addition, as a special exception, Digia gives you certain additional
27 : ** rights. These rights are described in the Digia Qt LGPL Exception
28 : ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 : **
30 : ** GNU General Public License Usage
31 : ** Alternatively, this file may be used under the terms of the GNU
32 : ** General Public License version 3.0 as published by the Free Software
33 : ** Foundation and appearing in the file LICENSE.GPL included in the
34 : ** packaging of this file. Please review the following information to
35 : ** ensure the GNU General Public License version 3.0 requirements will be
36 : ** met: http://www.gnu.org/copyleft/gpl.html.
37 : **
38 : **
39 : ** $QT_END_LICENSE$
40 : **
41 : ****************************************************************************/
42 :
43 : #ifndef Q_QDOC
44 :
45 : #ifndef QOBJECTDEFS_H
46 : #error Do not include qobjectdefs_impl.h directly
47 : #endif
48 :
49 : #if 0
50 : #pragma qt_sync_skip_header_check
51 : #pragma qt_sync_stop_processing
52 : #endif
53 :
54 : QT_BEGIN_NAMESPACE
55 :
56 :
57 : namespace QtPrivate {
58 : template <typename T> struct RemoveRef { typedef T Type; };
59 : template <typename T> struct RemoveRef<T&> { typedef T Type; };
60 : template <typename T> struct RemoveConstRef { typedef T Type; };
61 : template <typename T> struct RemoveConstRef<const T&> { typedef T Type; };
62 :
63 : /*
64 : The following List classes are used to help to handle the list of arguments.
65 : It follow the same principles as the lisp lists.
66 : List_Left<L,N> take a list and a number as a parameter and returns (via the Value typedef,
67 : the list composed of the first N element of the list
68 : */
69 : #ifndef Q_COMPILER_VARIADIC_TEMPLATES
70 : template <typename Head, typename Tail> struct List { typedef Head Car; typedef Tail Cdr; };
71 : template <typename L, int N> struct List_Left { typedef List<typename L::Car, typename List_Left<typename L::Cdr, N - 1>::Value > Value; };
72 : template <typename L> struct List_Left<L,0> { typedef void Value; };
73 : #else
74 : // With variadic template, lists are represented using a variadic template argument instead of the lisp way
75 : template <typename...> struct List {};
76 : template <typename Head, typename... Tail> struct List<Head, Tail...> { typedef Head Car; typedef List<Tail...> Cdr; };
77 : template <typename, typename> struct List_Append;
78 : template <typename... L1, typename...L2> struct List_Append<List<L1...>, List<L2...>> { typedef List<L1..., L2...> Value; };
79 : template <typename L, int N> struct List_Left {
80 : typedef typename List_Append<List<typename L::Car>,typename List_Left<typename L::Cdr, N - 1>::Value>::Value Value;
81 : };
82 : template <typename L> struct List_Left<L, 0> { typedef List<> Value; };
83 : #endif
84 : // List_Select<L,N> returns (via typedef Value) the Nth element of the list L
85 : template <typename L, int N> struct List_Select { typedef typename List_Select<typename L::Cdr, N - 1>::Value Value; };
86 : template <typename L> struct List_Select<L,0> { typedef typename L::Car Value; };
87 :
88 : /*
89 : trick to set the return value of a slot that works even if the signal or the slot returns void
90 : to be used like function(), ApplyReturnValue<ReturnType>(&return_value)
91 : if function() returns a value, the operator,(T, ApplyReturnValue<ReturnType>) is called, but if it
92 : returns void, the builtin one is used without an error.
93 : */
94 : template <typename T>
95 : struct ApplyReturnValue {
96 : void *data;
97 12 : explicit ApplyReturnValue(void *data_) : data(data_) {}
98 : };
99 : template<typename T, typename U>
100 : void operator,(const T &value, const ApplyReturnValue<U> &container) {
101 : if (container.data)
102 : *reinterpret_cast<U*>(container.data) = value;
103 : }
104 : #ifdef Q_COMPILER_RVALUE_REFS
105 : template<typename T, typename U>
106 : void operator,(T &&value, const ApplyReturnValue<U> &container) {
107 : if (container.data)
108 : *reinterpret_cast<U*>(container.data) = value;
109 : }
110 : #endif
111 : template<typename T>
112 : void operator,(T, const ApplyReturnValue<void> &) {}
113 :
114 :
115 : /*
116 : The FunctionPointer<Func> struct is a type trait for function pointer.
117 : - ArgumentCount is the number of argument, or -1 if it is unknown
118 : - the Object typedef is the Object of a pointer to member function
119 : - the Arguments typedef is the list of argument (in a QtPrivate::List)
120 : - the Function typedef is an alias to the template parameter Func
121 : - the call<Args, R>(f,o,args) method is used to call that slot
122 : Args is the list of argument of the signal
123 : R is the return type of the signal
124 : f is the function pointer
125 : o is the receiver object
126 : and args is the array of pointer to arguments, as used in qt_metacall
127 :
128 : The Functor<Func,N> struct is the helper to call a functor of N argument.
129 : its call function is the same as the FunctionPointer::call function.
130 : */
131 : #ifndef Q_COMPILER_VARIADIC_TEMPLATES
132 : template<typename Func> struct FunctionPointer { enum {ArgumentCount = -1, IsPointerToMemberFunction = false}; };
133 : //Pointers to member functions
134 : template<class Obj, typename Ret> struct FunctionPointer<Ret (Obj::*) ()>
135 : {
136 : typedef Obj Object;
137 : typedef void Arguments;
138 : typedef Ret ReturnType;
139 : typedef Ret (Obj::*Function) ();
140 : enum {ArgumentCount = 0, IsPointerToMemberFunction = true};
141 : template <typename Args, typename R>
142 : static void call(Function f, Obj *o, void **arg) { (o->*f)(), ApplyReturnValue<R>(arg[0]); }
143 : };
144 : template<class Obj, typename Ret, typename Arg1> struct FunctionPointer<Ret (Obj::*) (Arg1)>
145 : {
146 : typedef Obj Object;
147 : typedef List<Arg1, void> Arguments;
148 : typedef Ret ReturnType;
149 : typedef Ret (Obj::*Function) (Arg1);
150 : enum {ArgumentCount = 1, IsPointerToMemberFunction = true};
151 : template <typename Args, typename R>
152 : static void call(Function f, Obj *o, void **arg) {
153 : (o->*f)((*reinterpret_cast<typename RemoveRef<typename Args::Car>::Type *>(arg[1]))), ApplyReturnValue<R>(arg[0]);
154 : }
155 : };
156 : template<class Obj, typename Ret, typename Arg1, typename Arg2> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2)>
157 : {
158 : typedef Obj Object;
159 : typedef List<Arg1, List<Arg2, void> > Arguments;
160 : typedef Ret ReturnType;
161 : typedef Ret (Obj::*Function) (Arg1, Arg2);
162 : enum {ArgumentCount = 2, IsPointerToMemberFunction = true};
163 : template <typename Args, typename R>
164 : static void call(Function f, Obj *o, void **arg) {
165 : (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
166 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2])), ApplyReturnValue<R>(arg[0]);
167 : }
168 : };
169 : template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3)>
170 : {
171 : typedef Obj Object;
172 : typedef List<Arg1, List<Arg2, List<Arg3, void> > > Arguments;
173 : typedef Ret ReturnType;
174 : typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3);
175 : enum {ArgumentCount = 3, IsPointerToMemberFunction = true};
176 : template <typename Args, typename R>
177 : static void call(Function f, Obj *o, void **arg) {
178 : (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
179 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
180 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3])), ApplyReturnValue<R>(arg[0]);
181 : }
182 : };
183 : template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4)>
184 : {
185 : typedef Obj Object;
186 : typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > > Arguments;
187 : typedef Ret ReturnType;
188 : typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4);
189 : enum {ArgumentCount = 4, IsPointerToMemberFunction = true};
190 : template <typename Args, typename R>
191 : static void call(Function f, Obj *o, void **arg) {
192 : (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
193 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
194 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
195 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]);
196 : }
197 : };
198 : template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4, Arg5)>
199 : {
200 : typedef Obj Object;
201 : typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, void> > > > > Arguments;
202 : typedef Ret ReturnType;
203 : typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5);
204 : enum {ArgumentCount = 5, IsPointerToMemberFunction = true};
205 : template <typename Args, typename R>
206 : static void call(Function f, Obj *o, void **arg) {
207 : (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
208 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
209 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
210 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]),
211 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]);
212 : }
213 : };
214 : template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6>
215 : struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)>
216 : {
217 : typedef Obj Object;
218 : typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > > Arguments;
219 : typedef Ret ReturnType;
220 : typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6);
221 : enum {ArgumentCount = 6, IsPointerToMemberFunction = true};
222 : template <typename Args, typename R>
223 : static void call(Function f, Obj *o, void **arg) {
224 : (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
225 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
226 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
227 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]),
228 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]),
229 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), ApplyReturnValue<R>(arg[0]);
230 : }
231 : };
232 :
233 : //Pointers to const member functions
234 : template<class Obj, typename Ret> struct FunctionPointer<Ret (Obj::*) () const>
235 : {
236 : typedef Obj Object;
237 : typedef void Arguments;
238 : typedef Ret ReturnType;
239 : typedef Ret (Obj::*Function) () const;
240 : enum {ArgumentCount = 0, IsPointerToMemberFunction = true};
241 : template <typename Args, typename R>
242 : static void call(Function f, Obj *o, void **arg) { (o->*f)(), ApplyReturnValue<R>(arg[0]); }
243 : };
244 : template<class Obj, typename Ret, typename Arg1> struct FunctionPointer<Ret (Obj::*) (Arg1) const>
245 : {
246 : typedef Obj Object;
247 : typedef List<Arg1, void> Arguments;
248 : typedef Ret ReturnType;
249 : typedef Ret (Obj::*Function) (Arg1) const;
250 : enum {ArgumentCount = 1, IsPointerToMemberFunction = true};
251 : template <typename Args, typename R>
252 : static void call(Function f, Obj *o, void **arg) {
253 : (o->*f)((*reinterpret_cast<typename RemoveRef<typename Args::Car>::Type *>(arg[1]))), ApplyReturnValue<R>(arg[0]);
254 : }
255 : };
256 : template<class Obj, typename Ret, typename Arg1, typename Arg2> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2) const>
257 : {
258 : typedef Obj Object;
259 : typedef List<Arg1, List<Arg2, void> > Arguments;
260 : typedef Ret ReturnType;
261 : typedef Ret (Obj::*Function) (Arg1, Arg2) const;
262 : enum {ArgumentCount = 2, IsPointerToMemberFunction = true};
263 : template <typename Args, typename R>
264 : static void call(Function f, Obj *o, void **arg) {
265 : (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
266 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2])), ApplyReturnValue<R>(arg[0]);
267 : }
268 : };
269 : template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3) const>
270 : {
271 : typedef Obj Object;
272 : typedef List<Arg1, List<Arg2, List<Arg3, void> > > Arguments;
273 : typedef Ret ReturnType;
274 : typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3) const;
275 : enum {ArgumentCount = 3, IsPointerToMemberFunction = true};
276 : template <typename Args, typename R>
277 : static void call(Function f, Obj *o, void **arg) {
278 : (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
279 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
280 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3])), ApplyReturnValue<R>(arg[0]);
281 : }
282 : };
283 : template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4) const>
284 : {
285 : typedef Obj Object;
286 : typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > > Arguments;
287 : typedef Ret ReturnType;
288 : typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4) const;
289 : enum {ArgumentCount = 4, IsPointerToMemberFunction = true};
290 : template <typename Args, typename R>
291 : static void call(Function f, Obj *o, void **arg) {
292 : (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
293 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
294 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
295 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]);
296 : }
297 : };
298 : template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4, Arg5) const>
299 : {
300 : typedef Obj Object;
301 : typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, void> > > > > Arguments;
302 : typedef Ret ReturnType;
303 : typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5) const;
304 : enum {ArgumentCount = 5, IsPointerToMemberFunction = true};
305 : template <typename Args, typename R>
306 : static void call(Function f, Obj *o, void **arg) {
307 : (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
308 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
309 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
310 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]),
311 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]);
312 : }
313 : };
314 : template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6>
315 : struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const>
316 : {
317 : typedef Obj Object;
318 : typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > > Arguments;
319 : typedef Ret ReturnType;
320 : typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const;
321 : enum {ArgumentCount = 6, IsPointerToMemberFunction = true};
322 : template <typename Args, typename R>
323 : static void call(Function f, Obj *o, void **arg) {
324 : (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
325 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
326 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
327 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]),
328 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]),
329 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), ApplyReturnValue<R>(arg[0]);
330 : }
331 : };
332 :
333 : //Static functions
334 : template<typename Ret> struct FunctionPointer<Ret (*) ()>
335 : {
336 : typedef void Arguments;
337 : typedef Ret (*Function) ();
338 : typedef Ret ReturnType;
339 : enum {ArgumentCount = 0, IsPointerToMemberFunction = false};
340 : template <typename Args, typename R>
341 : static void call(Function f, void *, void **arg) { f(), ApplyReturnValue<R>(arg[0]); }
342 : };
343 : template<typename Ret, typename Arg1> struct FunctionPointer<Ret (*) (Arg1)>
344 : {
345 : typedef List<Arg1, void> Arguments;
346 : typedef Ret ReturnType;
347 : typedef Ret (*Function) (Arg1);
348 : enum {ArgumentCount = 1, IsPointerToMemberFunction = false};
349 : template <typename Args, typename R>
350 : static void call(Function f, void *, void **arg)
351 : { f(*reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1])), ApplyReturnValue<R>(arg[0]); }
352 : };
353 : template<typename Ret, typename Arg1, typename Arg2> struct FunctionPointer<Ret (*) (Arg1, Arg2)>
354 : {
355 : typedef List<Arg1, List<Arg2, void> > Arguments;
356 : typedef Ret ReturnType;
357 : typedef Ret (*Function) (Arg1, Arg2);
358 : enum {ArgumentCount = 2, IsPointerToMemberFunction = false};
359 : template <typename Args, typename R>
360 : static void call(Function f, void *, void **arg) {
361 : f(*reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
362 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2])), ApplyReturnValue<R>(arg[0]); }
363 : };
364 : template<typename Ret, typename Arg1, typename Arg2, typename Arg3> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3)>
365 : {
366 : typedef List<Arg1, List<Arg2, List<Arg3, void> > > Arguments;
367 : typedef Ret ReturnType;
368 : typedef Ret (*Function) (Arg1, Arg2, Arg3);
369 : enum {ArgumentCount = 3, IsPointerToMemberFunction = false};
370 : template <typename Args, typename R>
371 : static void call(Function f, void *, void **arg) {
372 : f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
373 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
374 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3])), ApplyReturnValue<R>(arg[0]);
375 : }
376 : };
377 : template<typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3, Arg4)>
378 : {
379 : typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > > Arguments;
380 : typedef Ret ReturnType;
381 : typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4);
382 : enum {ArgumentCount = 4, IsPointerToMemberFunction = false};
383 : template <typename Args, typename R>
384 : static void call(Function f, void *, void **arg) {
385 : f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
386 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
387 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
388 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]);
389 : }
390 : };
391 : template<typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3, Arg4, Arg5)>
392 : {
393 : typedef List<Arg1, List<Arg2, List<Arg3,
394 : List<Arg4, List<Arg5, void > > > > > Arguments;
395 : typedef Ret ReturnType;
396 : typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5);
397 : enum {ArgumentCount = 5, IsPointerToMemberFunction = false};
398 : template <typename Args, typename R>
399 : static void call(Function f, void *, void **arg) {
400 : f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
401 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
402 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
403 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]),
404 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]);
405 : }
406 : };
407 : template<typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)>
408 : {
409 : typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > > Arguments;
410 : typedef Ret ReturnType;
411 : typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6);
412 : enum {ArgumentCount = 6, IsPointerToMemberFunction = false};
413 : template <typename Args, typename R>
414 : static void call(Function f, void *, void **arg) {
415 : f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
416 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
417 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
418 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]),
419 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]),
420 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), ApplyReturnValue<R>(arg[0]);
421 : }
422 : };
423 :
424 : //Functors
425 : template<typename F, int N> struct Functor;
426 : template<typename Function> struct Functor<Function, 0>
427 : {
428 : template <typename Args, typename R>
429 : static void call(Function &f, void *, void **arg) { f(), ApplyReturnValue<R>(arg[0]); }
430 : };
431 : template<typename Function> struct Functor<Function, 1>
432 : {
433 : template <typename Args, typename R>
434 : static void call(Function &f, void *, void **arg) {
435 : f(*reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1])), ApplyReturnValue<R>(arg[0]);
436 : }
437 : };
438 : template<typename Function> struct Functor<Function, 2>
439 : {
440 : template <typename Args, typename R>
441 : static void call(Function &f, void *, void **arg) {
442 : f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
443 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2])), ApplyReturnValue<R>(arg[0]);
444 : }
445 : };
446 : template<typename Function> struct Functor<Function, 3>
447 : {
448 : template <typename Args, typename R>
449 : static void call(Function &f, void *, void **arg) {
450 : f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
451 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
452 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3])), ApplyReturnValue<R>(arg[0]);
453 : }
454 : };
455 : template<typename Function> struct Functor<Function, 4>
456 : {
457 : template <typename Args, typename R>
458 : static void call(Function &f, void *, void **arg) {
459 : f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
460 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
461 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
462 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]);
463 : }
464 : };
465 : template<typename Function> struct Functor<Function, 5>
466 : {
467 : template <typename Args, typename R>
468 : static void call(Function &f, void *, void **arg) {
469 : f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
470 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
471 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
472 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]),
473 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]);
474 : }
475 : };
476 : template<typename Function> struct Functor<Function, 6>
477 : {
478 : template <typename Args, typename R>
479 : static void call(Function &f, void *, void **arg) {
480 : f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
481 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
482 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
483 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]),
484 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]),
485 : *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), ApplyReturnValue<R>(arg[0]);
486 : }
487 : };
488 : #else
489 : template <int...> struct IndexesList {};
490 : template <typename IndexList, int Right> struct IndexesAppend;
491 : template <int... Left, int Right> struct IndexesAppend<IndexesList<Left...>, Right>
492 : { typedef IndexesList<Left..., Right> Value; };
493 : template <int N> struct Indexes
494 : { typedef typename IndexesAppend<typename Indexes<N - 1>::Value, N - 1>::Value Value; };
495 : template <> struct Indexes<0> { typedef IndexesList<> Value; };
496 : template<typename Func> struct FunctionPointer { enum {ArgumentCount = -1, IsPointerToMemberFunction = false}; };
497 :
498 : template <typename, typename, typename, typename> struct FunctorCall;
499 : template <int... II, typename... SignalArgs, typename R, typename Function>
500 : struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, Function> {
501 7 : static void call(Function f, void **arg) {
502 7 : f((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]);
503 7 : }
504 : };
505 : template <int... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj>
506 : struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...)> {
507 5 : static void call(SlotRet (Obj::*f)(SlotArgs...), Obj *o, void **arg) {
508 5 : (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]);
509 5 : }
510 : };
511 : template <int... II, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj>
512 : struct FunctorCall<IndexesList<II...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...) const> {
513 : static void call(SlotRet (Obj::*f)(SlotArgs...) const, Obj *o, void **arg) {
514 : (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[II+1]))...), ApplyReturnValue<R>(arg[0]);
515 : }
516 : };
517 :
518 : template<class Obj, typename Ret, typename... Args> struct FunctionPointer<Ret (Obj::*) (Args...)>
519 : {
520 : typedef Obj Object;
521 : typedef List<Args...> Arguments;
522 : typedef Ret ReturnType;
523 : typedef Ret (Obj::*Function) (Args...);
524 : enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = true};
525 : template <typename SignalArgs, typename R>
526 5 : static void call(Function f, Obj *o, void **arg) {
527 5 : FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, o, arg);
528 5 : }
529 : };
530 : template<class Obj, typename Ret, typename... Args> struct FunctionPointer<Ret (Obj::*) (Args...) const>
531 : {
532 : typedef Obj Object;
533 : typedef List<Args...> Arguments;
534 : typedef Ret ReturnType;
535 : typedef Ret (Obj::*Function) (Args...) const;
536 : enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = true};
537 : template <typename SignalArgs, typename R>
538 : static void call(Function f, Obj *o, void **arg) {
539 : FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, o, arg);
540 : }
541 : };
542 :
543 : template<typename Ret, typename... Args> struct FunctionPointer<Ret (*) (Args...)>
544 : {
545 : typedef List<Args...> Arguments;
546 : typedef Ret ReturnType;
547 : typedef Ret (*Function) (Args...);
548 : enum {ArgumentCount = sizeof...(Args), IsPointerToMemberFunction = false};
549 : template <typename SignalArgs, typename R>
550 : static void call(Function f, void *, void **arg) {
551 : FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, arg);
552 : }
553 : };
554 :
555 : template<typename Function, int N> struct Functor
556 : {
557 : template <typename SignalArgs, typename R>
558 7 : static void call(Function &f, void *, void **arg) {
559 7 : FunctorCall<typename Indexes<N>::Value, SignalArgs, R, Function>::call(f, arg);
560 7 : }
561 : };
562 : #endif
563 :
564 : /*
565 : Logic that check if the arguments of the slot matches the argument of the signal.
566 : To be used like this:
567 : Q_STATIC_ASSERT(CheckCompatibleArguments<FunctionPointer<Signal>::Arguments, FunctionPointer<Slot>::Arguments>::value)
568 : */
569 : template<typename A1, typename A2> struct AreArgumentsCompatible {
570 : static int test(const typename RemoveRef<A2>::Type&);
571 : static char test(...);
572 : static const typename RemoveRef<A1>::Type &dummy();
573 : enum { value = sizeof(test(dummy())) == sizeof(int) };
574 : };
575 : template<typename A1, typename A2> struct AreArgumentsCompatible<A1, A2&> { enum { value = false }; };
576 : template<typename A> struct AreArgumentsCompatible<A&, A&> { enum { value = true }; };
577 : // void as a return value
578 : template<typename A> struct AreArgumentsCompatible<void, A> { enum { value = true }; };
579 : template<typename A> struct AreArgumentsCompatible<A, void> { enum { value = true }; };
580 : template<> struct AreArgumentsCompatible<void, void> { enum { value = true }; };
581 :
582 : #ifndef Q_COMPILER_VARIADIC_TEMPLATES
583 : template <typename List1, typename List2> struct CheckCompatibleArguments { enum { value = false }; };
584 : template <> struct CheckCompatibleArguments<void, void> { enum { value = true }; };
585 : template <typename List1> struct CheckCompatibleArguments<List1, void> { enum { value = true }; };
586 : template <typename Arg1, typename Arg2, typename Tail1, typename Tail2> struct CheckCompatibleArguments<List<Arg1, Tail1>, List<Arg2, Tail2> >
587 : {
588 : enum { value = AreArgumentsCompatible<typename RemoveConstRef<Arg1>::Type, typename RemoveConstRef<Arg2>::Type>::value
589 : && CheckCompatibleArguments<Tail1, Tail2>::value };
590 : };
591 : #else
592 : template <typename List1, typename List2> struct CheckCompatibleArguments { enum { value = false }; };
593 : template <> struct CheckCompatibleArguments<List<>, List<>> { enum { value = true }; };
594 : template <typename List1> struct CheckCompatibleArguments<List1, List<>> { enum { value = true }; };
595 : template <typename Arg1, typename Arg2, typename... Tail1, typename... Tail2>
596 : struct CheckCompatibleArguments<List<Arg1, Tail1...>, List<Arg2, Tail2...>>
597 : {
598 : enum { value = AreArgumentsCompatible<typename RemoveConstRef<Arg1>::Type, typename RemoveConstRef<Arg2>::Type>::value
599 : && CheckCompatibleArguments<List<Tail1...>, List<Tail2...>>::value };
600 : };
601 : #endif
602 :
603 : #if defined(Q_COMPILER_DECLTYPE) && defined(Q_COMPILER_VARIADIC_TEMPLATES)
604 : /*
605 : Find the maximum number of arguments a functor object can take and be still compatible with
606 : the arguments from the signal.
607 : Value is the number of arguments, or -1 if nothing matches.
608 : */
609 : template <typename Functor, typename ArgList> struct ComputeFunctorArgumentCount;
610 :
611 : template <typename Functor, typename ArgList, bool Done> struct ComputeFunctorArgumentCountHelper
612 : { enum { Value = -1 }; };
613 : template <typename Functor, typename First, typename... ArgList>
614 : struct ComputeFunctorArgumentCountHelper<Functor, List<First, ArgList...>, false>
615 : : ComputeFunctorArgumentCount<Functor,
616 : typename List_Left<List<First, ArgList...>, sizeof...(ArgList)>::Value> {};
617 :
618 : template <typename Functor, typename... ArgList> struct ComputeFunctorArgumentCount<Functor, List<ArgList...>>
619 : {
620 : template <typename D> static D dummy();
621 : template <typename F> static auto test(F f) -> decltype(((f.operator()((dummy<ArgList>())...)), int()));
622 : static char test(...);
623 : enum {
624 : Ok = sizeof(test(dummy<Functor>())) == sizeof(int),
625 : Value = Ok ? int(sizeof...(ArgList)) : int(ComputeFunctorArgumentCountHelper<Functor, List<ArgList...>, Ok>::Value)
626 : };
627 : };
628 :
629 : /* get the return type of a functor, given the signal argument list */
630 : template <typename Functor, typename ArgList> struct FunctorReturnType;
631 : template <typename Functor, typename ... ArgList> struct FunctorReturnType<Functor, List<ArgList...>> {
632 : template <typename D> static D dummy();
633 : typedef decltype(dummy<Functor>().operator()((dummy<ArgList>())...)) Value;
634 : };
635 : #endif
636 :
637 : }
638 :
639 : QT_END_NAMESPACE
640 :
641 : #endif
|