corelib: invokeMethod: Allow non copyable functors to be used

[ChangeLog][QtCore][QMetaObject] Non-copyable lambdas can now be used
with invokeMethod(). For consistency reasons, the functor object is
now always moved.

Fixes: QTBUG-69683
Change-Id: I66ff5e21d6d1926f0f7c5f8c304bed1a90b69917
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
Hugo Beauzée-Luyssen 2019-04-03 18:30:43 +02:00
parent ab2c1e20fa
commit 2a815855a9
3 changed files with 21 additions and 2 deletions

View File

@ -523,7 +523,7 @@ struct Q_CORE_EXPORT QMetaObject
Qt::ConnectionType type = Qt::AutoConnection, decltype(function()) *ret = nullptr)
{
return invokeMethodImpl(context,
new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(function),
new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)),
type,
ret);
}
@ -535,7 +535,7 @@ struct Q_CORE_EXPORT QMetaObject
invokeMethod(QObject *context, Func function, typename std::result_of<Func()>::type *ret)
{
return invokeMethodImpl(context,
new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(function),
new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)),
Qt::AutoConnection,
ret);
}

View File

@ -1,4 +1,5 @@
CONFIG += testcase
qtConfig(c++14): CONFIG += c++14
TARGET = tst_qmetaobject
QT = core-private testlib
SOURCES = tst_qmetaobject.cpp

View File

@ -815,6 +815,15 @@ void tst_QMetaObject::invokePointer()
QCOMPARE(obj.slotResult, QString("sl1:bubu"));
}
QCOMPARE(countedStructObjectsCount, 0);
#ifdef __cpp_init_captures
{
CountedStruct str;
std::unique_ptr<int> ptr( new int );
QVERIFY(QMetaObject::invokeMethod(&obj, [str, &t1, &obj, p = std::move(ptr)]() { obj.sl1(t1); }));
QCOMPARE(obj.slotResult, QString("sl1:1"));
}
QCOMPARE(countedStructObjectsCount, 0);
#endif
}
void tst_QMetaObject::invokeQueuedMetaMember()
@ -1120,6 +1129,15 @@ void tst_QMetaObject::invokeBlockingQueuedPointer()
QCOMPARE(exp, QString("yessir"));
QCOMPARE(obj.slotResult, QString("sl1:bubu"));
}
#ifdef __cpp_init_captures
{
std::unique_ptr<int> ptr(new int);
QVERIFY(QMetaObject::invokeMethod(&obj,
[&obj, p = std::move(ptr)]() { return obj.sl1("hehe"); },
Qt::BlockingQueuedConnection));
QCOMPARE(obj.slotResult, QString("sl1:hehe"));
}
#endif
QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.moveToThread(QThread::currentThread());}, Qt::BlockingQueuedConnection));
t.quit();
QVERIFY(t.wait());