diff options
Diffstat (limited to 'src/corelib/kernel/qvariant.h')
-rw-r--r-- | src/corelib/kernel/qvariant.h | 58 |
1 files changed, 52 insertions, 6 deletions
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index ed4978699f..306e5b3a38 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -5,6 +5,7 @@ #define QVARIANT_H #include <QtCore/qatomic.h> +#include <QtCore/qcompare.h> #include <QtCore/qcontainerfwd.h> #include <QtCore/qmetatype.h> #ifndef QT_NO_DEBUG_STREAM @@ -263,7 +264,9 @@ public: QVariant(QChar qchar) noexcept; QVariant(QDate date) noexcept; QVariant(QTime time) noexcept; +#ifndef QT_BOOTSTRAPPED QVariant(const QBitArray &bitarray) noexcept; +#endif QVariant(const QByteArray &bytearray) noexcept; QVariant(const QDateTime &datetime) noexcept; QVariant(const QHash<QString, QVariant> &hash) noexcept; @@ -372,7 +375,9 @@ public: float toFloat(bool *ok = nullptr) const; qreal toReal(bool *ok = nullptr) const; QByteArray toByteArray() const; +#ifndef QT_BOOTSTRAPPED QBitArray toBitArray() const; +#endif QString toString() const; QStringList toStringList() const; QChar toChar() const; @@ -492,6 +497,7 @@ public: // If possible we reuse the current QVariant private. if (isDetached() && d.type() == metaType) { *reinterpret_cast<VT *>(const_cast<void *>(constData())) = std::forward<T>(avalue); + d.is_null = false; } else { *this = QVariant::fromValue<VT>(std::forward<T>(avalue)); } @@ -508,7 +514,7 @@ public: } template<typename T> - inline T value() const + inline T value() const & { return qvariant_cast<T>(*this); } template<typename T> @@ -519,6 +525,10 @@ public: return t; } + template<typename T> + inline T value() && + { return qvariant_cast<T>(std::move(*this)); } + template<typename T, if_rvalue<T> = true> #ifndef Q_QDOC /* needs is_copy_constructible for variants semantics, is_move_constructible so that moveConstruct works @@ -535,7 +545,7 @@ public: // handle special cases using Type = std::remove_cv_t<T>; if constexpr (std::is_null_pointer_v<Type>) - return QVariant(QMetaType::fromType<std::nullptr_t>()); + return QVariant::fromMetaType(QMetaType::fromType<std::nullptr_t>()); else if constexpr (std::is_same_v<Type, QVariant>) return std::forward<T>(value); else if constexpr (std::is_same_v<Type, std::monostate>) @@ -582,6 +592,8 @@ public: return fromStdVariantImpl(std::move(value)); } + static QVariant fromMetaType(QMetaType type, const void *copy = nullptr); + template<typename T> bool canConvert() const { return canConvert(QMetaType::fromType<T>()); } @@ -604,10 +616,10 @@ private: return std::visit(visitor, std::forward<StdVariant>(v)); } - friend inline bool operator==(const QVariant &a, const QVariant &b) + friend bool comparesEqual(const QVariant &a, const QVariant &b) { return a.equals(b); } - friend inline bool operator!=(const QVariant &a, const QVariant &b) - { return !a.equals(b); } + Q_DECLARE_EQUALITY_COMPARABLE(QVariant) + #ifndef QT_NO_DEBUG_STREAM template <typename T> friend auto operator<<(const QDebug &debug, const T &variant) -> std::enable_if_t<std::is_same_v<T, QVariant>, QDebug> { @@ -654,6 +666,9 @@ private: template<typename T> friend inline T qvariant_cast(const QVariant &); + template<typename T> + friend inline T qvariant_cast(QVariant &&); + protected: Private d; void create(int type, const void *copy); @@ -753,14 +768,45 @@ template<typename T> inline T qvariant_cast(const QVariant &v) return t; } +template<typename T> inline T qvariant_cast(QVariant &&v) +{ + QMetaType targetType = QMetaType::fromType<T>(); + if (v.d.type() == targetType) { + if constexpr (QVariant::Private::CanUseInternalSpace<T>) { + return std::move(*reinterpret_cast<T *>(v.d.data.data)); + } else { + if (v.d.data.shared->ref.loadRelaxed() == 1) + return std::move(*reinterpret_cast<T *>(v.d.data.shared->data())); + else + return v.d.get<T>(); + } + } + if constexpr (std::is_same_v<T, QVariant>) { + // if the metatype doesn't match, but we want a QVariant, just return the current variant + return v; + } if constexpr (std::is_same_v<T,std::remove_const_t<std::remove_pointer_t<T>> const *>) { + // moving a pointer is pointless, just do the same as the const & overload + using nonConstT = std::remove_const_t<std::remove_pointer_t<T>> *; + QMetaType nonConstTargetType = QMetaType::fromType<nonConstT>(); + if (v.d.type() == nonConstTargetType) + return v.d.get<nonConstT>(); + } + + T t{}; + QMetaType::convert(v.metaType(), v.constData(), targetType, &t); + return t; +} + +# ifndef QT_NO_VARIANT template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v) { if (v.metaType().id() == QMetaType::QVariant) return *reinterpret_cast<const QVariant *>(v.constData()); return v; } +# endif -#endif +#endif // QT_MOC #ifndef QT_NO_DEBUG_STREAM #if QT_DEPRECATED_SINCE(6, 0) |