/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef Q_QDOC #ifndef QOBJECTDEFS_H #error Do not include qobjectdefs_impl.h directly #endif #if 0 #pragma qt_sync_skip_header_check #pragma qt_sync_stop_processing #endif QT_BEGIN_NAMESPACE namespace QtPrivate { template struct RemoveRef { typedef T Type; }; template struct RemoveRef { typedef T Type; }; template struct RemoveConstRef { typedef T Type; }; template struct RemoveConstRef { typedef T Type; }; /* The following List classes are used to help to handle the list of arguments. It follow the same principles as the lisp lists. List_Left take a list and a number as a parametter and returns (via the Value typedef, the list composed of the first N element of the list */ #ifndef Q_COMPILER_VARIADIC_TEMPLATES template struct List { typedef Head Car; typedef Tail Cdr; }; template struct List_Left { typedef List::Value > Value; }; template struct List_Left { typedef void Value; }; #else // With variadic template, lists are represented using a variadic template argument instead of the lisp way template struct List {}; template struct List { typedef Head Car; typedef List Cdr; }; template struct List_Append; template struct List_Append, List> { typedef List Value; }; template struct List_Left { typedef typename List_Append,typename List_Left::Value>::Value Value; }; template struct List_Left { typedef List<> Value; }; #endif // List_Select returns (via typedef Value) the Nth element of the list L template struct List_Select { typedef typename List_Select::Value Value; }; template struct List_Select { typedef typename L::Car Value; }; /* trick to set the return value of a slot that works even if the signal or the slot returns void to be used like function(), ApplyReturnValue(&return_value) if function() returns a value, the operator,(T, ApplyReturnValue) is called, but if it returns void, the builtin one is used without an error. */ template struct ApplyReturnValue { void *data; ApplyReturnValue(void *data_) : data(data_) {} }; template void operator,(const T &value, const ApplyReturnValue &container) { if (container.data) *reinterpret_cast(container.data) = value; } #ifdef Q_COMPILER_RVALUE_REFS template void operator,(T &&value, const ApplyReturnValue &container) { if (container.data) *reinterpret_cast(container.data) = value; } #endif template void operator,(T, const ApplyReturnValue &) {} /* The FunctionPointer struct is a type trait for function pointer. - ArgumentCount is the number of argument, or -1 if it is unknown - the Object typedef is the Object of a pointer to member function - the Arguments typedef is the list of argument (in a QtPrivate::List) - the Function typedef is an alias to the template parametter Func - the call(f,o,args) method is used to call that slot Args is the list of argument of the signal R is the return type of the signal f is the function pointer o is the receiver object and args is the array of pointer to arguments, as used in qt_metacall The Functor struct is the helper to call a functor of N argument. its call function is the same as the FunctionPointer::call function. */ #ifndef Q_COMPILER_VARIADIC_TEMPLATES template struct FunctionPointer { enum {ArgumentCount = -1}; }; //Pointers to member functions template struct FunctionPointer { typedef Obj Object; typedef void Arguments; typedef Ret ReturnType; typedef Ret (Obj::*Function) (); enum {ArgumentCount = 0}; template static void call(Function f, Obj *o, void **arg) { (o->*f)(), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef Obj Object; typedef List Arguments; typedef Ret ReturnType; typedef Ret (Obj::*Function) (Arg1); enum {ArgumentCount = 1}; template static void call(Function f, Obj *o, void **arg) { (o->*f)((*reinterpret_cast::Type *>(arg[1]))), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef Obj Object; typedef List > Arguments; typedef Ret ReturnType; typedef Ret (Obj::*Function) (Arg1, Arg2); enum {ArgumentCount = 2}; template static void call(Function f, Obj *o, void **arg) { (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2])), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef Obj Object; typedef List > > Arguments; typedef Ret ReturnType; typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3); enum {ArgumentCount = 3}; template static void call(Function f, Obj *o, void **arg) { (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2]), *reinterpret_cast::Value>::Type *>(arg[3])), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef Obj Object; typedef List > > > Arguments; typedef Ret ReturnType; typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4); enum {ArgumentCount = 4}; template static void call(Function f, Obj *o, void **arg) { (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2]), *reinterpret_cast::Value>::Type *>(arg[3]), *reinterpret_cast::Value>::Type *>(arg[4])), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef Obj Object; typedef List > > > > Arguments; typedef Ret ReturnType; typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5); enum {ArgumentCount = 5}; template static void call(Function f, Obj *o, void **arg) { (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2]), *reinterpret_cast::Value>::Type *>(arg[3]), *reinterpret_cast::Value>::Type *>(arg[4]), *reinterpret_cast::Value>::Type *>(arg[5])), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef Obj Object; typedef List > > > > > Arguments; typedef Ret ReturnType; typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); enum {ArgumentCount = 6}; template static void call(Function f, Obj *o, void **arg) { (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2]), *reinterpret_cast::Value>::Type *>(arg[3]), *reinterpret_cast::Value>::Type *>(arg[4]), *reinterpret_cast::Value>::Type *>(arg[5]), *reinterpret_cast::Value>::Type *>(arg[6])), ApplyReturnValue(arg[0]); } }; //Pointers to const member functions template struct FunctionPointer { typedef Obj Object; typedef void Arguments; typedef Ret ReturnType; typedef Ret (Obj::*Function) () const; enum {ArgumentCount = 0}; template static void call(Function f, Obj *o, void **arg) { (o->*f)(), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef Obj Object; typedef List Arguments; typedef Ret ReturnType; typedef Ret (Obj::*Function) (Arg1) const; enum {ArgumentCount = 1}; template static void call(Function f, Obj *o, void **arg) { (o->*f)((*reinterpret_cast::Type *>(arg[1]))), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef Obj Object; typedef List > Arguments; typedef Ret ReturnType; typedef Ret (Obj::*Function) (Arg1, Arg2) const; enum {ArgumentCount = 2}; template static void call(Function f, Obj *o, void **arg) { (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2])), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef Obj Object; typedef List > > Arguments; typedef Ret ReturnType; typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3) const; enum {ArgumentCount = 3}; template static void call(Function f, Obj *o, void **arg) { (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2]), *reinterpret_cast::Value>::Type *>(arg[3])), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef Obj Object; typedef List > > > Arguments; typedef Ret ReturnType; typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4) const; enum {ArgumentCount = 4}; template static void call(Function f, Obj *o, void **arg) { (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2]), *reinterpret_cast::Value>::Type *>(arg[3]), *reinterpret_cast::Value>::Type *>(arg[4])), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef Obj Object; typedef List > > > > Arguments; typedef Ret ReturnType; typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5) const; enum {ArgumentCount = 5}; template static void call(Function f, Obj *o, void **arg) { (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2]), *reinterpret_cast::Value>::Type *>(arg[3]), *reinterpret_cast::Value>::Type *>(arg[4]), *reinterpret_cast::Value>::Type *>(arg[5])), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef Obj Object; typedef List > > > > > Arguments; typedef Ret ReturnType; typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const; enum {ArgumentCount = 6}; template static void call(Function f, Obj *o, void **arg) { (o->*f)( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2]), *reinterpret_cast::Value>::Type *>(arg[3]), *reinterpret_cast::Value>::Type *>(arg[4]), *reinterpret_cast::Value>::Type *>(arg[5]), *reinterpret_cast::Value>::Type *>(arg[6])), ApplyReturnValue(arg[0]); } }; //Static functions template struct FunctionPointer { typedef void Arguments; typedef Ret (*Function) (); typedef Ret ReturnType; enum {ArgumentCount = 0}; template static void call(Function f, void *, void **arg) { f(), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef List Arguments; typedef Ret ReturnType; typedef Ret (*Function) (Arg1); enum {ArgumentCount = 1}; template static void call(Function f, void *, void **arg) { f(*reinterpret_cast::Value>::Type *>(arg[1])), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef List > Arguments; typedef Ret ReturnType; typedef Ret (*Function) (Arg1, Arg2); enum {ArgumentCount = 2}; template static void call(Function f, void *, void **arg) { f(*reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2])), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef List > > Arguments; typedef Ret ReturnType; typedef Ret (*Function) (Arg1, Arg2, Arg3); enum {ArgumentCount = 3}; template static void call(Function f, void *, void **arg) { f( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2]), *reinterpret_cast::Value>::Type *>(arg[3])), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef List > > > Arguments; typedef Ret ReturnType; typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4); enum {ArgumentCount = 4}; template static void call(Function f, void *, void **arg) { f( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2]), *reinterpret_cast::Value>::Type *>(arg[3]), *reinterpret_cast::Value>::Type *>(arg[4])), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef List > > > > Arguments; typedef Ret ReturnType; typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5); enum {ArgumentCount = 5}; template static void call(Function f, void *, void **arg) { f( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2]), *reinterpret_cast::Value>::Type *>(arg[3]), *reinterpret_cast::Value>::Type *>(arg[4]), *reinterpret_cast::Value>::Type *>(arg[5])), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef List > > > > > Arguments; typedef Ret ReturnType; typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); enum {ArgumentCount = 6}; template static void call(Function f, void *, void **arg) { f( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2]), *reinterpret_cast::Value>::Type *>(arg[3]), *reinterpret_cast::Value>::Type *>(arg[4]), *reinterpret_cast::Value>::Type *>(arg[5]), *reinterpret_cast::Value>::Type *>(arg[6])), ApplyReturnValue(arg[0]); } }; //Functors template struct Functor; template struct Functor { template static void call(Function &f, void *, void **arg) { f(), ApplyReturnValue(arg[0]); } }; template struct Functor { template static void call(Function &f, void *, void **arg) { f(*reinterpret_cast::Value>::Type *>(arg[1])), ApplyReturnValue(arg[0]); } }; template struct Functor { template static void call(Function &f, void *, void **arg) { f( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2])), ApplyReturnValue(arg[0]); } }; template struct Functor { template static void call(Function &f, void *, void **arg) { f( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2]), *reinterpret_cast::Value>::Type *>(arg[3])), ApplyReturnValue(arg[0]); } }; template struct Functor { template static void call(Function &f, void *, void **arg) { f( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2]), *reinterpret_cast::Value>::Type *>(arg[3]), *reinterpret_cast::Value>::Type *>(arg[4])), ApplyReturnValue(arg[0]); } }; template struct Functor { template static void call(Function &f, void *, void **arg) { f( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2]), *reinterpret_cast::Value>::Type *>(arg[3]), *reinterpret_cast::Value>::Type *>(arg[4]), *reinterpret_cast::Value>::Type *>(arg[5])), ApplyReturnValue(arg[0]); } }; template struct Functor { template static void call(Function &f, void *, void **arg) { f( *reinterpret_cast::Value>::Type *>(arg[1]), *reinterpret_cast::Value>::Type *>(arg[2]), *reinterpret_cast::Value>::Type *>(arg[3]), *reinterpret_cast::Value>::Type *>(arg[4]), *reinterpret_cast::Value>::Type *>(arg[5]), *reinterpret_cast::Value>::Type *>(arg[6])), ApplyReturnValue(arg[0]); } }; #else template struct IndexesList {}; template struct IndexesAppend; template struct IndexesAppend, Right> { typedef IndexesList Value; }; template struct Indexes { typedef typename IndexesAppend::Value, N - 1>::Value Value; }; template <> struct Indexes<0> { typedef IndexesList<> Value; }; template struct FunctionPointer { enum {ArgumentCount = -1}; }; template struct FunctorCall; template struct FunctorCall, List, R, Function> { static void call(Function f, void **arg) { f((*reinterpret_cast::Type *>(arg[I+1]))...), ApplyReturnValue(arg[0]); } }; template struct FunctorCall, List, R, SlotRet (Obj::*)(SlotArgs...)> { static void call(SlotRet (Obj::*f)(SlotArgs...), Obj *o, void **arg) { (o->*f)((*reinterpret_cast::Type *>(arg[I+1]))...), ApplyReturnValue(arg[0]); } }; template struct FunctorCall, List, R, SlotRet (Obj::*)(SlotArgs...) const> { static void call(SlotRet (Obj::*f)(SlotArgs...) const, Obj *o, void **arg) { (o->*f)((*reinterpret_cast::Type *>(arg[I+1]))...), ApplyReturnValue(arg[0]); } }; template struct FunctionPointer { typedef Obj Object; typedef List Arguments; typedef Ret ReturnType; typedef Ret (Obj::*Function) (Args...); enum {ArgumentCount = sizeof...(Args)}; template static void call(Function f, Obj *o, void **arg) { FunctorCall::Value, SignalArgs, R, Function>::call(f, o, arg); } }; template struct FunctionPointer { typedef Obj Object; typedef List Arguments; typedef Ret ReturnType; typedef Ret (Obj::*Function) (Args...) const; enum {ArgumentCount = sizeof...(Args)}; template static void call(Function f, Obj *o, void **arg) { FunctorCall::Value, SignalArgs, R, Function>::call(f, o, arg); } }; template struct FunctionPointer { typedef List Arguments; typedef Ret ReturnType; typedef Ret (*Function) (Args...); enum {ArgumentCount = sizeof...(Args)}; template static void call(Function f, void *, void **arg) { FunctorCall::Value, SignalArgs, R, Function>::call(f, arg); } }; template struct Functor { template static void call(Function &f, void *, void **arg) { FunctorCall::Value, SignalArgs, R, Function>::call(f, arg); } }; #endif /* Logic that check if the arguments of the slot matches the argument of the signal. To be used like this: Q_STATIC_ASSERT(CheckCompatibleArguments::Arguments, FunctionPointer::Arguments>::value) */ template struct AreArgumentsCompatible { static int test(A2); static char test(...); static A1 dummy(); enum { value = sizeof(test(dummy())) == sizeof(int) }; }; template struct AreArgumentsCompatible { enum { value = false }; }; template struct AreArgumentsCompatible { enum { value = true }; }; // void as a return value template struct AreArgumentsCompatible { enum { value = true }; }; template struct AreArgumentsCompatible { enum { value = true }; }; template<> struct AreArgumentsCompatible { enum { value = true }; }; #ifndef Q_COMPILER_VARIADIC_TEMPLATES template struct CheckCompatibleArguments { enum { value = false }; }; template <> struct CheckCompatibleArguments { enum { value = true }; }; template struct CheckCompatibleArguments { enum { value = true }; }; template struct CheckCompatibleArguments, List > { enum { value = AreArgumentsCompatible::Type, typename RemoveConstRef::Type>::value && CheckCompatibleArguments::value }; }; #else template struct CheckCompatibleArguments { enum { value = false }; }; template <> struct CheckCompatibleArguments, List<>> { enum { value = true }; }; template struct CheckCompatibleArguments> { enum { value = true }; }; template struct CheckCompatibleArguments, List> { enum { value = AreArgumentsCompatible::Type, typename RemoveConstRef::Type>::value && CheckCompatibleArguments, List>::value }; }; #endif } QT_END_NAMESPACE #endif