diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 95322a9dbd6..9cb025d20d4 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -192,121 +192,55 @@ public: template static QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection); #else - //Connect a signal to a pointer to qobject member function + //connect with context template - static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer::Object *sender, Func1 signal, - const typename QtPrivate::FunctionPointer::Object *receiver, Func2 slot, - Qt::ConnectionType type = Qt::AutoConnection) - { - typedef QtPrivate::FunctionPointer SignalType; - typedef QtPrivate::FunctionPointer SlotType; - - static_assert(QtPrivate::HasQ_OBJECT_Macro::Value, - "No Q_OBJECT in the class with the signal"); - - //compilation error if the arguments does not match. - static_assert(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount), - "The slot requires more arguments than the signal provides."); - static_assert((QtPrivate::CheckCompatibleArguments::value), - "Signal and slot arguments are not compatible."); - static_assert((QtPrivate::AreArgumentsCompatible::value), - "Return type of the slot is not compatible with the return type of the signal."); - - const int *types = nullptr; - if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection) - types = QtPrivate::ConnectionTypes::types(); - - return connectImpl(sender, reinterpret_cast(&signal), - receiver, reinterpret_cast(&slot), - new QtPrivate::QSlotObject::Value, - typename SignalType::ReturnType>(slot), - type, types, &SignalType::Object::staticMetaObject); - } - - //connect to a function pointer (not a member) - template - static inline typename std::enable_if::ArgumentCount) >= 0, QMetaObject::Connection>::type - connect(const typename QtPrivate::FunctionPointer::Object *sender, Func1 signal, Func2 &&slot) - { - return connect(sender, signal, sender, std::forward(slot), Qt::DirectConnection); - } - - //connect to a function pointer (not a member) - template - static inline typename std::enable_if>::ArgumentCount) >= 0 && - !QtPrivate::FunctionPointer>::IsPointerToMemberFunction, QMetaObject::Connection>::type - connect(const typename QtPrivate::FunctionPointer::Object *sender, Func1 signal, const QObject *context, Func2 &&slot, - Qt::ConnectionType type = Qt::AutoConnection) + static inline QMetaObject::Connection + connect(const typename QtPrivate::FunctionPointer::Object *sender, Func1 signal, + const typename QtPrivate::ContextTypeForFunctor::ContextType *context, Func2 &&slot, + Qt::ConnectionType type = Qt::AutoConnection) { typedef QtPrivate::FunctionPointer SignalType; typedef QtPrivate::FunctionPointer> SlotType; + if constexpr (SlotType::ArgumentCount != -1) { + static_assert((QtPrivate::AreArgumentsCompatible::value), + "Return type of the slot is not compatible with the return type of the signal."); + } else { + constexpr int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount, typename SignalType::Arguments>::Value; + constexpr int SlotArgumentCount = (FunctorArgumentCount >= 0) ? FunctorArgumentCount : 0; + typedef typename QtPrivate::FunctorReturnType, typename QtPrivate::List_Left::Value>::Value SlotReturnType; + + static_assert((QtPrivate::AreArgumentsCompatible::value), + "Return type of the slot is not compatible with the return type of the signal."); + } + static_assert(QtPrivate::HasQ_OBJECT_Macro::Value, "No Q_OBJECT in the class with the signal"); //compilation error if the arguments does not match. static_assert(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount), "The slot requires more arguments than the signal provides."); - static_assert((QtPrivate::CheckCompatibleArguments::value), - "Signal and slot arguments are not compatible."); - static_assert((QtPrivate::AreArgumentsCompatible::value), - "Return type of the slot is not compatible with the return type of the signal."); const int *types = nullptr; if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection) types = QtPrivate::ConnectionTypes::types(); - return connectImpl(sender, reinterpret_cast(&signal), context, nullptr, - new QtPrivate::QFunctorSlotObject::Value, - typename SignalType::ReturnType>(std::forward(slot)), + void **pSlot = nullptr; + if constexpr (std::is_member_function_pointer_v>) + pSlot = const_cast(reinterpret_cast(&slot)); + + return connectImpl(sender, reinterpret_cast(&signal), context, pSlot, + QtPrivate::makeSlotObject(std::forward(slot)), type, types, &SignalType::Object::staticMetaObject); } - //connect to a functor + //connect without context template - static inline typename std::enable_if< - QtPrivate::FunctionPointer::ArgumentCount == -1 && - !std::is_convertible_v, // don't match old-style connect - QMetaObject::Connection>::type - connect(const typename QtPrivate::FunctionPointer::Object *sender, Func1 signal, Func2 &&slot) + static inline QMetaObject::Connection + connect(const typename QtPrivate::FunctionPointer::Object *sender, Func1 signal, Func2 &&slot) { return connect(sender, signal, sender, std::forward(slot), Qt::DirectConnection); } - - //connect to a functor, with a "context" object defining in which event loop is going to be executed - template - static inline typename std::enable_if< - QtPrivate::FunctionPointer::ArgumentCount == -1 && - !std::is_convertible_v, // don't match old-style connect - QMetaObject::Connection>::type - connect(const typename QtPrivate::FunctionPointer::Object *sender, Func1 signal, const QObject *context, Func2 slot, - Qt::ConnectionType type = Qt::AutoConnection) - { - typedef QtPrivate::FunctionPointer SignalType; - const int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount::Value; - - static_assert((FunctorArgumentCount >= 0), - "Signal and slot arguments are not compatible."); - const int SlotArgumentCount = (FunctorArgumentCount >= 0) ? FunctorArgumentCount : 0; - typedef typename QtPrivate::FunctorReturnType::Value>::Value SlotReturnType; - - static_assert((QtPrivate::AreArgumentsCompatible::value), - "Return type of the slot is not compatible with the return type of the signal."); - - static_assert(QtPrivate::HasQ_OBJECT_Macro::Value, - "No Q_OBJECT in the class with the signal"); - - const int *types = nullptr; - if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection) - types = QtPrivate::ConnectionTypes::types(); - - return connectImpl(sender, reinterpret_cast(&signal), context, nullptr, - new QtPrivate::QFunctorSlotObject::Value, - typename SignalType::ReturnType>(std::move(slot)), - type, types, &SignalType::Object::staticMetaObject); - } #endif //Q_QDOC static bool disconnect(const QObject *sender, const char *signal, diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index e8e33f2c1cc..8d1564c4be8 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -401,35 +401,14 @@ namespace QtPrivate { Q_DISABLE_COPY_MOVE(QSlotObjectBase) }; - // implementation of QSlotObjectBase for which the slot is a pointer to member function of a QObject - // Args and R are the List of arguments and the return type of the signal to which the slot is connected. - template class QSlotObject : public QSlotObjectBase - { - typedef QtPrivate::FunctionPointer FuncType; - Func function; - static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret) - { - switch (which) { - case Destroy: - delete static_cast(this_); - break; - case Call: - FuncType::template call(static_cast(this_)->function, static_cast(r), a); - break; - case Compare: - *ret = *reinterpret_cast(a) == static_cast(this_)->function; - break; - case NumOperations: ; - } - } - public: - explicit QSlotObject(Func f) : QSlotObjectBase(&impl), function(f) {} - }; // implementation of QSlotObjectBase for which the slot is a functor (or lambda) // Args and R are the List of arguments and the return type of the signal to which the slot is connected. template class QFunctorSlotObject : public QSlotObjectBase { - using FuncType = QtPrivate::Functor; + using FuncType = std::conditional_t>, + QtPrivate::FunctionPointer>, + QtPrivate::Functor + >; Func function; static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret) { @@ -438,9 +417,18 @@ namespace QtPrivate { delete static_cast(this_); break; case Call: - FuncType::template call(static_cast(this_)->function, r, a); + if constexpr (std::is_member_function_pointer_v>) + FuncType::template call(static_cast(this_)->function, static_cast(r), a); + else + FuncType::template call(static_cast(this_)->function, r, a); break; - case Compare: // not implemented + case Compare: + if constexpr (std::is_member_function_pointer_v>) { + *ret = *reinterpret_cast *>(a) == static_cast(this_)->function; + break; + } + // not implemented otherwise + Q_FALLTHROUGH(); case NumOperations: Q_UNUSED(ret); } @@ -451,7 +439,7 @@ namespace QtPrivate { // typedefs for readability for when there are no parameters template - using QSlotObjectWithNoArgs = QSlotObject, typename QtPrivate::FunctionPointer::ReturnType>; @@ -506,19 +494,15 @@ namespace QtPrivate { using ExpectedSignature = QtPrivate::FunctionPointer; using ExpectedReturnType = typename ExpectedSignature::ReturnType; using ExpectedArguments = typename ExpectedSignature::Arguments; + using ActualSignature = QtPrivate::FunctionPointer; + constexpr int MatchingArgumentCount = QtPrivate::countMatchingArguments(); + using ActualArguments = typename QtPrivate::List_Left::Value; static_assert(int(ActualSignature::ArgumentCount) <= int(ExpectedSignature::ArgumentCount), "Functor requires more arguments than what can be provided."); - if constexpr (QtPrivate::FunctionPointer::IsPointerToMemberFunction) { - using ActualArguments = typename ActualSignature::Arguments; - return new QtPrivate::QSlotObject(std::move(func)); - } else { - constexpr int MatchingArgumentCount = QtPrivate::countMatchingArguments(); - using ActualArguments = typename QtPrivate::List_Left::Value; - return new QtPrivate::QFunctorSlotObject(std::move(func)); - } + return new QtPrivate::QFunctorSlotObject(std::forward(func)); } template