From a6c091c2d18f6e7f849da7dfa3bd1971017fca73 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Sat, 22 Apr 2017 12:40:01 +0200 Subject: Support move-only function objects in QObject::connect [ChangeLog][QtCore][QObject] Added connect() support for move-only function objects. Task-number: QTBUG-60339 Change-Id: Iae5e48432bb64517b0607b0c2ba23931957f432e Reviewed-by: Thiago Macieira --- src/corelib/kernel/qobject.h | 4 +-- src/corelib/kernel/qobjectdefs_impl.h | 2 +- tests/auto/corelib/kernel/qobject/tst_qobject.cpp | 42 +++++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 6941c55896..2e66daa914 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -304,7 +304,7 @@ public: static inline typename std::enable_if::ArgumentCount == -1, QMetaObject::Connection>::type connect(const typename QtPrivate::FunctionPointer::Object *sender, Func1 signal, Func2 slot) { - return connect(sender, signal, sender, slot, Qt::DirectConnection); + return connect(sender, signal, sender, std::move(slot), Qt::DirectConnection); } //connect to a functor, with a "context" object defining in which event loop is going to be executed @@ -334,7 +334,7 @@ public: return connectImpl(sender, reinterpret_cast(&signal), context, Q_NULLPTR, new QtPrivate::QFunctorSlotObject::Value, - typename SignalType::ReturnType>(slot), + typename SignalType::ReturnType>(std::move(slot)), type, types, &SignalType::Object::staticMetaObject); } #endif //Q_QDOC diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index ef68050529..876742ab6c 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -430,7 +430,7 @@ namespace QtPrivate { } } public: - explicit QFunctorSlotObject(const Func &f) : QSlotObjectBase(&impl), function(f) {} + explicit QFunctorSlotObject(Func f) : QSlotObjectBase(&impl), function(std::move(f)) {} }; // typedefs for readability for when there are no parameters diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index db6bdf0809..89d6be6c7a 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 connectFunctorWithContext(); void connectFunctorWithContextUnique(); void connectFunctorDeadlock(); + void connectFunctorMoveOnly(); void connectStaticSlotWithObject(); void disconnectDoesNotLeakFunctor(); void contextDoesNotLeakFunctor(); @@ -6237,6 +6238,47 @@ void tst_QObject::connectFunctorDeadlock() sender.emitSignal1(); } +void tst_QObject::connectFunctorMoveOnly() +{ + struct MoveOnlyFunctor { + Q_DISABLE_COPY(MoveOnlyFunctor) + MoveOnlyFunctor(int *status) : status(status) {} + MoveOnlyFunctor(MoveOnlyFunctor &&o) : status(o.status) { o.status = nullptr; }; + void operator()(int i) { *status = i; } + void operator()() { *status = -8; } + int *status; + }; + + int status = 1; + SenderObject obj; + QEventLoop e; + + connect(&obj, &SenderObject::signal1, MoveOnlyFunctor(&status)); + QCOMPARE(status, 1); + obj.signal1(); + QCOMPARE(status, -8); + + connect(&obj, &SenderObject::signal7, MoveOnlyFunctor(&status)); + QCOMPARE(status, -8); + obj.signal7(7888, "Hello"); + QCOMPARE(status, 7888); + + // With a context + status = 1; + connect(&obj, &SenderObject::signal2, this, MoveOnlyFunctor(&status)); + QCOMPARE(status, 1); + obj.signal2(); + QCOMPARE(status, -8); + + // QueuedConnection + status = 1; + connect(&obj, &SenderObject::signal3, this, MoveOnlyFunctor(&status), Qt::QueuedConnection); + obj.signal3(); + QCOMPARE(status, 1); + QCoreApplication::processEvents(); + QCOMPARE(status, -8); +} + static int s_static_slot_checker = 1; class StaticSlotChecker : public QObject -- cgit v1.2.3