File indexing completed on 2026-05-07 08:48:25
0001
0002
0003
0004
0005 #ifndef QVARIANT_H
0006 #define QVARIANT_H
0007
0008 #include <QtCore/qatomic.h>
0009 #include <QtCore/qcompare.h>
0010 #include <QtCore/qcontainerfwd.h>
0011 #include <QtCore/qmetatype.h>
0012 #ifndef QT_NO_DEBUG_STREAM
0013 #include <QtCore/qdebug.h>
0014 #endif
0015
0016 #include <memory>
0017 #include <QtCore/q20type_traits.h>
0018 #include <QtCore/q23utility.h>
0019 #include <variant>
0020
0021 #if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 1
0022 # include <QtCore/qlist.h>
0023 # include <QtCore/qstringlist.h>
0024 # include <QtCore/qbytearraylist.h>
0025 # include <QtCore/qhash.h>
0026 # include <QtCore/qmap.h>
0027 # include <QtCore/qobject.h>
0028 #endif
0029
0030 QT_BEGIN_NAMESPACE
0031
0032 QT_ENABLE_P0846_SEMANTICS_FOR(get_if)
0033 QT_ENABLE_P0846_SEMANTICS_FOR(get)
0034
0035 class QBitArray;
0036 class QDataStream;
0037 class QDate;
0038 class QDateTime;
0039 class QEasingCurve;
0040 class QLine;
0041 class QLineF;
0042 class QLocale;
0043 class QModelIndex;
0044 class QPersistentModelIndex;
0045 class QPoint;
0046 class QPointF;
0047 class QRect;
0048 class QRectF;
0049 class QRegularExpression;
0050 class QSize;
0051 class QSizeF;
0052 class QTextFormat;
0053 class QTextLength;
0054 class QTime;
0055 class QTransform;
0056 class QUrl;
0057 class QVariant;
0058
0059 template<typename T>
0060 inline T qvariant_cast(const QVariant &);
0061
0062 namespace QtPrivate {
0063 template<> constexpr inline bool qIsRelocatable<QVariant> = true;
0064
0065 template<typename Referred>
0066 class ConstReference;
0067
0068 template<typename Referred>
0069 class Reference;
0070
0071 template<typename Pointed>
0072 class ConstPointer;
0073
0074 template<typename Pointed>
0075 class Pointer;
0076 }
0077
0078 class Q_CORE_EXPORT QVariant
0079 {
0080 template <typename T, typename... Args>
0081 using if_constructible = std::enable_if_t<
0082 std::conjunction_v<
0083 std::is_copy_constructible<q20::remove_cvref_t<T>>,
0084 std::is_destructible<q20::remove_cvref_t<T>>,
0085 std::is_constructible<q20::remove_cvref_t<T>, Args...>
0086 >,
0087 bool>;
0088
0089 template <typename T>
0090 using if_rvalue = std::enable_if_t<!std::is_reference_v<T>, bool>;
0091
0092 struct CborValueStandIn { qint64 n; void *c; int t; };
0093 public:
0094 struct PrivateShared
0095 {
0096 private:
0097 inline PrivateShared() : ref(1) { }
0098 public:
0099 static int computeOffset(PrivateShared *ps, size_t align);
0100 static size_t computeAllocationSize(size_t size, size_t align);
0101 static PrivateShared *create(size_t size, size_t align);
0102 static void free(PrivateShared *p);
0103
0104 alignas(8) QAtomicInt ref;
0105 int offset;
0106
0107 const void *data() const { return reinterpret_cast<const uchar *>(this) + offset; }
0108 void *data() { return reinterpret_cast<uchar *>(this) + offset; }
0109 };
0110
0111 struct Private
0112 {
0113 static constexpr size_t MaxInternalSize = 3 * sizeof(void *);
0114 template <size_t S> static constexpr bool FitsInInternalSize = S <= MaxInternalSize;
0115 template<typename T> static constexpr bool CanUseInternalSpace =
0116 (QTypeInfo<T>::isRelocatable && FitsInInternalSize<sizeof(T)> && alignof(T) <= alignof(double));
0117 static constexpr bool canUseInternalSpace(const QtPrivate::QMetaTypeInterface *type)
0118 {
0119 Q_ASSERT(type);
0120 return QMetaType::TypeFlags(type->flags) & QMetaType::RelocatableType &&
0121 size_t(type->size) <= MaxInternalSize && size_t(type->alignment) <= alignof(double);
0122 }
0123
0124 union
0125 {
0126 uchar data[MaxInternalSize] = {};
0127 PrivateShared *shared;
0128 double _forAlignment;
0129 } data;
0130 quintptr is_shared : 1;
0131 quintptr is_null : 1;
0132 quintptr packedType : sizeof(QMetaType) * 8 - 2;
0133
0134 constexpr Private() noexcept : is_shared(false), is_null(true), packedType(0) {}
0135 explicit Private(const QtPrivate::QMetaTypeInterface *iface) noexcept;
0136 template <typename T> explicit Private(std::piecewise_construct_t, const T &t);
0137
0138 const void *storage() const
0139 { return is_shared ? data.shared->data() : &data.data; }
0140
0141 template<typename T> const T &get() const
0142 { return *static_cast<const T *>(storage()); }
0143
0144 inline const QtPrivate::QMetaTypeInterface *typeInterface() const
0145 {
0146 return reinterpret_cast<const QtPrivate::QMetaTypeInterface *>(packedType << 2);
0147 }
0148
0149 inline QMetaType type() const
0150 {
0151 return QMetaType(typeInterface());
0152 }
0153 };
0154
0155 #if QT_DEPRECATED_SINCE(6, 0)
0156 enum QT_DEPRECATED_VERSION_X_6_0("Use QMetaType::Type instead.") Type
0157 {
0158 Invalid = QMetaType::UnknownType,
0159 Bool = QMetaType::Bool,
0160 Int = QMetaType::Int,
0161 UInt = QMetaType::UInt,
0162 LongLong = QMetaType::LongLong,
0163 ULongLong = QMetaType::ULongLong,
0164 Double = QMetaType::Double,
0165 Char = QMetaType::QChar,
0166 Map = QMetaType::QVariantMap,
0167 List = QMetaType::QVariantList,
0168 String = QMetaType::QString,
0169 StringList = QMetaType::QStringList,
0170 ByteArray = QMetaType::QByteArray,
0171 BitArray = QMetaType::QBitArray,
0172 Date = QMetaType::QDate,
0173 Time = QMetaType::QTime,
0174 DateTime = QMetaType::QDateTime,
0175 Url = QMetaType::QUrl,
0176 Locale = QMetaType::QLocale,
0177 Rect = QMetaType::QRect,
0178 RectF = QMetaType::QRectF,
0179 Size = QMetaType::QSize,
0180 SizeF = QMetaType::QSizeF,
0181 Line = QMetaType::QLine,
0182 LineF = QMetaType::QLineF,
0183 Point = QMetaType::QPoint,
0184 PointF = QMetaType::QPointF,
0185 #if QT_CONFIG(regularexpression)
0186 RegularExpression = QMetaType::QRegularExpression,
0187 #endif
0188 Hash = QMetaType::QVariantHash,
0189 #if QT_CONFIG(easingcurve)
0190 EasingCurve = QMetaType::QEasingCurve,
0191 #endif
0192 Uuid = QMetaType::QUuid,
0193 #if QT_CONFIG(itemmodel)
0194 ModelIndex = QMetaType::QModelIndex,
0195 PersistentModelIndex = QMetaType::QPersistentModelIndex,
0196 #endif
0197 LastCoreType = QMetaType::LastCoreType,
0198
0199 Font = QMetaType::QFont,
0200 Pixmap = QMetaType::QPixmap,
0201 Brush = QMetaType::QBrush,
0202 Color = QMetaType::QColor,
0203 Palette = QMetaType::QPalette,
0204 Image = QMetaType::QImage,
0205 Polygon = QMetaType::QPolygon,
0206 Region = QMetaType::QRegion,
0207 Bitmap = QMetaType::QBitmap,
0208 Cursor = QMetaType::QCursor,
0209 #if QT_CONFIG(shortcut)
0210 KeySequence = QMetaType::QKeySequence,
0211 #endif
0212 Pen = QMetaType::QPen,
0213 TextLength = QMetaType::QTextLength,
0214 TextFormat = QMetaType::QTextFormat,
0215 Transform = QMetaType::QTransform,
0216 Matrix4x4 = QMetaType::QMatrix4x4,
0217 Vector2D = QMetaType::QVector2D,
0218 Vector3D = QMetaType::QVector3D,
0219 Vector4D = QMetaType::QVector4D,
0220 Quaternion = QMetaType::QQuaternion,
0221 PolygonF = QMetaType::QPolygonF,
0222 Icon = QMetaType::QIcon,
0223 LastGuiType = QMetaType::LastGuiType,
0224
0225 SizePolicy = QMetaType::QSizePolicy,
0226
0227 UserType = QMetaType::User,
0228 LastType = 0xffffffff
0229 };
0230 #endif
0231 QVariant() noexcept : d() {}
0232 ~QVariant();
0233 explicit QVariant(QMetaType type, const void *copy = nullptr);
0234 QVariant(const QVariant &other);
0235
0236 private:
0237 template <typename T, typename ...Args>
0238 using is_noexcept_constructible = std::conjunction<
0239 std::bool_constant<Private::CanUseInternalSpace<T>>,
0240 std::is_nothrow_constructible<T, Args...>
0241 >;
0242
0243 public:
0244 template<typename Referred>
0245 class ConstReference
0246 {
0247 private:
0248 const Referred m_referred;
0249
0250 public:
0251
0252
0253 explicit ConstReference(const Referred &referred)
0254 noexcept(std::is_nothrow_copy_constructible_v<Referred>)
0255 : m_referred(referred) {}
0256 explicit ConstReference(Referred &&referred)
0257 noexcept(std::is_nothrow_move_constructible_v<Referred>)
0258 : m_referred(std::move(referred)) {}
0259 ConstReference(const ConstReference &) = default;
0260 ConstReference(ConstReference &&) = default;
0261 ~ConstReference() = default;
0262 ConstReference &operator=(const ConstReference &value) = delete;
0263 ConstReference &operator=(ConstReference &&value) = delete;
0264
0265
0266 operator QVariant() const noexcept(Referred::canNoexceptConvertToQVariant);
0267 };
0268
0269 template<typename Referred>
0270 class Reference
0271 {
0272 private:
0273 Referred m_referred;
0274
0275 friend void swap(Reference a, Reference b) { return a.swap(std::move(b)); }
0276
0277 public:
0278
0279
0280 explicit Reference(const Referred &referred)
0281 noexcept(std::is_nothrow_copy_constructible_v<Referred>)
0282 : m_referred(referred) {}
0283 explicit Reference(Referred &&referred)
0284 noexcept(std::is_nothrow_move_constructible_v<Referred>)
0285 : m_referred(std::move(referred)) {}
0286 Reference(const Reference &) = default;
0287 Reference(Reference &&) = default;
0288 ~Reference() = default;
0289
0290 Reference &operator=(const Reference &value)
0291 noexcept(Referred::canNoexceptAssignQVariant)
0292 {
0293 return operator=(QVariant(value));
0294 }
0295
0296 Reference &operator=(Reference &&value)
0297 noexcept(Referred::canNoexceptAssignQVariant)
0298 {
0299 return operator=(QVariant(value));
0300 }
0301
0302 operator QVariant() const noexcept(Referred::canNoexceptConvertToQVariant)
0303 {
0304 return ConstReference(m_referred);
0305 }
0306
0307 void swap(Reference b)
0308 {
0309
0310 QVariant tmp = *this;
0311 *this = std::move(b);
0312 b = std::move(tmp);
0313 }
0314
0315
0316 Reference &operator=(const QVariant &value) noexcept(Referred::canNoexceptAssignQVariant);
0317 };
0318
0319 template<typename Pointed>
0320 class ConstPointer
0321 {
0322 private:
0323 Pointed m_pointed;
0324
0325 public:
0326 explicit ConstPointer(const Pointed &pointed)
0327 noexcept(std::is_nothrow_copy_constructible_v<Pointed>)
0328 : m_pointed(pointed) {}
0329 explicit ConstPointer(Pointed &&pointed)
0330 noexcept(std::is_nothrow_move_constructible_v<Pointed>)
0331 : m_pointed(std::move(pointed)) {}
0332
0333 ConstReference<Pointed> operator*()
0334 const noexcept(std::is_nothrow_copy_constructible_v<Pointed>)
0335 {
0336 return ConstReference<Pointed>(m_pointed);
0337 }
0338 };
0339
0340 template<typename Pointed>
0341 class Pointer
0342 {
0343 private:
0344 Pointed m_pointed;
0345
0346 public:
0347 explicit Pointer(const Pointed &pointed)
0348 noexcept(std::is_nothrow_copy_constructible_v<Pointed>)
0349 : m_pointed(pointed) {}
0350 explicit Pointer(Pointed &&pointed)
0351 noexcept(std::is_nothrow_move_constructible_v<Pointed>)
0352 : m_pointed(std::move(pointed)) {}
0353
0354 Reference<Pointed> operator*()
0355 const noexcept(std::is_nothrow_copy_constructible_v<Pointed>)
0356 {
0357 return Reference<Pointed>(m_pointed);
0358 }
0359 };
0360
0361 template <typename T, typename... Args,
0362 if_constructible<T, Args...> = true>
0363 explicit QVariant(std::in_place_type_t<T>, Args&&... args)
0364 noexcept(is_noexcept_constructible<q20::remove_cvref_t<T>, Args...>::value)
0365 : QVariant(std::in_place, QMetaType::fromType<q20::remove_cvref_t<T>>() )
0366 {
0367 void *data = const_cast<void *>(constData());
0368 new (data) T(std::forward<Args>(args)...);
0369 }
0370
0371 template <typename T, typename U, typename... Args,
0372 if_constructible<T, std::initializer_list<U> &, Args...> = true>
0373 explicit QVariant(std::in_place_type_t<T>, std::initializer_list<U> il, Args&&... args)
0374 noexcept(is_noexcept_constructible<q20::remove_cvref_t<T>,
0375 std::initializer_list<U> &,
0376 Args...
0377 >::value)
0378 : QVariant(std::in_place, QMetaType::fromType<q20::remove_cvref_t<T>>())
0379 {
0380 void *data = const_cast<void *>(constData());
0381 new (data) T(il, std::forward<Args>(args)...);
0382 }
0383
0384
0385 QVariant(int i) noexcept;
0386 QVariant(uint ui) noexcept;
0387 QVariant(qlonglong ll) noexcept;
0388 QVariant(qulonglong ull) noexcept;
0389 QVariant(bool b) noexcept;
0390 QVariant(double d) noexcept;
0391 QVariant(float f) noexcept;
0392
0393
0394 QVariant(QChar qchar) noexcept;
0395 QVariant(QDate date) noexcept;
0396 QVariant(QTime time) noexcept;
0397 QVariant(const QBitArray &bitarray) noexcept;
0398 QVariant(const QByteArray &bytearray) noexcept;
0399 QVariant(const QDateTime &datetime) noexcept;
0400 QVariant(const QHash<QString, QVariant> &hash) noexcept;
0401 QVariant(const QJsonArray &jsonArray) noexcept;
0402 QVariant(const QJsonObject &jsonObject) noexcept;
0403 QVariant(const QList<QVariant> &list) noexcept;
0404 QVariant(const QLocale &locale) noexcept;
0405 QVariant(const QMap<QString, QVariant> &map) noexcept;
0406 QVariant(const QRegularExpression &re) noexcept;
0407 QVariant(const QString &string) noexcept;
0408 QVariant(const QStringList &stringlist) noexcept;
0409 QVariant(const QUrl &url) noexcept;
0410
0411
0412
0413 QVariant(const QJsonValue &jsonValue) noexcept(Private::FitsInInternalSize<sizeof(CborValueStandIn)>);
0414 QVariant(const QModelIndex &modelIndex) noexcept(Private::FitsInInternalSize<8 + 2 * sizeof(quintptr)>);
0415 QVariant(QUuid uuid) noexcept(Private::FitsInInternalSize<16>);
0416 QVariant(QSize size) noexcept;
0417 QVariant(QSizeF size) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>);
0418 QVariant(QPoint pt) noexcept;
0419 QVariant(QPointF pt) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 2>);
0420 QVariant(QLine line) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>);
0421 QVariant(QLineF line) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>);
0422 QVariant(QRect rect) noexcept(Private::FitsInInternalSize<sizeof(int) * 4>);
0423 QVariant(QRectF rect) noexcept(Private::FitsInInternalSize<sizeof(qreal) * 4>);
0424
0425
0426 QVariant(const QEasingCurve &easing) noexcept(false);
0427 QVariant(const QJsonDocument &jsonDocument) noexcept(false);
0428 QVariant(const QPersistentModelIndex &modelIndex) noexcept(false);
0429
0430 #ifndef QT_NO_CAST_FROM_ASCII
0431 QT_ASCII_CAST_WARN QVariant(const char *str) noexcept(false)
0432 : QVariant(QString::fromUtf8(str))
0433 {}
0434 #endif
0435 QVariant(QLatin1StringView string) noexcept(false);
0436
0437 #if !defined(Q_CC_GHS)
0438
0439 template <typename T,
0440 std::enable_if_t<std::disjunction_v<std::is_pointer<T>, std::is_member_pointer<T>>, bool> = false>
0441 QVariant(T) = delete;
0442 #else
0443 QVariant(const volatile void *) = delete;
0444 #endif
0445
0446 #if QT_CORE_REMOVED_SINCE(6, 5)
0447 QVariant(const QSize &size);
0448 QVariant(const QSizeF &size);
0449 QVariant(const QPoint &pt);
0450 QVariant(const QPointF &pt);
0451 QVariant(const QLine &line);
0452 QVariant(const QLineF &line);
0453 QVariant(const QRect &rect);
0454 QVariant(const QRectF &rect);
0455 QVariant(const QUuid &uuid);
0456 #endif
0457
0458 QVariant& operator=(const QVariant &other);
0459 inline QVariant(QVariant &&other) noexcept : d(other.d)
0460 { other.d = Private(); }
0461 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QVariant)
0462
0463 inline void swap(QVariant &other) noexcept { std::swap(d, other.d); }
0464
0465 int userType() const { return typeId(); }
0466 int typeId() const
0467 {
0468
0469 const QtPrivate::QMetaTypeInterface *mt = metaType().iface();
0470 if (!mt)
0471 return 0;
0472 int id = mt->typeId.loadRelaxed();
0473
0474 return id;
0475 }
0476
0477 QT_CORE_INLINE_SINCE(6, 10)
0478 const char *typeName() const;
0479 QT_CORE_INLINE_SINCE(6, 10)
0480 QMetaType metaType() const;
0481
0482 bool canConvert(QMetaType targetType) const
0483 { return QMetaType::canConvert(d.type(), targetType); }
0484 bool convert(QMetaType type);
0485
0486 bool canView(QMetaType targetType) const
0487 { return QMetaType::canView(d.type(), targetType); }
0488
0489 #if QT_DEPRECATED_SINCE(6, 0)
0490 QT_DEPRECATED_VERSION_6_0
0491 bool canConvert(int targetTypeId) const
0492 { return QMetaType::canConvert(d.type(), QMetaType(targetTypeId)); }
0493 QT_DEPRECATED_VERSION_6_0
0494 bool convert(int targetTypeId)
0495 { return convert(QMetaType(targetTypeId)); }
0496 #endif
0497
0498 inline bool isValid() const;
0499 bool isNull() const;
0500
0501 void clear();
0502
0503 void detach();
0504 inline bool isDetached() const;
0505
0506 int toInt(bool *ok = nullptr) const;
0507 uint toUInt(bool *ok = nullptr) const;
0508 qlonglong toLongLong(bool *ok = nullptr) const;
0509 qulonglong toULongLong(bool *ok = nullptr) const;
0510 bool toBool() const;
0511 double toDouble(bool *ok = nullptr) const;
0512 float toFloat(bool *ok = nullptr) const;
0513 qreal toReal(bool *ok = nullptr) const;
0514 QByteArray toByteArray() const;
0515 QBitArray toBitArray() const;
0516 QString toString() const;
0517 QStringList toStringList() const;
0518 QChar toChar() const;
0519 QDate toDate() const;
0520 QTime toTime() const;
0521 QDateTime toDateTime() const;
0522 QList<QVariant> toList() const;
0523 QMap<QString, QVariant> toMap() const;
0524 QHash<QString, QVariant> toHash() const;
0525
0526 QPoint toPoint() const;
0527 QPointF toPointF() const;
0528 QRect toRect() const;
0529 QSize toSize() const;
0530 QSizeF toSizeF() const;
0531 QLine toLine() const;
0532 QLineF toLineF() const;
0533 QRectF toRectF() const;
0534 QLocale toLocale() const;
0535 #if QT_CONFIG(regularexpression)
0536 QRegularExpression toRegularExpression() const;
0537 #endif
0538 #if QT_CONFIG(easingcurve)
0539 QEasingCurve toEasingCurve() const;
0540 #endif
0541 QUuid toUuid() const;
0542 QUrl toUrl() const;
0543 QJsonValue toJsonValue() const;
0544 QJsonObject toJsonObject() const;
0545 QJsonArray toJsonArray() const;
0546 QJsonDocument toJsonDocument() const;
0547 #if QT_CONFIG(itemmodel)
0548 QModelIndex toModelIndex() const;
0549 QPersistentModelIndex toPersistentModelIndex() const;
0550 #endif
0551
0552 #ifndef QT_NO_DATASTREAM
0553 void load(QDataStream &ds);
0554 void save(QDataStream &ds) const;
0555 #endif
0556 #if QT_DEPRECATED_SINCE(6, 0)
0557 QT_WARNING_PUSH
0558 QT_WARNING_DISABLE_DEPRECATED
0559 QT_DEPRECATED_VERSION_X_6_0("Use the constructor taking a QMetaType instead.")
0560 explicit QVariant(Type type)
0561 : QVariant(QMetaType(int(type)))
0562 {}
0563 QT_DEPRECATED_VERSION_X_6_0("Use typeId() or metaType().")
0564 Type type() const
0565 {
0566 int type = d.type().id();
0567 return type >= QMetaType::User ? UserType : static_cast<Type>(type);
0568 }
0569 QT_DEPRECATED_VERSION_6_0
0570 static const char *typeToName(int typeId)
0571 { return QMetaType(typeId).name(); }
0572 QT_DEPRECATED_VERSION_6_0
0573 static Type nameToType(const char *name)
0574 {
0575 int metaType = QMetaType::fromName(name).id();
0576 return metaType <= int(UserType) ? QVariant::Type(metaType) : UserType;
0577 }
0578 QT_WARNING_POP
0579 #endif
0580
0581 void *data();
0582 const void *constData() const
0583 { return d.storage(); }
0584 inline const void *data() const { return constData(); }
0585
0586 private:
0587 template <typename T>
0588 void verifySuitableForEmplace()
0589 {
0590 static_assert(!std::is_reference_v<T>,
0591 "QVariant does not support reference types");
0592 static_assert(!std::is_const_v<T>,
0593 "QVariant does not support const types");
0594 static_assert(std::is_copy_constructible_v<T>,
0595 "QVariant requires that the type is copyable");
0596 static_assert(std::is_destructible_v<T>,
0597 "QVariant requires that the type is destructible");
0598 }
0599
0600 template <typename T, typename... Args>
0601 T &emplaceImpl(Args&&... args)
0602 {
0603 verifySuitableForEmplace<T>();
0604 auto data = static_cast<T *>(prepareForEmplace(QMetaType::fromType<T>()));
0605 return *q20::construct_at(data, std::forward<Args>(args)...);
0606 }
0607
0608 public:
0609 template <typename T, typename... Args,
0610 if_constructible<T, Args...> = true>
0611 T &emplace(Args&&... args)
0612 {
0613 return emplaceImpl<T>(std::forward<Args>(args)...);
0614 }
0615
0616 template <typename T, typename U, typename... Args,
0617 if_constructible<T, std::initializer_list<U> &, Args...> = true>
0618 T &emplace(std::initializer_list<U> list, Args&&... args)
0619 {
0620 return emplaceImpl<T>(list, std::forward<Args>(args)...);
0621 }
0622
0623 template<typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, QVariant>>>
0624 void setValue(T &&avalue)
0625 {
0626 using VT = std::decay_t<T>;
0627 QMetaType metaType = QMetaType::fromType<VT>();
0628
0629 if (isDetached() && d.type() == metaType) {
0630 *reinterpret_cast<VT *>(const_cast<void *>(constData())) = std::forward<T>(avalue);
0631 d.is_null = false;
0632 } else {
0633 *this = QVariant::fromValue<VT>(std::forward<T>(avalue));
0634 }
0635 }
0636
0637 void setValue(const QVariant &avalue)
0638 {
0639 *this = avalue;
0640 }
0641
0642 void setValue(QVariant &&avalue)
0643 {
0644 *this = std::move(avalue);
0645 }
0646
0647 template<typename T>
0648 inline T value() const &
0649 { return qvariant_cast<T>(*this); }
0650
0651 template<typename T>
0652 inline T view()
0653 {
0654 T t{};
0655 QMetaType::view(metaType(), data(), QMetaType::fromType<T>(), &t);
0656 return t;
0657 }
0658
0659 template<typename T>
0660 inline T value() &&
0661 { return qvariant_cast<T>(std::move(*this)); }
0662
0663 template<typename T, if_rvalue<T> = true>
0664 #ifndef Q_QDOC
0665
0666
0667
0668 static inline auto fromValue(T &&value)
0669 noexcept(std::is_nothrow_copy_constructible_v<T> && Private::CanUseInternalSpace<T>)
0670 -> std::enable_if_t<std::conjunction_v<std::is_copy_constructible<T>,
0671 std::is_destructible<T>>, QVariant>
0672 #else
0673 static inline QVariant fromValue(T &&value)
0674 #endif
0675 {
0676
0677 using Type = std::remove_cv_t<T>;
0678 if constexpr (std::is_null_pointer_v<Type>)
0679 return QVariant::fromMetaType(QMetaType::fromType<std::nullptr_t>());
0680 else if constexpr (std::is_same_v<Type, QVariant>)
0681 return std::forward<T>(value);
0682 else if constexpr (std::is_same_v<Type, std::monostate>)
0683 return QVariant();
0684 QMetaType mt = QMetaType::fromType<Type>();
0685 mt.registerType();
0686
0687
0688
0689 if constexpr (std::conjunction_v<std::is_move_constructible<Type>, std::negation<std::is_const<T>>>)
0690 return moveConstruct(QMetaType::fromType<Type>(), std::addressof(value));
0691 else
0692 return copyConstruct(mt, std::addressof(value));
0693 }
0694
0695 template<typename T>
0696 #ifndef Q_QDOC
0697 static inline auto fromValue(const T &value)
0698 noexcept(std::is_nothrow_copy_constructible_v<T> && Private::CanUseInternalSpace<T>)
0699 -> std::enable_if_t<std::is_copy_constructible_v<T> && std::is_destructible_v<T>, QVariant>
0700 #else
0701 static inline QVariant fromValue(const T &value)
0702 #endif
0703 {
0704 if constexpr (std::is_null_pointer_v<T>)
0705 return QVariant(QMetaType::fromType<std::nullptr_t>());
0706 else if constexpr (std::is_same_v<T, QVariant>)
0707 return value;
0708 else if constexpr (std::is_same_v<T, std::monostate>)
0709 return QVariant();
0710 return QVariant(QMetaType::fromType<T>(), std::addressof(value));
0711 }
0712
0713 template<typename... Types>
0714 static inline QVariant fromStdVariant(const std::variant<Types...> &value)
0715 {
0716 return fromStdVariantImpl(value);
0717 }
0718
0719 template<typename... Types>
0720 static QVariant fromStdVariant(std::variant<Types...> &&value)
0721 {
0722 return fromStdVariantImpl(std::move(value));
0723 }
0724
0725 static QVariant fromMetaType(QMetaType type, const void *copy = nullptr);
0726
0727 template<typename T>
0728 bool canConvert() const
0729 { return canConvert(QMetaType::fromType<T>()); }
0730
0731 template<typename T>
0732 bool canView() const
0733 { return canView(QMetaType::fromType<T>()); }
0734
0735 static QPartialOrdering compare(const QVariant &lhs, const QVariant &rhs);
0736
0737 private:
0738 template <typename StdVariant>
0739 static QVariant fromStdVariantImpl(StdVariant &&v)
0740 {
0741 if (Q_UNLIKELY(v.valueless_by_exception()))
0742 return QVariant();
0743 auto visitor = [](auto &&arg) {
0744 return QVariant::fromValue(q23::forward_like<StdVariant>(arg));
0745 };
0746 return std::visit(visitor, std::forward<StdVariant>(v));
0747 }
0748
0749 friend bool comparesEqual(const QVariant &a, const QVariant &b)
0750 { return a.equals(b); }
0751 Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(QVariant)
0752
0753 #ifndef QT_NO_DEBUG_STREAM
0754 template <typename T>
0755 friend auto operator<<(const QDebug &debug, const T &variant) -> std::enable_if_t<std::is_same_v<T, QVariant>, QDebug> {
0756 return variant.qdebugHelper(debug);
0757 }
0758 QDebug qdebugHelper(QDebug) const;
0759 #endif
0760
0761 template <typename T>
0762 friend T *get_if(QVariant *v) noexcept
0763 {
0764
0765 if (!v || v->d.type() != QMetaType::fromType<T>())
0766 return nullptr;
0767 return static_cast<T*>(v->data());
0768 }
0769 template <typename T>
0770 friend const T *get_if(const QVariant *v) noexcept
0771 {
0772
0773 if (!v || v->d.is_null || v->d.type() != QMetaType::fromType<T>())
0774 return nullptr;
0775 return static_cast<const T*>(v->data());
0776 }
0777
0778 #define Q_MK_GET(cvref) \
0779 template <typename T> \
0780 friend T cvref get(QVariant cvref v) \
0781 { \
0782 if constexpr (std::is_const_v<T cvref>) \
0783 Q_ASSERT(!v.d.is_null); \
0784 Q_ASSERT(v.d.type() == QMetaType::fromType<q20::remove_cvref_t<T>>()); \
0785 return static_cast<T cvref>(*get_if<T>(&v)); \
0786 } \
0787
0788 Q_MK_GET(&)
0789 Q_MK_GET(const &)
0790 Q_MK_GET(&&)
0791 Q_MK_GET(const &&)
0792 #undef Q_MK_GET
0793
0794 static QVariant moveConstruct(QMetaType type, void *data);
0795 static QVariant copyConstruct(QMetaType type, const void *data);
0796
0797 template<typename T>
0798 friend inline T qvariant_cast(const QVariant &);
0799 template<typename T>
0800 friend inline T qvariant_cast(QVariant &&);
0801
0802 protected:
0803 Private d;
0804 void create(int type, const void *copy);
0805 void create(QMetaType type, const void *copy);
0806 bool equals(const QVariant &other) const;
0807 bool convert(int type, void *ptr) const;
0808 bool view(int type, void *ptr);
0809
0810 private:
0811
0812 inline QVariant(void *) = delete;
0813
0814
0815
0816
0817
0818
0819 QVariant(QMetaType::Type) = delete;
0820
0821
0822 QVariant(std::in_place_t, QMetaType type);
0823
0824 void *prepareForEmplace(QMetaType type);
0825
0826
0827
0828
0829
0830
0831 QVariant(Qt::GlobalColor) = delete;
0832 QVariant(Qt::BrushStyle) = delete;
0833 QVariant(Qt::PenStyle) = delete;
0834 QVariant(Qt::CursorShape) = delete;
0835 #ifdef QT_NO_CAST_FROM_ASCII
0836
0837 inline QVariant(const char *) = delete;
0838 #endif
0839 public:
0840 typedef Private DataPtr;
0841 inline DataPtr &data_ptr() { return d; }
0842 inline const DataPtr &data_ptr() const { return d; }
0843 };
0844
0845 inline bool QVariant::isValid() const
0846 {
0847 return d.type().isValid(QT6_CALL_NEW_OVERLOAD);
0848 }
0849
0850 #ifndef QT_NO_DATASTREAM
0851 Q_CORE_EXPORT QDataStream &operator>>(QDataStream &s, QVariant &p);
0852 Q_CORE_EXPORT QDataStream &operator<<(QDataStream &s, const QVariant &p);
0853
0854 #if QT_DEPRECATED_SINCE(6, 0)
0855 QT_WARNING_PUSH
0856 QT_WARNING_DISABLE_DEPRECATED
0857 QT_DEPRECATED_VERSION_6_0
0858 inline QDataStream &operator>>(QDataStream &s, QVariant::Type &p)
0859 {
0860 quint32 u;
0861 s >> u;
0862 p = static_cast<QVariant::Type>(u);
0863 return s;
0864 }
0865 QT_DEPRECATED_VERSION_6_0
0866 inline QDataStream &operator<<(QDataStream &s, const QVariant::Type p)
0867 {
0868 s << static_cast<quint32>(p);
0869 return s;
0870 }
0871 QT_WARNING_POP
0872 #endif
0873
0874 #endif
0875
0876 #if QT_CORE_INLINE_IMPL_SINCE(6, 10)
0877 QMetaType QVariant::metaType() const
0878 {
0879 return d.type();
0880 }
0881
0882 const char *QVariant::typeName() const
0883 {
0884 return d.type().name();
0885 }
0886 #endif
0887
0888 inline bool QVariant::isDetached() const
0889 { return !d.is_shared || d.data.shared->ref.loadRelaxed() == 1; }
0890
0891 inline void swap(QVariant &value1, QVariant &value2) noexcept
0892 { value1.swap(value2); }
0893
0894 #ifndef QT_MOC
0895
0896 template<typename T> inline T qvariant_cast(const QVariant &v)
0897 {
0898 QMetaType targetType = QMetaType::fromType<T>();
0899 if (v.d.type() == targetType)
0900 return v.d.get<T>();
0901 if constexpr (std::is_same_v<T,std::remove_const_t<std::remove_pointer_t<T>> const *>) {
0902 using nonConstT = std::remove_const_t<std::remove_pointer_t<T>> *;
0903 QMetaType nonConstTargetType = QMetaType::fromType<nonConstT>();
0904 if (v.d.type() == nonConstTargetType)
0905 return v.d.get<nonConstT>();
0906 }
0907
0908 T t{};
0909 QMetaType::convert(v.metaType(), v.constData(), targetType, &t);
0910 return t;
0911 }
0912
0913 template<typename T> inline T qvariant_cast(QVariant &&v)
0914 {
0915 QMetaType targetType = QMetaType::fromType<T>();
0916 if (v.d.type() == targetType) {
0917 if constexpr (QVariant::Private::FitsInInternalSize<sizeof(T)>) {
0918
0919
0920
0921 if (!v.d.is_shared)
0922 return std::move(*reinterpret_cast<T *>(v.d.data.data));
0923 }
0924
0925 Q_ASSERT(v.d.is_shared);
0926 if (v.d.data.shared->ref.loadRelaxed() == 1)
0927 return std::move(*reinterpret_cast<T *>(v.d.data.shared->data()));
0928 else
0929 return v.d.get<T>();
0930 }
0931 if constexpr (std::is_same_v<T, QVariant>) {
0932
0933 return v;
0934 } if constexpr (std::is_same_v<T,std::remove_const_t<std::remove_pointer_t<T>> const *>) {
0935
0936 using nonConstT = std::remove_const_t<std::remove_pointer_t<T>> *;
0937 QMetaType nonConstTargetType = QMetaType::fromType<nonConstT>();
0938 if (v.d.type() == nonConstTargetType)
0939 return v.d.get<nonConstT>();
0940 }
0941
0942 T t{};
0943 QMetaType::convert(v.metaType(), v.constData(), targetType, &t);
0944 return t;
0945 }
0946
0947 # ifndef QT_NO_VARIANT
0948 template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v)
0949 {
0950 if (v.metaType().id() == QMetaType::QVariant)
0951 return *reinterpret_cast<const QVariant *>(v.constData());
0952 return v;
0953 }
0954 # endif
0955
0956 #endif
0957
0958 #ifndef QT_NO_DEBUG_STREAM
0959 #if QT_DEPRECATED_SINCE(6, 0)
0960 QT_WARNING_PUSH
0961 QT_WARNING_DISABLE_DEPRECATED
0962 QT_DEPRECATED_VERSION_6_0
0963 Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type);
0964 QT_WARNING_POP
0965 #endif
0966 #endif
0967
0968 namespace QtPrivate {
0969 class Q_CORE_EXPORT QVariantTypeCoercer
0970 {
0971 public:
0972
0973 const void *convert(const QVariant &value, const QMetaType &type);
0974 const void *coerce(const QVariant &value, const QMetaType &type);
0975
0976 private:
0977 QVariant converted;
0978 };
0979 }
0980
0981 template<typename Pointer>
0982 class QVariantRef
0983 {
0984 private:
0985 const Pointer *m_pointer = nullptr;
0986
0987 public:
0988 explicit QVariantRef(const Pointer *reference) : m_pointer(reference) {}
0989 QVariantRef(const QVariantRef &) = default;
0990 QVariantRef(QVariantRef &&) = default;
0991 ~QVariantRef() = default;
0992
0993 operator QVariant() const;
0994 QVariantRef &operator=(const QVariant &value);
0995 QVariantRef &operator=(const QVariantRef &value) { return operator=(QVariant(value)); }
0996 QVariantRef &operator=(QVariantRef &&value) { return operator=(QVariant(value)); }
0997
0998 friend void swap(QVariantRef a, QVariantRef b)
0999 {
1000 QVariant tmp = a;
1001 a = b;
1002 b = std::move(tmp);
1003 }
1004 };
1005
1006 class Q_CORE_EXPORT QVariantConstPointer
1007 {
1008 private:
1009 QVariant m_variant;
1010
1011 public:
1012 explicit QVariantConstPointer(QVariant variant);
1013
1014 QVariant operator*() const;
1015 const QVariant *operator->() const;
1016 };
1017
1018 template<typename Pointer>
1019 class QVariantPointer
1020 {
1021 private:
1022 const Pointer *m_pointer = nullptr;
1023
1024 public:
1025 explicit QVariantPointer(const Pointer *pointer) : m_pointer(pointer) {}
1026 QVariantRef<Pointer> operator*() const { return QVariantRef<Pointer>(m_pointer); }
1027 Pointer operator->() const { return *m_pointer; }
1028 };
1029
1030 QT_END_NAMESPACE
1031
1032 #endif