summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qvariant.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qvariant.h')
-rw-r--r--src/corelib/kernel/qvariant.h58
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)