diff options
-rw-r--r-- | src/corelib/kernel/qobject.h | 20 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qobject/tst_qobject.cpp | 36 |
2 files changed, 55 insertions, 1 deletions
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 689946b6c4..e9316c98f0 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -279,10 +279,28 @@ public: static inline typename QtPrivate::QEnableIf<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::Type connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot) { +#ifndef Q_COMPILER_DECLTYPE //Workaround the lack of decltype using another function as indirection + return connect_functor(sender, signal, slot, &Func2::operator()); } + template <typename Func1, typename Func2, typename Func2Operator> + static inline QMetaObject::Connection connect_functor(const QObject *sender, Func1 signal, Func2 slot, Func2Operator) { + typedef QtPrivate::FunctionPointer<Func2Operator> SlotType ; +#else + + typedef QtPrivate::FunctionPointer<decltype(&Func2::operator())> SlotType ; +#endif typedef QtPrivate::FunctionPointer<Func1> SignalType; + Q_STATIC_ASSERT_X(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount), + "The slot requires more arguments than the signal provides."); + Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value), + "Signal and slot arguments are not compatible."); + Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value), + "Return type of the slot is not compatible with the return type of the signal."); + return connectImpl(sender, reinterpret_cast<void **>(&signal), sender, 0, - new QtPrivate::QFunctorSlotObject<Func2, SignalType::ArgumentCount, typename SignalType::Arguments, typename SignalType::ReturnType>(slot), + new QtPrivate::QFunctorSlotObject<Func2, SlotType::ArgumentCount, + typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value, + typename SignalType::ReturnType>(slot), Qt::DirectConnection, 0, &SignalType::Object::staticMetaObject); } #endif //Q_QDOC diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index f48f86cceb..c340d00361 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -140,6 +140,7 @@ private slots: void returnValue2_data(); void returnValue2(); void connectVirtualSlots(); + void connectFunctorArgDifference(); }; class SenderObject : public QObject @@ -5484,5 +5485,40 @@ void tst_QObject::connectVirtualSlots() */ } +struct SlotFunctor +{ + void operator()() {} +}; + +struct SlotFunctorString +{ + void operator()(const QString &) {} +}; + +void tst_QObject::connectFunctorArgDifference() +{ + QTimer timer; + // Compile-time tests that the connection is successful. + connect(&timer, &QTimer::timeout, SlotFunctor()); + connect(&timer, &QTimer::objectNameChanged, SlotFunctorString()); + connect(qApp, &QCoreApplication::aboutToQuit, SlotFunctor()); + + connect(&timer, &QTimer::objectNameChanged, SlotFunctor()); + QStringListModel model; + connect(&model, &QStringListModel::rowsInserted, SlotFunctor()); + +#if defined(Q_COMPILER_LAMBDA) + connect(&timer, &QTimer::timeout, [=](){}); + connect(&timer, &QTimer::objectNameChanged, [=](const QString &){}); + connect(qApp, &QCoreApplication::aboutToQuit, [=](){}); + + connect(&timer, &QTimer::objectNameChanged, [=](){}); + connect(&model, &QStringListModel::rowsInserted, [=](){}); + connect(&model, &QStringListModel::rowsInserted, [=](const QModelIndex &){}); +#endif + + QVERIFY(true); +} + QTEST_MAIN(tst_QObject) #include "tst_qobject.moc" |