diff options
author | Arno Rehn <a.rehn@menlosystems.com> | 2022-09-23 16:31:47 +0200 |
---|---|---|
committer | Arno Rehn <a.rehn@menlosystems.com> | 2022-09-27 20:59:21 +0200 |
commit | 7a7051b58f78a85cc55aece7b8691583c33ac47e (patch) | |
tree | e5c8bef3bac3a8e6bbd60818fc7e2af6e01ba96e /tests/auto/corelib/kernel | |
parent | 38f8d531a26720cbf5574f06481c58ef4dad7e4b (diff) |
QMetaType: Support custom unary converters with optional<To> return type
To indicate success of a conversion, the public API has previously only
supported registering member functions of the form To (From::*)(bool *).
When adding custom converters for types that cannot be modified, this is
usually not a possibility.
As an alternative, this patch adds support for std::optional in the
UnaryFunction overload of QMetaType::registerConverter. If the returned
optional has no value, the conversion is considered failed.
Task-number: QTBUG-92902
Change-Id: Ibac52d2cb9b5a2457081b4bebb0def1f03e3c55d
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tests/auto/corelib/kernel')
-rw-r--r-- | tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp | 67 |
1 files changed, 53 insertions, 14 deletions
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp index f2343bbbd2..c0650c7b1a 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp @@ -30,6 +30,30 @@ struct ConvertFunctor } }; +template<typename T> +struct OptionalWrapper +{ + std::optional<T> operator()(const T& t) const + { + if (!CustomConvertibleType::s_ok) + return std::nullopt; + + return t; + } +}; + +template<typename From> +struct ConvertFunctorWithOptional +{ + std::optional<CustomConvertibleType> operator()(const From& f) const + { + if (!CustomConvertibleType::s_ok) + return std::nullopt; + + return CustomConvertibleType(QVariant::fromValue(f)); + } +}; + template<typename From, typename To> bool hasRegisteredConverterFunction() { @@ -81,6 +105,7 @@ void customTypeNotYetConvertible() testCustomTypeNotYetConvertible<QLineF, CustomConvertibleType>(); testCustomTypeNotYetConvertible<QChar, CustomConvertibleType>(); testCustomTypeNotYetConvertible<CustomConvertibleType, CustomConvertibleType2>(); + testCustomTypeNotYetConvertible<CustomConvertibleType, std::optional<CustomConvertibleType>>(); } void registerCustomTypeConversions() @@ -99,20 +124,22 @@ void registerCustomTypeConversions() QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QLine>(&CustomConvertibleType::convert<QLine>))); QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QLineF>(&CustomConvertibleType::convertOk<QLineF>))); QVERIFY((QMetaType::registerConverter<CustomConvertibleType, QChar>(&CustomConvertibleType::convert<QChar>))); - QVERIFY((QMetaType::registerConverter<QString, CustomConvertibleType>(ConvertFunctor<QString>()))); + QVERIFY((QMetaType::registerConverter<QString, CustomConvertibleType>(ConvertFunctorWithOptional<QString>()))); QVERIFY((QMetaType::registerConverter<bool, CustomConvertibleType>(ConvertFunctor<bool>()))); - QVERIFY((QMetaType::registerConverter<int, CustomConvertibleType>(ConvertFunctor<int>()))); + QVERIFY((QMetaType::registerConverter<int, CustomConvertibleType>(ConvertFunctorWithOptional<int>()))); QVERIFY((QMetaType::registerConverter<double, CustomConvertibleType>(ConvertFunctor<double>()))); - QVERIFY((QMetaType::registerConverter<float, CustomConvertibleType>(ConvertFunctor<float>()))); + QVERIFY((QMetaType::registerConverter<float, CustomConvertibleType>(ConvertFunctorWithOptional<float>()))); QVERIFY((QMetaType::registerConverter<QRect, CustomConvertibleType>(ConvertFunctor<QRect>()))); - QVERIFY((QMetaType::registerConverter<QRectF, CustomConvertibleType>(ConvertFunctor<QRectF>()))); + QVERIFY((QMetaType::registerConverter<QRectF, CustomConvertibleType>(ConvertFunctorWithOptional<QRectF>()))); QVERIFY((QMetaType::registerConverter<QPoint, CustomConvertibleType>(ConvertFunctor<QPoint>()))); - QVERIFY((QMetaType::registerConverter<QPointF, CustomConvertibleType>(ConvertFunctor<QPointF>()))); + QVERIFY((QMetaType::registerConverter<QPointF, CustomConvertibleType>(ConvertFunctorWithOptional<QPointF>()))); QVERIFY((QMetaType::registerConverter<QSize, CustomConvertibleType>(ConvertFunctor<QSize>()))); - QVERIFY((QMetaType::registerConverter<QSizeF, CustomConvertibleType>(ConvertFunctor<QSizeF>()))); + QVERIFY((QMetaType::registerConverter<QSizeF, CustomConvertibleType>(ConvertFunctorWithOptional<QSizeF>()))); QVERIFY((QMetaType::registerConverter<QLine, CustomConvertibleType>(ConvertFunctor<QLine>()))); - QVERIFY((QMetaType::registerConverter<QLineF, CustomConvertibleType>(ConvertFunctor<QLineF>()))); + QVERIFY((QMetaType::registerConverter<QLineF, CustomConvertibleType>(ConvertFunctorWithOptional<QLineF>()))); QVERIFY((QMetaType::registerConverter<QChar, CustomConvertibleType>(ConvertFunctor<QChar>()))); + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, std::optional<CustomConvertibleType>>(OptionalWrapper<CustomConvertibleType>()))); + QVERIFY((QMetaType::registerConverter<CustomConvertibleType, CustomConvertibleType2>())); QTest::ignoreMessage(QtWarningMsg, "Type conversion already registered from type CustomConvertibleType to type CustomConvertibleType2"); QVERIFY((!QMetaType::registerConverter<CustomConvertibleType, CustomConvertibleType2>())); @@ -171,7 +198,7 @@ void tst_QMetaType::convertCustomType() QCOMPARE(v.toString(), ok ? testQString : QString()); QCOMPARE(v.value<QString>(), ok ? testQString : QString()); QVERIFY(CustomConvertibleType::s_value.canConvert<CustomConvertibleType>()); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toString()), testQString); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toString()), ok ? testQString : QString()); QFETCH(bool, testBool); CustomConvertibleType::s_value = testBool; @@ -183,7 +210,7 @@ void tst_QMetaType::convertCustomType() CustomConvertibleType::s_value = testInt; QCOMPARE(v.toInt(), ok ? testInt : 0); QCOMPARE(v.value<int>(), ok ? testInt : 0); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toInt()), testInt); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toInt()), ok ? testInt : 0); QFETCH(double, testDouble); CustomConvertibleType::s_value = testDouble; @@ -195,7 +222,7 @@ void tst_QMetaType::convertCustomType() CustomConvertibleType::s_value = testFloat; QCOMPARE(v.toFloat(), ok ? testFloat : 0.0); QCOMPARE(v.value<float>(), ok ? testFloat : 0.0); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toFloat()), testFloat); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toFloat()), ok ? testFloat : 0); QFETCH(QRect, testQRect); CustomConvertibleType::s_value = testQRect; @@ -207,7 +234,7 @@ void tst_QMetaType::convertCustomType() CustomConvertibleType::s_value = testQRectF; QCOMPARE(v.toRectF(), ok ? testQRectF : QRectF()); QCOMPARE(v.value<QRectF>(), ok ? testQRectF : QRectF()); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toRectF()), testQRectF); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toRectF()), ok ? testQRectF : QRectF()); QFETCH(QPoint, testQPoint); CustomConvertibleType::s_value = testQPoint; @@ -219,7 +246,7 @@ void tst_QMetaType::convertCustomType() CustomConvertibleType::s_value = testQPointF; QCOMPARE(v.toPointF(), ok ? testQPointF : QPointF()); QCOMPARE(v.value<QPointF>(), ok ? testQPointF : QPointF()); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toPointF()), testQPointF); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toPointF()), ok ? testQPointF : QPointF()); QFETCH(QSize, testQSize); CustomConvertibleType::s_value = testQSize; @@ -231,7 +258,7 @@ void tst_QMetaType::convertCustomType() CustomConvertibleType::s_value = testQSizeF; QCOMPARE(v.toSizeF(), ok ? testQSizeF : QSizeF()); QCOMPARE(v.value<QSizeF>(), ok ? testQSizeF : QSizeF()); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toSizeF()), testQSizeF); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toSizeF()), ok ? testQSizeF : QSizeF()); QFETCH(QLine, testQLine); CustomConvertibleType::s_value = testQLine; @@ -243,7 +270,7 @@ void tst_QMetaType::convertCustomType() CustomConvertibleType::s_value = testQLineF; QCOMPARE(v.toLineF(), ok ? testQLineF : QLineF()); QCOMPARE(v.value<QLineF>(), ok ? testQLineF : QLineF()); - QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toLineF()), testQLineF); + QCOMPARE((CustomConvertibleType::s_value.value<CustomConvertibleType>().m_foo.toLineF()), ok ? testQLineF : QLineF()); QFETCH(QChar, testQChar); CustomConvertibleType::s_value = testQChar; @@ -255,6 +282,18 @@ void tst_QMetaType::convertCustomType() QVERIFY(v.canConvert(QMetaType(::qMetaTypeId<CustomConvertibleType2>()))); QCOMPARE(v.value<CustomConvertibleType2>().m_foo, testCustom.m_foo); + // Check that converters that actually convert to std::optional<T> are not + // taken to indicate success or failure of the conversion. In these cases, + // the conversion must always succeed, even if the converter has returned a + // nullopt. + v = QVariant::fromValue(testCustom); + QVERIFY(v.canConvert(QMetaType::fromType<std::optional<CustomConvertibleType>>())); + QVERIFY(v.convert(QMetaType::fromType<std::optional<CustomConvertibleType>>())); + QCOMPARE(v.value<std::optional<CustomConvertibleType>>().has_value(), ok); + if (ok) { + QCOMPARE(v.value<std::optional<CustomConvertibleType>>().value().m_foo, testCustom.m_foo); + } + QFETCH(DerivedGadgetType, testDerived); v = QVariant::fromValue(testDerived); QCOMPARE(v.metaType(), QMetaType::fromType<DerivedGadgetType>()); |