From 1ed8c80ee3239264c9054250a0a4718a2241080b Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Mon, 1 May 2023 10:48:47 +0200 Subject: [PATCH] Revert "Support move-only functors in invokeMethod and async APIs" This reverts commit 9958edba41ac49097a54e0872c3c4934d2dd81f9, which incorrectly tested a move-only functor without actually moving the functor. Change-Id: I3707f9f8e5055102f7edfb3e1cb9750978356dd7 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qobjectdefs.h | 24 +++++++++---------- src/corelib/kernel/qobjectdefs_impl.h | 8 +++---- .../corelib/kernel/qobject/tst_qobject.cpp | 11 +++++---- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 982af5a18a..28b4e368fe 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -417,11 +417,11 @@ struct Q_CORE_EXPORT QMetaObject && !std::is_convertible::value && QtPrivate::FunctionPointer::ArgumentCount == 0, bool>::type invokeMethod(typename QtPrivate::FunctionPointer::Object *object, - Func &&function, + Func function, Qt::ConnectionType type = Qt::AutoConnection, typename QtPrivate::FunctionPointer::ReturnType *ret = nullptr) { - return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs(std::forward(function)), type, ret); + return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs(function), type, ret); } template @@ -429,10 +429,10 @@ struct Q_CORE_EXPORT QMetaObject && !std::is_convertible::value && QtPrivate::FunctionPointer::ArgumentCount == 0, bool>::type invokeMethod(typename QtPrivate::FunctionPointer::Object *object, - Func &&function, + Func function, typename QtPrivate::FunctionPointer::ReturnType *ret) { - return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs(std::forward(function)), Qt::AutoConnection, ret); + return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs(function), Qt::AutoConnection, ret); } // invokeMethod() for function pointer (not member) @@ -440,21 +440,21 @@ struct Q_CORE_EXPORT QMetaObject static typename std::enable_if::IsPointerToMemberFunction && !std::is_convertible::value && QtPrivate::FunctionPointer::ArgumentCount == 0, bool>::type - invokeMethod(QObject *context, Func &&function, + invokeMethod(QObject *context, Func function, Qt::ConnectionType type = Qt::AutoConnection, typename QtPrivate::FunctionPointer::ReturnType *ret = nullptr) { - return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn(std::forward(function)), type, ret); + return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn(function), type, ret); } template static typename std::enable_if::IsPointerToMemberFunction && !std::is_convertible::value && QtPrivate::FunctionPointer::ArgumentCount == 0, bool>::type - invokeMethod(QObject *context, Func &&function, + invokeMethod(QObject *context, Func function, typename QtPrivate::FunctionPointer::ReturnType *ret) { - return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn(std::forward(function)), Qt::AutoConnection, ret); + return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn(function), Qt::AutoConnection, ret); } // invokeMethod() for Functor @@ -462,11 +462,11 @@ struct Q_CORE_EXPORT QMetaObject static typename std::enable_if::IsPointerToMemberFunction && QtPrivate::FunctionPointer::ArgumentCount == -1 && !std::is_convertible::value, bool>::type - invokeMethod(QObject *context, Func &&function, + invokeMethod(QObject *context, Func function, Qt::ConnectionType type = Qt::AutoConnection, decltype(function()) *ret = nullptr) { return invokeMethodImpl(context, - new QtPrivate::QFunctorSlotObjectWithNoArgs(std::forward(function)), + new QtPrivate::QFunctorSlotObjectWithNoArgs(std::move(function)), type, ret); } @@ -475,10 +475,10 @@ struct Q_CORE_EXPORT QMetaObject static typename std::enable_if::IsPointerToMemberFunction && QtPrivate::FunctionPointer::ArgumentCount == -1 && !std::is_convertible::value, bool>::type - invokeMethod(QObject *context, Func &&function, decltype(function()) *ret) + invokeMethod(QObject *context, Func function, decltype(function()) *ret) { return invokeMethodImpl(context, - new QtPrivate::QFunctorSlotObjectWithNoArgs(std::forward(function)), + new QtPrivate::QFunctorSlotObjectWithNoArgs(std::move(function)), Qt::AutoConnection, ret); } diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index 721193fe91..a950cf9d4e 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -439,7 +439,7 @@ namespace QtPrivate { } } public: - explicit QFunctorSlotObject(Func &&f) : QSlotObjectBase(&impl), function(std::forward(f)) {} + explicit QFunctorSlotObject(Func f) : QSlotObjectBase(&impl), function(std::move(f)) {} }; // typedefs for readability for when there are no parameters @@ -492,7 +492,7 @@ namespace QtPrivate { template static constexpr std::enable_if_t() >= 0, QtPrivate::QSlotObjectBase *> - makeSlotObject(Functor &&func) + makeSlotObject(Functor func) { using ExpectedSignature = QtPrivate::FunctionPointer; using ExpectedArguments = typename ExpectedSignature::Arguments; @@ -503,13 +503,13 @@ namespace QtPrivate { if constexpr (QtPrivate::FunctionPointer::IsPointerToMemberFunction) { using ActualArguments = typename ActualSignature::Arguments; - return new QtPrivate::QSlotObject(std::forward(func)); + return new QtPrivate::QSlotObject(func); } else { constexpr int MatchingArgumentCount = QtPrivate::countMatchingArguments(); using ActualArguments = typename QtPrivate::List_Left::Value; return new QtPrivate::QFunctorSlotObject(std::forward(func)); + ActualArguments, void>(std::move(func)); } } diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 76ceb84271..82d46a3127 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -8428,7 +8428,6 @@ void tst_QObject::asyncCallbackHelper() static_assert(compiles(&AsyncCaller::callback0)); static_assert(compiles(&AsyncCaller::staticCallback0)); static_assert(compiles(lambda0)); - static_assert(compiles(moveOnlyLambda)); static_assert(compiles(freeFunction0)); static_assert(compiles(functor0)); @@ -8443,7 +8442,6 @@ void tst_QObject::asyncCallbackHelper() static_assert(compiles(&AsyncCaller::callback1)); static_assert(compiles(&AsyncCaller::staticCallback1)); static_assert(compiles(lambda1)); - static_assert(compiles(moveOnlyLambda)); static_assert(compiles(constLambda)); static_assert(compiles(freeFunction1)); static_assert(compiles(functor1)); @@ -8457,6 +8455,11 @@ void tst_QObject::asyncCallbackHelper() static_assert(!compiles(freeFunction1)); static_assert(!compiles(functor1)); + // move-only functor - should work, but doesn't because QFunctorSlotObject requires + // the functor to be of a copyable type! + static_assert(!compiles(moveOnlyLambda)); + static_assert(!compiles(moveOnlyLambda)); + // wrong parameter type static_assert(!compiles(&AsyncCaller::callbackInt)); @@ -8474,7 +8477,7 @@ void tst_QObject::asyncCallbackHelper() QVERIFY(caller.callMe0(&caller, &AsyncCaller::staticCallback0)); QVERIFY(caller.callMe0(&caller, lambda0)); QVERIFY(caller.callMe0(&caller, freeFunction0)); - QVERIFY(caller.callMe0(&caller, moveOnlyLambda)); +// QVERIFY(caller.callMe0(&caller, moveOnlyLambda)); QVERIFY(caller.callMe1(&caller, &AsyncCaller::callback1)); QVERIFY(caller.callMe1(&caller, &AsyncCaller::staticCallback1)); @@ -8486,7 +8489,7 @@ void tst_QObject::asyncCallbackHelper() QVERIFY(caller.callMe0(&AsyncCaller::staticCallback0)); QVERIFY(caller.callMe0(lambda0)); QVERIFY(caller.callMe0(freeFunction0)); - QVERIFY(caller.callMe0(moveOnlyLambda)); +// QVERIFY(caller.callMe0(moveOnlyLambda)); QVERIFY(caller.callMe1(&AsyncCaller::staticCallback1)); QVERIFY(caller.callMe1(lambda1));