moc: Support signals that return movable-only type
By adding std::move where it makes sense. This is not only good for move-only types, but for any type which can be moved as it saves copies of the return value in any case. [ChangeLog][moc] Move-only types are now supported as return types of signals and slots. Change-Id: Idc9453af993e7574a6bddd4a87210eddd3da48a9 Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
This commit is contained in:
parent
0d287500be
commit
16d1ddfc42
@ -90,14 +90,9 @@ namespace QtPrivate {
|
||||
explicit ApplyReturnValue(void *data_) : data(data_) {}
|
||||
};
|
||||
template<typename T, typename U>
|
||||
void operator,(const T &value, const ApplyReturnValue<U> &container) {
|
||||
if (container.data)
|
||||
*reinterpret_cast<U*>(container.data) = value;
|
||||
}
|
||||
template<typename T, typename U>
|
||||
void operator,(T &&value, const ApplyReturnValue<U> &container) {
|
||||
if (container.data)
|
||||
*reinterpret_cast<U*>(container.data) = value;
|
||||
*reinterpret_cast<U *>(container.data) = std::forward<T>(value);
|
||||
}
|
||||
template<typename T>
|
||||
void operator,(T, const ApplyReturnValue<void> &) {}
|
||||
|
@ -1193,7 +1193,7 @@ void Generator::generateStaticMetacall()
|
||||
}
|
||||
fprintf(out, ");");
|
||||
if (f.normalizedType != "void") {
|
||||
fprintf(out, "\n if (_a[0]) *reinterpret_cast< %s*>(_a[0]) = _r; } ",
|
||||
fprintf(out, "\n if (_a[0]) *reinterpret_cast< %s*>(_a[0]) = std::move(_r); } ",
|
||||
noRef(f.normalizedType).constData());
|
||||
isUsed_a = true;
|
||||
}
|
||||
@ -1506,11 +1506,7 @@ void Generator::generateSignal(FunctionDef *def,int index)
|
||||
fprintf(out, ")%s\n{\n", constQualifier);
|
||||
if (def->type.name.size() && def->normalizedType != "void") {
|
||||
QByteArray returnType = noRef(def->normalizedType);
|
||||
if (returnType.endsWith('*')) {
|
||||
fprintf(out, " %s _t0 = 0;\n", returnType.constData());
|
||||
} else {
|
||||
fprintf(out, " %s _t0 = %s();\n", returnType.constData(), returnType.constData());
|
||||
}
|
||||
fprintf(out, " %s _t0{};\n", returnType.constData());
|
||||
}
|
||||
|
||||
fprintf(out, " void *_a[] = { ");
|
||||
|
@ -5306,6 +5306,15 @@ void tst_QObject::connectNoDefaultConstructorArg()
|
||||
QVERIFY(connect(&ob, &NoDefaultContructorArguments::mySignal, &ob, &NoDefaultContructorArguments::mySlot, Qt::QueuedConnection));
|
||||
}
|
||||
|
||||
struct MoveOnly
|
||||
{
|
||||
int value;
|
||||
explicit MoveOnly(int v = 1) : value(v) {}
|
||||
MoveOnly(MoveOnly &&o) : value(o.value) { o.value = -1; }
|
||||
MoveOnly &operator=(MoveOnly &&o) { value = o.value; o.value = -1; return *this; }
|
||||
Q_DISABLE_COPY(MoveOnly);
|
||||
};
|
||||
|
||||
class ReturnValue : public QObject {
|
||||
friend class tst_QObject;
|
||||
Q_OBJECT
|
||||
@ -5315,6 +5324,7 @@ signals:
|
||||
int returnInt(int);
|
||||
void returnVoid(int);
|
||||
CustomType returnCustomType(int);
|
||||
MoveOnly returnMoveOnly(int);
|
||||
|
||||
QObject *returnPointer();
|
||||
public slots:
|
||||
@ -5327,6 +5337,7 @@ public slots:
|
||||
QString returnHello() { return QStringLiteral("hello"); }
|
||||
QObject *returnThisSlot1() { return this; }
|
||||
ReturnValue *returnThisSlot2() { return this; }
|
||||
MoveOnly returnMoveOnlySlot(int i) { return MoveOnly(i); }
|
||||
public:
|
||||
struct VariantFunctor {
|
||||
QVariant operator()(int i) { return i; }
|
||||
@ -5343,6 +5354,9 @@ public:
|
||||
struct VoidFunctor {
|
||||
void operator()(int) {}
|
||||
};
|
||||
struct MoveOnlyFunctor {
|
||||
MoveOnly operator()(int i) { return MoveOnly(i); }
|
||||
};
|
||||
};
|
||||
|
||||
QString someFunctionReturningString(int i) {
|
||||
@ -5380,6 +5394,7 @@ void tst_QObject::returnValue()
|
||||
emit r.returnVoid(45);
|
||||
QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
|
||||
QCOMPARE((emit r.returnPointer()), static_cast<QObject *>(0));
|
||||
QCOMPARE((emit r.returnMoveOnly(666)).value, MoveOnly().value);
|
||||
}
|
||||
{ // connected to a slot returning the same type
|
||||
CheckInstanceCount checker;
|
||||
@ -5394,6 +5409,8 @@ void tst_QObject::returnValue()
|
||||
QCOMPARE((emit r.returnCustomType(45)).value(), CustomType(45).value());
|
||||
QVERIFY(connect(&r, &ReturnValue::returnPointer, &receiver, &ReturnValue::returnThisSlot1, type));
|
||||
QCOMPARE((emit r.returnPointer()), static_cast<QObject *>(&receiver));
|
||||
QVERIFY(connect(&r, &ReturnValue::returnMoveOnly, &receiver, &ReturnValue::returnMoveOnlySlot, type));
|
||||
QCOMPARE((emit r.returnMoveOnly(666)).value, 666);
|
||||
}
|
||||
if (!isBlockingQueued) { // connected to simple functions or functor
|
||||
CheckInstanceCount checker;
|
||||
@ -5412,6 +5429,10 @@ void tst_QObject::returnValue()
|
||||
ReturnValue::IntFunctor intFunctor;
|
||||
QVERIFY(connect(&r, &ReturnValue::returnInt, intFunctor));
|
||||
QCOMPARE(emit r.returnInt(45), int(45));
|
||||
|
||||
ReturnValue::MoveOnlyFunctor moveOnlyFunctor;
|
||||
QVERIFY(connect(&r, &ReturnValue::returnMoveOnly, moveOnlyFunctor));
|
||||
QCOMPARE((emit r.returnMoveOnly(666)).value, 666);
|
||||
}
|
||||
{ // connected to a slot with different type
|
||||
CheckInstanceCount checker;
|
||||
@ -5450,6 +5471,8 @@ void tst_QObject::returnValue()
|
||||
QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
|
||||
QVERIFY(connect(&r, &ReturnValue::returnPointer, &receiver, &ReturnValue::returnVoidSlot, type));
|
||||
QCOMPARE((emit r.returnPointer()), static_cast<QObject *>(0));
|
||||
QVERIFY(connect(&r, &ReturnValue::returnMoveOnly, &receiver, &ReturnValue::returnVoidSlot, type));
|
||||
QCOMPARE((emit r.returnMoveOnly(666)).value, MoveOnly().value);
|
||||
}
|
||||
if (!isBlockingQueued) {
|
||||
// queued connection should not forward the return value
|
||||
@ -5465,6 +5488,8 @@ void tst_QObject::returnValue()
|
||||
QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
|
||||
QVERIFY(connect(&r, &ReturnValue::returnPointer, &receiver, &ReturnValue::returnThisSlot1, Qt::QueuedConnection));
|
||||
QCOMPARE((emit r.returnPointer()), static_cast<QObject *>(0));
|
||||
QVERIFY(connect(&r, &ReturnValue::returnMoveOnly, &receiver, &ReturnValue::returnMoveOnlySlot, Qt::QueuedConnection));
|
||||
QCOMPARE((emit r.returnMoveOnly(666)).value, MoveOnly().value);
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
@ -5548,6 +5573,8 @@ void tst_QObject::returnValue2()
|
||||
QCOMPARE(emit r.returnInt(45), int(45));
|
||||
QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnCustomTypeSlot(int)), type));
|
||||
QCOMPARE((emit r.returnCustomType(45)).value(), CustomType(45).value());
|
||||
QVERIFY(connect(&r, SIGNAL(returnMoveOnly(int)), &receiver, SLOT(returnMoveOnlySlot(int)), type));
|
||||
QCOMPARE((emit r.returnMoveOnly(45)).value, 45);
|
||||
}
|
||||
{ // connected to a slot returning void
|
||||
CheckInstanceCount checker;
|
||||
@ -5560,6 +5587,8 @@ void tst_QObject::returnValue2()
|
||||
QCOMPARE(emit r.returnInt(45), int());
|
||||
QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnVoidSlot()), type));
|
||||
QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
|
||||
QVERIFY(connect(&r, SIGNAL(returnMoveOnly(int)), &receiver, SLOT(returnVoidSlot()), type));
|
||||
QCOMPARE((emit r.returnMoveOnly(45)).value, MoveOnly().value);
|
||||
}
|
||||
if (!isBlockingQueued) {
|
||||
// queued connection should not forward the return value
|
||||
@ -5573,6 +5602,9 @@ void tst_QObject::returnValue2()
|
||||
QCOMPARE(emit r.returnInt(45), int());
|
||||
QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnCustomTypeSlot(int)), Qt::QueuedConnection));
|
||||
QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
|
||||
QVERIFY(connect(&r, SIGNAL(returnMoveOnly(int)), &receiver, SLOT(returnMoveOnlySlot(int)), Qt::QueuedConnection));
|
||||
QCOMPARE((emit r.returnMoveOnly(45)).value, MoveOnly().value);
|
||||
|
||||
QCoreApplication::processEvents();
|
||||
|
||||
//Queued conneciton with different return type should be safe
|
||||
|
Loading…
Reference in New Issue
Block a user