Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-01-07 10:16:37

0001 // Copyright (C) 2020 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
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; // we want an 8byte alignment on 32bit systems as well
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 // need this so that gcc >= 3.4 allocates 32 bits for Type
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     // primitives
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     // trivial, trivially-copyable or COW
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     // conditionally noexcept trivial or trivially-copyable
0281     // (most of these are noexcept on 64-bit)
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     // not noexcept
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); // converts to QString
0305 
0306 #if !defined(Q_CC_GHS)
0307     // GHS has an ICE with this code; use the simplified version below
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         // QVariant types are always registered (see fromMetaType())
0338         const QtPrivate::QMetaTypeInterface *mt = metaType().iface();
0339         if (!mt)
0340             return 0;
0341         int id = mt->typeId.loadRelaxed();
0342         // Q_ASSUME(id > 0);
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 // QT_CONFIG(regularexpression)
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         // If possible we reuse the current QVariant private.
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         /* needs is_copy_constructible for variants semantics, is_move_constructible so that moveConstruct works
0535           (but copy_constructible implies move_constructble, so don't bother checking)
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         // handle special cases
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(); // we want the type stored in QVariant to always be registered
0555 
0556         // We only try to move if the type is actually moveable and not if T is const
0557         // as in const int i; QVariant::fromValue(std::move(i));
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         // data() will detach from is_null, returning non-nullptr
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         // (const) data() will not detach from is_null, return nullptr
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     /* end */
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     // force compile error, prevent QVariant(bool) to be called
0681     inline QVariant(void *) = delete;
0682     // QVariant::Type is marked as \obsolete, but we don't want to
0683     // provide a constructor from its intended replacement,
0684     // QMetaType::Type, instead, because the idea behind these
0685     // constructors is flawed in the first place. But we also don't
0686     // want QVariant(QMetaType::String) to compile and falsely be an
0687     // int variant, so delete this constructor:
0688     QVariant(QMetaType::Type) = delete;
0689 
0690     // used to setup the QVariant internals for the "real" inplace ctor
0691     QVariant(std::in_place_t, QMetaType type);
0692     // helper for emplace
0693     void *prepareForEmplace(QMetaType type);
0694 
0695     // These constructors don't create QVariants of the type associated
0696     // with the enum, as expected, but they would create a QVariant of
0697     // type int with the value of the enum value.
0698     // Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for
0699     // example.
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     // force compile error when implicit conversion is not wanted
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             // If T in principle fits into the internal space, it may be using
0788             // it (depending on e.g. QTypeInfo, which, generally, can change
0789             // from version to version, so we need to check is_shared:
0790             if (!v.d.is_shared)
0791                 return std::move(*reinterpret_cast<T *>(v.d.data.data));
0792         }
0793         // Otherwise, it cannot possibly be using internal space:
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         // if the metatype doesn't match, but we want a QVariant, just return the current variant
0802         return v;
0803     } if constexpr (std::is_same_v<T,std::remove_const_t<std::remove_pointer_t<T>> const *>) {
0804         // moving a pointer is pointless, just do the same as the const & overload
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 // QT_MOC
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     // ### Qt7: Pass QMetaType as value rather than const ref.
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 // QVARIANT_H