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 <thiago.macieira@intel.com>
bb10
Olivier Goffart 2017-04-22 12:40:01 +02:00 committed by Olivier Goffart (Woboq GmbH)
parent 779c00d454
commit a6c091c2d1
3 changed files with 45 additions and 3 deletions

View File

@ -304,7 +304,7 @@ public:
static inline typename std::enable_if<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::type
connect(const typename QtPrivate::FunctionPointer<Func1>::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<void **>(&signal), context, Q_NULLPTR,
new QtPrivate::QFunctorSlotObject<Func2, SlotArgumentCount,
typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value,
typename SignalType::ReturnType>(slot),
typename SignalType::ReturnType>(std::move(slot)),
type, types, &SignalType::Object::staticMetaObject);
}
#endif //Q_QDOC

View File

@ -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

View File

@ -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