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