Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-07 08:48:25

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 // Qt-Security score:critical reason:data-parser
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 } // namespace QtPrivate
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; // we want an 8byte alignment on 32bit systems as well
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 // need this so that gcc >= 3.4 allocates 32 bits for Type
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         // You can initialize a const reference from another one, but you can't assign to it.
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         // To be specialized for each Referred
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         // Assigning and initializing are different operations for references.
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             // swapping a reference is not swapping the referred item, but swapping its contents.
0310             QVariant tmp = *this;
0311             *this = std::move(b);
0312             b = std::move(tmp);
0313         }
0314 
0315         // To be specialized for each Referred
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     // primitives
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     // trivial, trivially-copyable or COW
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     // conditionally noexcept trivial or trivially-copyable
0412     // (most of these are noexcept on 64-bit)
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     // not noexcept
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); // converts to QString
0436 
0437 #if !defined(Q_CC_GHS)
0438     // GHS has an ICE with this code; use the simplified version below
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         // QVariant types are always registered (see fromMetaType())
0469         const QtPrivate::QMetaTypeInterface *mt = metaType().iface();
0470         if (!mt)
0471             return 0;
0472         int id = mt->typeId.loadRelaxed();
0473         // Q_ASSUME(id > 0);
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 // QT_CONFIG(regularexpression)
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         // If possible we reuse the current QVariant private.
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         /* needs is_copy_constructible for variants semantics, is_move_constructible so that moveConstruct works
0666           (but copy_constructible implies move_constructble, so don't bother checking)
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         // handle special cases
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(); // we want the type stored in QVariant to always be registered
0686 
0687         // We only try to move if the type is actually moveable and not if T is const
0688         // as in const int i; QVariant::fromValue(std::move(i));
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         // data() will detach from is_null, returning non-nullptr
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         // (const) data() will not detach from is_null, return nullptr
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     /* end */
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     // force compile error, prevent QVariant(bool) to be called
0812     inline QVariant(void *) = delete;
0813     // QVariant::Type is marked as \obsolete, but we don't want to
0814     // provide a constructor from its intended replacement,
0815     // QMetaType::Type, instead, because the idea behind these
0816     // constructors is flawed in the first place. But we also don't
0817     // want QVariant(QMetaType::String) to compile and falsely be an
0818     // int variant, so delete this constructor:
0819     QVariant(QMetaType::Type) = delete;
0820 
0821     // used to setup the QVariant internals for the "real" inplace ctor
0822     QVariant(std::in_place_t, QMetaType type);
0823     // helper for emplace
0824     void *prepareForEmplace(QMetaType type);
0825 
0826     // These constructors don't create QVariants of the type associated
0827     // with the enum, as expected, but they would create a QVariant of
0828     // type int with the value of the enum value.
0829     // Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for
0830     // example.
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     // force compile error when implicit conversion is not wanted
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             // If T in principle fits into the internal space, it may be using
0919             // it (depending on e.g. QTypeInfo, which, generally, can change
0920             // from version to version, so we need to check is_shared:
0921             if (!v.d.is_shared)
0922                 return std::move(*reinterpret_cast<T *>(v.d.data.data));
0923         }
0924         // Otherwise, it cannot possibly be using internal space:
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         // if the metatype doesn't match, but we want a QVariant, just return the current variant
0933         return v;
0934     } if constexpr (std::is_same_v<T,std::remove_const_t<std::remove_pointer_t<T>> const *>) {
0935         // moving a pointer is pointless, just do the same as the const & overload
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 // QT_MOC
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     // ### Qt7: Pass QMetaType as value rather than const ref.
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 // QVARIANT_H