diff options
-rw-r--r-- | src/corelib/kernel/qvariant.cpp | 6 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant.h | 21 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp | 45 |
3 files changed, 69 insertions, 3 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 8e2457350c..30da12c95b 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -2722,6 +2722,12 @@ QT_WARNING_POP */ /*! + \fn template<typename... Types> QVariant QVariant::fromStdVariant(std::variant<Types...> &&value) + \since 6.6 + \overload +*/ + +/*! \fn template<typename T> T qvariant_cast(const QVariant &value) \relates QVariant diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 582f135fab..fe99ad6bdd 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -569,9 +569,13 @@ public: template<typename... Types> static inline QVariant fromStdVariant(const std::variant<Types...> &value) { - if (value.valueless_by_exception()) - return QVariant(); - return std::visit([](const auto &arg) { return QVariant::fromValue(arg); }, value); + return fromStdVariantImpl(value); + } + + template<typename... Types> + static QVariant fromStdVariant(std::variant<Types...> &&value) + { + return fromStdVariantImpl(std::move(value)); } template<typename T> @@ -585,6 +589,17 @@ public: static QPartialOrdering compare(const QVariant &lhs, const QVariant &rhs); private: + template <typename StdVariant> + static QVariant fromStdVariantImpl(StdVariant &&v) + { + if (Q_UNLIKELY(v.valueless_by_exception())) + return QVariant(); + auto visitor = [](auto &&arg) { + return QVariant::fromValue(q23::forward_like<StdVariant>(arg)); + }; + return std::visit(visitor, std::forward<StdVariant>(v)); + } + friend inline bool operator==(const QVariant &a, const QVariant &b) { return a.equals(b); } friend inline bool operator!=(const QVariant &a, const QVariant &b) diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index addf7ceec9..23fa969edd 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -5392,6 +5392,16 @@ void tst_QVariant::shouldDeleteVariantDataWorksForAssociative() void tst_QVariant::fromStdVariant() { +#define CHECK_EQUAL(lhs, rhs, type) do { \ + QCOMPARE(lhs.typeId(), rhs.typeId()); \ + if (lhs.isNull()) { \ + QVERIFY(rhs.isNull()); \ + } else { \ + QVERIFY(!rhs.isNull()); \ + QCOMPARE(get< type >(lhs), get< type >(rhs)); \ + } \ + } while (false) + { typedef std::variant<int, bool> intorbool_t; intorbool_t stdvar = 5; @@ -5399,21 +5409,38 @@ void tst_QVariant::fromStdVariant() QVERIFY(!qvar.isNull()); QCOMPARE(qvar.typeId(), QMetaType::Int); QCOMPARE(qvar.value<int>(), std::get<int>(stdvar)); + { + const auto qv2 = QVariant::fromStdVariant(std::move(stdvar)); + CHECK_EQUAL(qv2, qvar, int); + } + stdvar = true; qvar = QVariant::fromStdVariant(stdvar); QVERIFY(!qvar.isNull()); QCOMPARE(qvar.typeId(), QMetaType::Bool); QCOMPARE(qvar.value<bool>(), std::get<bool>(stdvar)); + { + const auto qv2 = QVariant::fromStdVariant(std::move(stdvar)); + CHECK_EQUAL(qv2, qvar, bool); + } } { std::variant<std::monostate, int> stdvar; QVariant qvar = QVariant::fromStdVariant(stdvar); QVERIFY(!qvar.isValid()); + { + const auto qv2 = QVariant::fromStdVariant(std::move(stdvar)); + CHECK_EQUAL(qv2, qvar, int); // fake type, they're empty + } stdvar = -4; qvar = QVariant::fromStdVariant(stdvar); QVERIFY(!qvar.isNull()); QCOMPARE(qvar.typeId(), QMetaType::Int); QCOMPARE(qvar.value<int>(), std::get<int>(stdvar)); + { + const auto qv2 = QVariant::fromStdVariant(std::move(stdvar)); + CHECK_EQUAL(qv2, qvar, int); + } } { std::variant<int, bool, QChar> stdvar = QChar::fromLatin1(' '); @@ -5421,7 +5448,25 @@ void tst_QVariant::fromStdVariant() QVERIFY(!qvar.isNull()); QCOMPARE(qvar.typeId(), QMetaType::QChar); QCOMPARE(qvar.value<QChar>(), std::get<QChar>(stdvar)); + { + const auto qv2 = QVariant::fromStdVariant(std::move(stdvar)); + CHECK_EQUAL(qv2, qvar, QChar); + } } + // rvalue fromStdVariant() actually moves: + { + const auto foo = u"foo"_s; + std::variant<QString, QByteArray> stdvar = foo; + QVariant qvar = QVariant::fromStdVariant(std::move(stdvar)); + const auto ps = get_if<QString>(&stdvar); + QVERIFY(ps); + QVERIFY(ps->isNull()); // QString was moved from + QVERIFY(!qvar.isNull()); + QCOMPARE(qvar.typeId(), QMetaType::QString); + QCOMPARE(get<QString>(qvar), foo); + } + +#undef CHECK_EQUAL } void tst_QVariant::qt4UuidDataStream() |