From cf1eb700702aec473db0a4794b1a6549ee10bb62 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 12 Jan 2012 20:46:15 +0100 Subject: [PATCH] Fix connection to const slots (or from const signals) Pointer to const member function have a different signature, and hence need their own traits code. Change-Id: Ie4b2434a412f412444fb07ef1388a37cab105ecd Reviewed-by: Stephen Kelly --- src/corelib/kernel/qobjectdefs_impl.h | 121 ++++++++++++++++++++++ tests/auto/corelib/kernel/qobject/tst_qobject.cpp | 13 +++ 2 files changed, 134 insertions(+) diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index 2c85b92..55a8904 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -126,6 +126,7 @@ namespace QtPrivate { */ #ifndef Q_COMPILER_VARIADIC_TEMPLATES template struct FunctionPointer { enum {ArgumentCount = -1}; }; + //Pointers to member functions template struct FunctionPointer { typedef Obj Object; @@ -225,6 +226,107 @@ namespace QtPrivate { } }; + //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; @@ -315,6 +417,7 @@ namespace QtPrivate { } }; + //Functors template struct Functor; template struct Functor { @@ -401,6 +504,12 @@ namespace QtPrivate { (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 { @@ -414,6 +523,18 @@ namespace QtPrivate { 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 { diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 0cabc46..f48f86c 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -4737,6 +4737,9 @@ class LotsOfSignalsAndSlots: public QObject #endif*/ void slot_vPFvvE(fptr) {} + void const_slot_v() const {}; + void const_slot_vi(int) const {}; + static void static_slot_v() {} static void static_slot_vi(int) {} static void static_slot_vii(int, int) {} @@ -4768,6 +4771,9 @@ class LotsOfSignalsAndSlots: public QObject #endif*/ void signal_vPFvvE(fptr); + void const_signal_v() const; + void const_signal_vi(int) const; + void signal(short&, short, long long, short); void otherSignal(const char *); }; @@ -4879,6 +4885,13 @@ void tst_QObject::connectCxx0xTypeMatching() QObject::connect(&obj, &Foo::signal_vPFvvE, &Foo::static_slot_v); QObject::connect(&obj, &Foo::signal_vPFvvE, &Foo::static_slot_i); QObject::connect(&obj, &Foo::signal_vPFvvE, &Foo::static_slot_vPFvvE); + + QVERIFY(QObject::connect(&obj, &Foo::const_signal_v, &obj, &Foo::const_slot_v)); + QVERIFY(QObject::connect(&obj, &Foo::const_signal_vi, &obj, &Foo::const_slot_v)); + QVERIFY(QObject::connect(&obj, &Foo::const_signal_vi, &obj, &Foo::slot_vi)); + QVERIFY(QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::const_slot_vi)); + QVERIFY(QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::const_slot_v)); + QVERIFY(true); //compilation only test } -- 2.7.4