Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-05 09:27:44

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