Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:26:38

0001 // Copyright (C) 2021 The Qt Company Ltd.
0002 // Copyright (C) 2018 Intel Corporation.
0003 // Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
0004 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0005 
0006 #ifndef QMETATYPE_H
0007 #define QMETATYPE_H
0008 
0009 #include <QtCore/qglobal.h>
0010 #include <QtCore/qatomic.h>
0011 #include <QtCore/qbytearray.h>
0012 #include <QtCore/qcompare.h>
0013 #include <QtCore/qdatastream.h>
0014 #include <QtCore/qflags.h>
0015 #include <QtCore/qfloat16.h>
0016 #include <QtCore/qhashfunctions.h>
0017 #include <QtCore/qiterable.h>
0018 #ifndef QT_NO_QOBJECT
0019 #include <QtCore/qobjectdefs.h>
0020 #endif
0021 #include <QtCore/qscopeguard.h>
0022 #include <QtCore/qttypetraits.h>
0023 
0024 #include <array>
0025 #include <new>
0026 #include <vector>
0027 #include <list>
0028 #include <map>
0029 #include <functional>
0030 #include <optional>
0031 #include <QtCore/qxptype_traits.h>
0032 
0033 #ifdef Bool
0034 #error qmetatype.h must be included before any header file that defines Bool
0035 #endif
0036 
0037 QT_BEGIN_NAMESPACE
0038 
0039 // from qcborcommon.h
0040 enum class QCborSimpleType : quint8;
0041 
0042 template <typename T>
0043 struct QMetaTypeId2;
0044 
0045 template <typename T>
0046 inline constexpr int qMetaTypeId();
0047 
0048 // F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, RealType)
0049 #define QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(F)\
0050     F(Bool, 1, bool) \
0051     F(Int, 2, int) \
0052     F(UInt, 3, uint) \
0053     F(LongLong, 4, qlonglong) \
0054     F(ULongLong, 5, qulonglong) \
0055     F(Double, 6, double) \
0056     F(Long, 32, long) \
0057     F(Short, 33, short) \
0058     F(Char, 34, char) \
0059     F(Char16, 56, char16_t) \
0060     F(Char32, 57, char32_t) \
0061     F(ULong, 35, ulong) \
0062     F(UShort, 36, ushort) \
0063     F(UChar, 37, uchar) \
0064     F(Float, 38, float) \
0065     F(SChar, 40, signed char) \
0066     F(Nullptr, 51, std::nullptr_t) \
0067     F(QCborSimpleType, 52, QCborSimpleType) \
0068 
0069 #define QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)        \
0070     QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(F)   \
0071     F(Void, 43, void) \
0072 
0073 #define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)     \
0074     F(VoidStar, 31, void*) \
0075 
0076 #if QT_CONFIG(easingcurve)
0077 #define QT_FOR_EACH_STATIC_EASINGCURVE(F)\
0078     F(QEasingCurve, 29, QEasingCurve)
0079 #else
0080 #define QT_FOR_EACH_STATIC_EASINGCURVE(F)
0081 #endif
0082 
0083 #if QT_CONFIG(itemmodel)
0084 #define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)\
0085     F(QModelIndex, 42, QModelIndex) \
0086     F(QPersistentModelIndex, 50, QPersistentModelIndex)
0087 #else
0088 #define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
0089 #endif
0090 
0091 #if QT_CONFIG(regularexpression)
0092 #  define QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F) \
0093     F(QRegularExpression, 44, QRegularExpression)
0094 #else
0095 #  define QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F)
0096 #endif
0097 #ifndef QT_NO_VARIANT
0098 #  define QT_FOR_EACH_STATIC_QVARIANT(F) \
0099     F(QVariant, 41, QVariant)
0100 #else
0101 #  define QT_FOR_EACH_STATIC_QVARIANT(F)
0102 #endif
0103 
0104 #define QT_FOR_EACH_STATIC_CORE_CLASS(F)\
0105     F(QChar, 7, QChar) \
0106     F(QString, 10, QString) \
0107     F(QByteArray, 12, QByteArray) \
0108     F(QBitArray, 13, QBitArray) \
0109     F(QDate, 14, QDate) \
0110     F(QTime, 15, QTime) \
0111     F(QDateTime, 16, QDateTime) \
0112     F(QUrl, 17, QUrl) \
0113     F(QLocale, 18, QLocale) \
0114     F(QRect, 19, QRect) \
0115     F(QRectF, 20, QRectF) \
0116     F(QSize, 21, QSize) \
0117     F(QSizeF, 22, QSizeF) \
0118     F(QLine, 23, QLine) \
0119     F(QLineF, 24, QLineF) \
0120     F(QPoint, 25, QPoint) \
0121     F(QPointF, 26, QPointF) \
0122     QT_FOR_EACH_STATIC_EASINGCURVE(F) \
0123     F(QUuid, 30, QUuid) \
0124     QT_FOR_EACH_STATIC_QVARIANT(F) \
0125     QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F) \
0126     F(QJsonValue, 45, QJsonValue) \
0127     F(QJsonObject, 46, QJsonObject) \
0128     F(QJsonArray, 47, QJsonArray) \
0129     F(QJsonDocument, 48, QJsonDocument) \
0130     F(QCborValue, 53, QCborValue) \
0131     F(QCborArray, 54, QCborArray) \
0132     F(QCborMap, 55, QCborMap) \
0133     F(Float16, 63, qfloat16) \
0134     QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
0135 
0136 #define QT_FOR_EACH_STATIC_CORE_POINTER(F)\
0137     F(QObjectStar, 39, QObject*)
0138 
0139 #ifndef QT_NO_VARIANT
0140 #  define QT_FOR_EACH_STATIC_CORE_QVARIANT_TEMPLATE(F) \
0141     F(QVariantMap, 8, QVariantMap) \
0142     F(QVariantList, 9, QVariantList) \
0143     F(QVariantHash, 28, QVariantHash) \
0144     F(QVariantPair, 58, QVariantPair) \
0145     /**/
0146 #else
0147 #  define QT_FOR_EACH_STATIC_CORE_QVARIANT_TEMPLATE(F)
0148 #endif // QT_NO_VARIANT
0149 
0150 #define QT_FOR_EACH_STATIC_CORE_TEMPLATE(F) \
0151     QT_FOR_EACH_STATIC_CORE_QVARIANT_TEMPLATE(F) \
0152     F(QByteArrayList, 49, QByteArrayList) \
0153     F(QStringList, 11, QStringList)
0154 
0155 #if QT_CONFIG(shortcut)
0156 #define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)\
0157     F(QKeySequence, 0x100b, QKeySequence)
0158 #else
0159 #define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)
0160 #endif
0161 
0162 #define QT_FOR_EACH_STATIC_GUI_CLASS(F)\
0163     F(QFont, 0x1000, QFont) \
0164     F(QPixmap, 0x1001, QPixmap) \
0165     F(QBrush, 0x1002, QBrush) \
0166     F(QColor, 0x1003, QColor) \
0167     F(QPalette, 0x1004, QPalette) \
0168     F(QIcon, 0x1005, QIcon) \
0169     F(QImage, 0x1006, QImage) \
0170     F(QPolygon, 0x1007, QPolygon) \
0171     F(QRegion, 0x1008, QRegion) \
0172     F(QBitmap, 0x1009, QBitmap) \
0173     F(QCursor, 0x100a, QCursor) \
0174     QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F) \
0175     F(QPen, 0x100c, QPen) \
0176     F(QTextLength, 0x100d, QTextLength) \
0177     F(QTextFormat, 0x100e, QTextFormat) \
0178     F(QTransform, 0x1010, QTransform) \
0179     F(QMatrix4x4, 0x1011, QMatrix4x4) \
0180     F(QVector2D, 0x1012, QVector2D) \
0181     F(QVector3D, 0x1013, QVector3D) \
0182     F(QVector4D, 0x1014, QVector4D) \
0183     F(QQuaternion, 0x1015, QQuaternion) \
0184     F(QPolygonF, 0x1016, QPolygonF) \
0185     F(QColorSpace, 0x1017, QColorSpace) \
0186 
0187 
0188 #define QT_FOR_EACH_STATIC_WIDGETS_CLASS(F)\
0189     F(QSizePolicy, 0x2000, QSizePolicy) \
0190 
0191 // F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, AliasingType, "RealType")
0192 #define QT_FOR_EACH_STATIC_ALIAS_TYPE(F)\
0193     F(ULong, -1, ulong, "unsigned long") \
0194     F(UInt, -1, uint, "unsigned int") \
0195     F(UShort, -1, ushort, "unsigned short") \
0196     F(UChar, -1, uchar, "unsigned char") \
0197     F(LongLong, -1, qlonglong, "long long") \
0198     F(ULongLong, -1, qulonglong, "unsigned long long") \
0199     F(SChar, -1, signed char, "qint8") \
0200     F(UChar, -1, uchar, "quint8") \
0201     F(Short, -1, short, "qint16") \
0202     F(UShort, -1, ushort, "quint16") \
0203     F(Int, -1, int, "qint32") \
0204     F(UInt, -1, uint, "quint32") \
0205     F(LongLong, -1, qlonglong, "qint64") \
0206     F(ULongLong, -1, qulonglong, "quint64") \
0207     F(QByteArrayList, -1, QByteArrayList, "QList<QByteArray>") \
0208     F(QStringList, -1, QStringList, "QList<QString>") \
0209     QT_FOR_EACH_STATIC_VARIANT_ALIAS_TYPE(F)
0210 
0211 #ifndef QT_NO_VARIANT
0212 #define QT_FOR_EACH_STATIC_VARIANT_ALIAS_TYPE(F) \
0213     F(QVariantList, -1, QVariantList, "QList<QVariant>") \
0214     F(QVariantMap, -1, QVariantMap, "QMap<QString,QVariant>") \
0215     F(QVariantHash, -1, QVariantHash, "QHash<QString,QVariant>") \
0216     F(QVariantPair, -1, QVariantPair, "QPair<QVariant,QVariant>") \
0217     /**/
0218 #else
0219 #define QT_FOR_EACH_STATIC_VARIANT_ALIAS_TYPE(F)
0220 #endif
0221 
0222 #define QT_FOR_EACH_STATIC_TYPE(F)\
0223     QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
0224     QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\
0225     QT_FOR_EACH_STATIC_CORE_CLASS(F)\
0226     QT_FOR_EACH_STATIC_CORE_POINTER(F)\
0227     QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)\
0228     QT_FOR_EACH_STATIC_GUI_CLASS(F)\
0229     QT_FOR_EACH_STATIC_WIDGETS_CLASS(F)\
0230 
0231 #define QT_DEFINE_METATYPE_ID(TypeName, Id, Name) \
0232     TypeName = Id,
0233 
0234 #define QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(F) \
0235     F(QList) \
0236     F(QQueue) \
0237     F(QStack) \
0238     F(QSet) \
0239     /*end*/
0240 
0241 #define QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(F) \
0242     F(QHash, class) \
0243     F(QMap, class)
0244 
0245 #define QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(F) \
0246     F(QSharedPointer) \
0247     F(QWeakPointer) \
0248     F(QPointer)
0249 
0250 class QDataStream;
0251 struct QMetaObject;
0252 
0253 namespace QtPrivate
0254 {
0255 
0256 class QMetaTypeInterface;
0257 
0258 // MSVC is the only supported compiler that includes the type of a variable in
0259 // its mangled form, so it's not binary-compatible to drop the const in
0260 // QMetaTypeInterfaceWrapper::metaType for it, which means we must keep the
0261 // mutable field until Qt 7.
0262 #if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) || !defined(Q_CC_MSVC)
0263 #  define QMTI_MUTABLE
0264 using NonConstMetaTypeInterface = QMetaTypeInterface;
0265 #else
0266 #  define QMTI_MUTABLE mutable
0267 using NonConstMetaTypeInterface = const QMetaTypeInterface;
0268 #endif
0269 
0270 class QMetaTypeInterface
0271 {
0272 public:
0273 
0274     /* Revision: Can increase if new field are added, or if semantics changes
0275        0: Initial Revision
0276        1: the meaning of the NeedsDestruction flag changed
0277     */
0278     static inline constexpr ushort CurrentRevision = 1;
0279 
0280     ushort revision;
0281     ushort alignment;
0282     uint size;
0283     uint flags;
0284     QMTI_MUTABLE QBasicAtomicInt typeId;
0285 
0286     using MetaObjectFn = const QMetaObject *(*)(const QMetaTypeInterface *);
0287     MetaObjectFn metaObjectFn;
0288 
0289     const char *name;
0290 
0291     using DefaultCtrFn = void (*)(const QMetaTypeInterface *, void *);
0292     DefaultCtrFn defaultCtr;
0293     using CopyCtrFn = void (*)(const QMetaTypeInterface *, void *, const void *);
0294     CopyCtrFn copyCtr;
0295     using MoveCtrFn = void (*)(const QMetaTypeInterface *, void *, void *);
0296     MoveCtrFn moveCtr;
0297     using DtorFn = void (*)(const QMetaTypeInterface *, void *);
0298     DtorFn dtor;
0299     using EqualsFn = bool (*)(const QMetaTypeInterface *, const void *, const void *);
0300     EqualsFn equals;
0301     using LessThanFn = bool (*)(const QMetaTypeInterface *, const void *, const void *);
0302     LessThanFn lessThan;
0303     using DebugStreamFn = void (*)(const QMetaTypeInterface *, QDebug &, const void *);
0304     DebugStreamFn debugStream;
0305     using DataStreamOutFn = void (*)(const QMetaTypeInterface *, QDataStream &, const void *);
0306     DataStreamOutFn dataStreamOut;
0307     using DataStreamInFn = void (*)(const QMetaTypeInterface *, QDataStream &, void *);
0308     DataStreamInFn dataStreamIn;
0309 
0310     using LegacyRegisterOp = void (*)();
0311     LegacyRegisterOp legacyRegisterOp;
0312 };
0313 #undef QMTI_MUTABLE
0314 
0315 /*!
0316     This template is used for implicit conversion from type From to type To.
0317     \internal
0318 */
0319 template<typename From, typename To>
0320 To convertImplicit(const From& from)
0321 {
0322     return from;
0323 }
0324 
0325     template<typename T, bool>
0326     struct SequentialValueTypeIsMetaType;
0327     template<typename T, bool>
0328     struct AssociativeValueTypeIsMetaType;
0329     template<typename T, bool>
0330     struct IsMetaTypePair;
0331     template<typename, typename>
0332     struct MetaTypeSmartPointerHelper;
0333 
0334     template<typename T>
0335     struct IsEnumOrFlags : std::disjunction<std::is_enum<T>, IsQFlags<T>> {};
0336 }  // namespace QtPrivate
0337 
0338 class Q_CORE_EXPORT QMetaType {
0339 public:
0340 #ifndef Q_QDOC
0341     // The code that actually gets compiled.
0342     enum Type {
0343         // these are merged with QVariant
0344         QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID)
0345 
0346         FirstCoreType = Bool,
0347         LastCoreType = Float16,
0348         FirstGuiType = QFont,
0349         LastGuiType = QColorSpace,
0350         FirstWidgetsType = QSizePolicy,
0351         LastWidgetsType = QSizePolicy,
0352         HighestInternalId = LastWidgetsType,
0353 
0354         QReal = sizeof(qreal) == sizeof(double) ? Double : Float,
0355 
0356         UnknownType = 0,
0357         User = 65536
0358     };
0359 #else
0360     // If we are using QDoc it fakes the Type enum looks like this.
0361     enum Type {
0362         UnknownType = 0, Bool = 1, Int = 2, UInt = 3, LongLong = 4, ULongLong = 5,
0363         Double = 6, Long = 32, Short = 33, Char = 34, ULong = 35, UShort = 36,
0364         UChar = 37, Float = 38,
0365         VoidStar = 31,
0366         QChar = 7, QString = 10, QStringList = 11, QByteArray = 12,
0367         QBitArray = 13, QDate = 14, QTime = 15, QDateTime = 16, QUrl = 17,
0368         QLocale = 18, QRect = 19, QRectF = 20, QSize = 21, QSizeF = 22,
0369         QLine = 23, QLineF = 24, QPoint = 25, QPointF = 26,
0370         QEasingCurve = 29, QUuid = 30, QVariant = 41, QModelIndex = 42,
0371         QPersistentModelIndex = 50, QRegularExpression = 44,
0372         QJsonValue = 45, QJsonObject = 46, QJsonArray = 47, QJsonDocument = 48,
0373         QByteArrayList = 49, QObjectStar = 39, SChar = 40,
0374         Void = 43,
0375         Nullptr = 51,
0376         QVariantMap = 8, QVariantList = 9, QVariantHash = 28, QVariantPair = 58,
0377         QCborSimpleType = 52, QCborValue = 53, QCborArray = 54, QCborMap = 55,
0378         Char16 = 56, Char32 = 57,
0379         Int128 = 59, UInt128 = 60, Float128 = 61, BFloat16 = 62, Float16 = 63,
0380 
0381         // Gui types
0382         QFont = 0x1000, QPixmap = 0x1001, QBrush = 0x1002, QColor = 0x1003, QPalette = 0x1004,
0383         QIcon = 0x1005, QImage = 0x1006, QPolygon = 0x1007, QRegion = 0x1008, QBitmap = 0x1009,
0384         QCursor = 0x100a, QKeySequence = 0x100b, QPen = 0x100c, QTextLength = 0x100d, QTextFormat = 0x100e,
0385         QTransform = 0x1010, QMatrix4x4 = 0x1011, QVector2D = 0x1012,
0386         QVector3D = 0x1013, QVector4D = 0x1014, QQuaternion = 0x1015, QPolygonF = 0x1016, QColorSpace = 0x1017,
0387 
0388         // Widget types
0389         QSizePolicy = 0x2000,
0390 
0391         // Start-point for client-code types:
0392         User = 65536
0393     };
0394 #endif
0395 
0396     enum TypeFlag {
0397         NeedsConstruction = 0x1,
0398         NeedsDestruction = 0x2,
0399         RelocatableType = 0x4,
0400 #if QT_DEPRECATED_SINCE(6, 0)
0401         MovableType Q_DECL_ENUMERATOR_DEPRECATED_X("Use RelocatableType instead.") = RelocatableType,
0402 #endif
0403         PointerToQObject = 0x8,
0404         IsEnumeration = 0x10,
0405         SharedPointerToQObject = 0x20,
0406         WeakPointerToQObject = 0x40,
0407         TrackingPointerToQObject = 0x80,
0408         IsUnsignedEnumeration = 0x100,
0409         IsGadget = 0x200,
0410         PointerToGadget = 0x400,
0411         IsPointer = 0x800,
0412         IsQmlList =0x1000, // used in the QML engine to recognize QQmlListProperty<T> and list<T>
0413         IsConst = 0x2000,
0414         // since 6.5:
0415         NeedsCopyConstruction = 0x4000,
0416         NeedsMoveConstruction = 0x8000,
0417     };
0418     Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
0419 
0420     static void registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, QMetaType type);
0421 
0422 #if QT_DEPRECATED_SINCE(6, 0)
0423     QT_DEPRECATED_VERSION_6_0
0424     static int type(const char *typeName)
0425     { return QMetaType::fromName(typeName).id(); }
0426     QT_DEPRECATED_VERSION_6_0
0427     static int type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName)
0428     { return QMetaType::fromName(typeName).id(); }
0429     QT_DEPRECATED_VERSION_6_0
0430     static const char *typeName(int type)
0431     { return QMetaType(type).name(); }
0432     QT_DEPRECATED_VERSION_6_0
0433     static int sizeOf(int type)
0434     { return int(QMetaType(type).sizeOf()); }
0435     QT_DEPRECATED_VERSION_6_0
0436     static TypeFlags typeFlags(int type)
0437     { return QMetaType(type).flags(); }
0438     QT_DEPRECATED_VERSION_6_0
0439     static const QMetaObject *metaObjectForType(int type)
0440     { return QMetaType(type).metaObject(); }
0441     QT_DEPRECATED_VERSION_6_0
0442     static void *create(int type, const void *copy = nullptr)
0443     { return QMetaType(type).create(copy); }
0444     QT_DEPRECATED_VERSION_6_0
0445     static void destroy(int type, void *data)
0446     { return QMetaType(type).destroy(data); }
0447     QT_DEPRECATED_VERSION_6_0
0448     static void *construct(int type, void *where, const void *copy)
0449     { return QMetaType(type).construct(where, copy); }
0450     QT_DEPRECATED_VERSION_6_0
0451     static void destruct(int type, void *where)
0452     { return QMetaType(type).destruct(where); }
0453 #endif
0454     static bool isRegistered(int type);
0455 
0456     explicit QMetaType(int type);
0457     explicit constexpr QMetaType(const QtPrivate::QMetaTypeInterface *d) : d_ptr(d) {}
0458     constexpr QMetaType() = default;
0459 
0460 #if QT_CORE_REMOVED_SINCE(6, 9)
0461     bool isValid() const;
0462     bool isRegistered() const;
0463 #endif
0464     constexpr bool isValid(QT6_DECL_NEW_OVERLOAD) const noexcept;
0465     inline bool isRegistered(QT6_DECL_NEW_OVERLOAD) const noexcept;
0466     void registerType() const
0467     {
0468         // "register" is a reserved keyword
0469         registerHelper();
0470     }
0471 #if QT_CORE_REMOVED_SINCE(6, 1) || defined(Q_QDOC)
0472     int id() const;
0473 #else
0474     // ### Qt 7: Remove traces of out of line version
0475     // unused int parameter is used to avoid ODR violation
0476     int id(int = 0) const
0477     {
0478         return registerHelper();
0479     }
0480 #endif
0481     constexpr qsizetype sizeOf() const;
0482     constexpr qsizetype alignOf() const;
0483     constexpr TypeFlags flags() const;
0484     constexpr const QMetaObject *metaObject() const;
0485     constexpr const char *name() const;
0486 
0487     void *create(const void *copy = nullptr) const;
0488     void destroy(void *data) const;
0489     void *construct(void *where, const void *copy = nullptr) const;
0490     void destruct(void *data) const;
0491     QPartialOrdering compare(const void *lhs, const void *rhs) const;
0492     bool equals(const void *lhs, const void *rhs) const;
0493 
0494     bool isDefaultConstructible() const noexcept { return d_ptr && isDefaultConstructible(d_ptr); }
0495     bool isCopyConstructible() const noexcept { return d_ptr && isCopyConstructible(d_ptr); }
0496     bool isMoveConstructible() const noexcept { return d_ptr && isMoveConstructible(d_ptr); }
0497     bool isDestructible() const noexcept { return d_ptr && isDestructible(d_ptr); }
0498     bool isEqualityComparable() const;
0499     bool isOrdered() const;
0500 
0501 #ifndef QT_NO_DATASTREAM
0502     bool save(QDataStream &stream, const void *data) const;
0503     bool load(QDataStream &stream, void *data) const;
0504     bool hasRegisteredDataStreamOperators() const;
0505 
0506 #if QT_DEPRECATED_SINCE(6, 0)
0507     QT_DEPRECATED_VERSION_6_0
0508     static bool save(QDataStream &stream, int type, const void *data)
0509     { return QMetaType(type).save(stream, data); }
0510     QT_DEPRECATED_VERSION_6_0
0511     static bool load(QDataStream &stream, int type, void *data)
0512     { return QMetaType(type).load(stream, data); }
0513 #endif
0514 #endif
0515 
0516     QMetaType underlyingType() const;
0517 
0518     template<typename T>
0519     constexpr static QMetaType fromType();
0520     static QMetaType fromName(QByteArrayView name);
0521 private:
0522     friend bool comparesEqual(const QMetaType &lhs,
0523                               const QMetaType &rhs)
0524     {
0525         if (lhs.d_ptr == rhs.d_ptr)
0526             return true;
0527         if (!lhs.d_ptr || !rhs.d_ptr)
0528             return false; // one type is undefined, the other is defined
0529         // avoid id call if we already have the id
0530         const int aId = lhs.id();
0531         const int bId = rhs.id();
0532         return aId == bId;
0533     }
0534     Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(QMetaType)
0535 #ifndef QT_NO_DEBUG_STREAM
0536 private:
0537     friend Q_CORE_EXPORT QDebug operator<<(QDebug d, QMetaType m);
0538 public:
0539     bool debugStream(QDebug& dbg, const void *rhs);
0540     bool hasRegisteredDebugStreamOperator() const;
0541 
0542 #if QT_DEPRECATED_SINCE(6, 0)
0543     QT_DEPRECATED_VERSION_6_0
0544     static bool debugStream(QDebug& dbg, const void *rhs, int typeId)
0545     { return QMetaType(typeId).debugStream(dbg, rhs); }
0546     template<typename T>
0547     QT_DEPRECATED_VERSION_6_0
0548     static bool hasRegisteredDebugStreamOperator()
0549     { return QMetaType::fromType<T>().hasRegisteredDebugStreamOperator(); }
0550     QT_DEPRECATED_VERSION_6_0
0551     static bool hasRegisteredDebugStreamOperator(int typeId)
0552     { return QMetaType(typeId).hasRegisteredDebugStreamOperator(); }
0553 #endif
0554 #endif
0555 
0556     // type erased converter function
0557     using ConverterFunction = std::function<bool(const void *src, void *target)>;
0558 
0559     // type erased mutable view, primarily for containers
0560     using MutableViewFunction = std::function<bool(void *src, void *target)>;
0561 
0562     // implicit conversion supported like double -> float
0563     template<typename From, typename To>
0564     static bool registerConverter()
0565     {
0566         return registerConverter<From, To>(QtPrivate::convertImplicit<From, To>);
0567     }
0568 
0569     // member function as in "QString QFont::toString() const"
0570     template<typename From, typename To>
0571     static bool registerConverter(To(From::*function)() const)
0572     {
0573         static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
0574             "QMetaType::registerConverter: At least one of the types must be a custom type.");
0575 
0576         const QMetaType fromType = QMetaType::fromType<From>();
0577         const QMetaType toType = QMetaType::fromType<To>();
0578         auto converter = [function](const void *from, void *to) -> bool {
0579             const From *f = static_cast<const From *>(from);
0580             To *t = static_cast<To *>(to);
0581             *t = (f->*function)();
0582             return true;
0583         };
0584         return registerConverterImpl<From, To>(converter, fromType, toType);
0585     }
0586 
0587     // member function
0588     template<typename From, typename To>
0589     static bool registerMutableView(To(From::*function)())
0590     {
0591         static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
0592             "QMetaType::registerMutableView: At least one of the types must be a custom type.");
0593 
0594         const QMetaType fromType = QMetaType::fromType<From>();
0595         const QMetaType toType = QMetaType::fromType<To>();
0596         auto view = [function](void *from, void *to) -> bool {
0597             From *f = static_cast<From *>(from);
0598             To *t = static_cast<To *>(to);
0599             *t = (f->*function)();
0600             return true;
0601         };
0602         return registerMutableViewImpl<From, To>(view, fromType, toType);
0603     }
0604 
0605     // member function as in "double QString::toDouble(bool *ok = nullptr) const"
0606     template<typename From, typename To>
0607     static bool registerConverter(To(From::*function)(bool*) const)
0608     {
0609         static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
0610             "QMetaType::registerConverter: At least one of the types must be a custom type.");
0611 
0612         const QMetaType fromType = QMetaType::fromType<From>();
0613         const QMetaType toType = QMetaType::fromType<To>();
0614         auto converter = [function](const void *from, void *to) -> bool {
0615             const From *f = static_cast<const From *>(from);
0616             To *t = static_cast<To *>(to);
0617             bool result = true;
0618             *t = (f->*function)(&result);
0619             if (!result)
0620                 *t = To();
0621             return result;
0622         };
0623         return registerConverterImpl<From, To>(converter, fromType, toType);
0624     }
0625 
0626     // functor or function pointer
0627     template<typename From, typename To, typename UnaryFunction>
0628     static bool registerConverter(UnaryFunction function)
0629     {
0630         static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
0631             "QMetaType::registerConverter: At least one of the types must be a custom type.");
0632 
0633         const QMetaType fromType = QMetaType::fromType<From>();
0634         const QMetaType toType = QMetaType::fromType<To>();
0635         auto converter = [function = std::move(function)](const void *from, void *to) -> bool {
0636             const From *f = static_cast<const From *>(from);
0637             To *t = static_cast<To *>(to);
0638             auto &&r = function(*f);
0639             if constexpr (std::is_same_v<q20::remove_cvref_t<decltype(r)>, std::optional<To>>) {
0640                 if (!r)
0641                     return false;
0642                 *t = *std::forward<decltype(r)>(r);
0643             } else {
0644                 *t = std::forward<decltype(r)>(r);
0645             }
0646             return true;
0647         };
0648         return registerConverterImpl<From, To>(std::move(converter), fromType, toType);
0649     }
0650 
0651     // functor or function pointer
0652     template<typename From, typename To, typename UnaryFunction>
0653     static bool registerMutableView(UnaryFunction function)
0654     {
0655         static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
0656             "QMetaType::registerMutableView: At least one of the types must be a custom type.");
0657 
0658         const QMetaType fromType = QMetaType::fromType<From>();
0659         const QMetaType toType = QMetaType::fromType<To>();
0660         auto view = [function = std::move(function)](void *from, void *to) -> bool {
0661             From *f = static_cast<From *>(from);
0662             To *t = static_cast<To *>(to);
0663             *t = function(*f);
0664             return true;
0665         };
0666         return registerMutableViewImpl<From, To>(std::move(view), fromType, toType);
0667     }
0668 
0669 private:
0670     template<typename From, typename To>
0671     static bool registerConverterImpl(ConverterFunction converter, QMetaType fromType, QMetaType toType)
0672     {
0673         if (registerConverterFunction(std::move(converter), fromType, toType)) {
0674             static const auto unregister = qScopeGuard([=] {
0675                 unregisterConverterFunction(fromType, toType);
0676             });
0677             return true;
0678         } else {
0679             return false;
0680         }
0681     }
0682 
0683     template<typename From, typename To>
0684     static bool registerMutableViewImpl(MutableViewFunction view, QMetaType fromType, QMetaType toType)
0685     {
0686         if (registerMutableViewFunction(std::move(view), fromType, toType)) {
0687             static const auto unregister = qScopeGuard([=] {
0688                unregisterMutableViewFunction(fromType, toType);
0689             });
0690             return true;
0691         } else {
0692             return false;
0693         }
0694     }
0695 public:
0696 
0697     static bool convert(QMetaType fromType, const void *from, QMetaType toType, void *to);
0698     static bool canConvert(QMetaType fromType, QMetaType toType);
0699 
0700     static bool view(QMetaType fromType, void *from, QMetaType toType, void *to);
0701     static bool canView(QMetaType fromType, QMetaType toType);
0702 #if QT_DEPRECATED_SINCE(6, 0)
0703     QT_DEPRECATED_VERSION_6_0
0704     static bool convert(const void *from, int fromTypeId, void *to, int toTypeId)
0705     { return convert(QMetaType(fromTypeId), from, QMetaType(toTypeId), to); }
0706     QT_DEPRECATED_VERSION_6_0
0707     static bool compare(const void *lhs, const void *rhs, int typeId, int *result)
0708     {
0709         QMetaType t(typeId);
0710         auto c = t.compare(lhs, rhs);
0711         if (c == QPartialOrdering::Unordered) {
0712             *result = 0;
0713             return false;
0714         } else if (c == QPartialOrdering::Less) {
0715             *result = -1;
0716             return true;
0717         } else if (c == QPartialOrdering::Equivalent) {
0718             *result = 0;
0719             return true;
0720         } else {
0721             *result = 1;
0722             return true;
0723         }
0724     }
0725     QT_DEPRECATED_VERSION_6_0
0726     static bool equals(const void *lhs, const void *rhs, int typeId, int *result)
0727     {
0728         QMetaType t(typeId);
0729         if (!t.isEqualityComparable())
0730             return false;
0731         *result = t.equals(lhs, rhs) ? 0 : -1;
0732         return true;
0733     }
0734 #endif
0735 
0736     template<typename From, typename To>
0737     static bool hasRegisteredConverterFunction()
0738     {
0739         return hasRegisteredConverterFunction(
0740                     QMetaType::fromType<From>(), QMetaType::fromType<To>());
0741     }
0742 
0743     static bool hasRegisteredConverterFunction(QMetaType fromType, QMetaType toType);
0744 
0745     template<typename From, typename To>
0746     static bool hasRegisteredMutableViewFunction()
0747     {
0748         return hasRegisteredMutableViewFunction(
0749                     QMetaType::fromType<From>(), QMetaType::fromType<To>());
0750     }
0751 
0752     static bool hasRegisteredMutableViewFunction(QMetaType fromType, QMetaType toType);
0753 
0754 #ifndef Q_QDOC
0755     template<typename, bool> friend struct QtPrivate::SequentialValueTypeIsMetaType;
0756     template<typename, bool> friend struct QtPrivate::AssociativeValueTypeIsMetaType;
0757     template<typename, bool> friend struct QtPrivate::IsMetaTypePair;
0758     template<typename, typename> friend struct QtPrivate::MetaTypeSmartPointerHelper;
0759 #endif
0760     static bool registerConverterFunction(const ConverterFunction &f, QMetaType from, QMetaType to);
0761     static void unregisterConverterFunction(QMetaType from, QMetaType to);
0762 
0763     static bool registerMutableViewFunction(const MutableViewFunction &f, QMetaType from, QMetaType to);
0764     static void unregisterMutableViewFunction(QMetaType from, QMetaType to);
0765 
0766     static void unregisterMetaType(QMetaType type);
0767 
0768 #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
0769     constexpr const QtPrivate::QMetaTypeInterface *iface() { return d_ptr; }
0770 #endif
0771     constexpr const QtPrivate::QMetaTypeInterface *iface() const { return d_ptr; }
0772 
0773 private:
0774     static bool isDefaultConstructible(const QtPrivate::QMetaTypeInterface *) noexcept Q_DECL_PURE_FUNCTION;
0775     static bool isCopyConstructible(const QtPrivate::QMetaTypeInterface *) noexcept Q_DECL_PURE_FUNCTION;
0776     static bool isMoveConstructible(const QtPrivate::QMetaTypeInterface *) noexcept Q_DECL_PURE_FUNCTION;
0777     static bool isDestructible(const QtPrivate::QMetaTypeInterface *) noexcept Q_DECL_PURE_FUNCTION;
0778 
0779 #if QT_CORE_REMOVED_SINCE(6, 5)
0780     int idHelper() const;
0781 #endif
0782     static int registerHelper(const QtPrivate::QMetaTypeInterface *iface);
0783     int registerHelper() const
0784     {
0785         if (d_ptr) {
0786             if (int id = d_ptr->typeId.loadRelaxed())
0787                 return id;
0788             return registerHelper(d_ptr);
0789         }
0790         return 0;
0791     }
0792 
0793     friend int qRegisterMetaType(QMetaType meta);
0794 
0795     friend class QVariant;
0796     const QtPrivate::QMetaTypeInterface *d_ptr = nullptr;
0797 };
0798 
0799 #undef QT_DEFINE_METATYPE_ID
0800 
0801 Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags)
0802 
0803 #define QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(C, F)  \
0804     }                                               \
0805     Q_DECLARE_TYPEINFO(QtMetaTypePrivate:: C, (F)); \
0806     namespace QtMetaTypePrivate {
0807 
0808 
0809 namespace QtMetaTypePrivate {
0810 
0811 class QPairVariantInterfaceImpl
0812 {
0813 public:
0814     const void *_pair;
0815     QMetaType _metaType_first;
0816     QMetaType _metaType_second;
0817 
0818     typedef void (*getFunc)(const void * const *p, void *);
0819 
0820     getFunc _getFirst;
0821     getFunc _getSecond;
0822 
0823     template<class T>
0824     static void getFirstImpl(const void * const *pair, void *dataPtr)
0825     { *static_cast<typename T::first_type *>(dataPtr) = static_cast<const T*>(*pair)->first; }
0826     template<class T>
0827     static void getSecondImpl(const void * const *pair, void *dataPtr)
0828     { *static_cast<typename T::second_type *>(dataPtr) = static_cast<const T*>(*pair)->second; }
0829 
0830 public:
0831     template<class T> QPairVariantInterfaceImpl(const T*p)
0832       : _pair(p)
0833       , _metaType_first(QMetaType::fromType<typename T::first_type>())
0834       , _metaType_second(QMetaType::fromType<typename T::second_type>())
0835       , _getFirst(getFirstImpl<T>)
0836       , _getSecond(getSecondImpl<T>)
0837     {
0838     }
0839 
0840     constexpr QPairVariantInterfaceImpl()
0841       : _pair(nullptr)
0842       , _getFirst(nullptr)
0843       , _getSecond(nullptr)
0844     {
0845     }
0846 
0847     inline void first(void *dataPtr) const { _getFirst(&_pair, dataPtr); }
0848     inline void second(void *dataPtr) const { _getSecond(&_pair, dataPtr); }
0849 };
0850 QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QPairVariantInterfaceImpl, Q_RELOCATABLE_TYPE)
0851 
0852 template<typename From>
0853 struct QPairVariantInterfaceConvertFunctor;
0854 
0855 template<typename T, typename U>
0856 struct QPairVariantInterfaceConvertFunctor<std::pair<T, U> >
0857 {
0858     QPairVariantInterfaceImpl operator()(const std::pair<T, U>& f) const
0859     {
0860         return QPairVariantInterfaceImpl(&f);
0861     }
0862 };
0863 
0864 }
0865 
0866 class QObject;
0867 
0868 #define QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER(Name) \
0869     template <class T> class Name; \
0870 
0871 QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER)
0872 
0873 namespace QtPrivate
0874 {
0875     namespace detail {
0876     template<typename T, typename ODR_VIOLATION_PREVENTER>
0877     struct is_complete_helper
0878     {
0879         template<typename U>
0880         static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
0881         static auto check(...) -> std::false_type;
0882         using type = decltype(check(static_cast<T *>(nullptr)));
0883     };
0884     } // namespace detail
0885 
0886     template <typename T, typename ODR_VIOLATION_PREVENTER>
0887     struct is_complete : detail::is_complete_helper<std::remove_reference_t<T>, ODR_VIOLATION_PREVENTER>::type {};
0888 
0889     template <typename T> struct MetatypeDecay              { using type = T; };
0890     template <typename T> struct MetatypeDecay<const T>     { using type = T; };
0891     template <typename T> struct MetatypeDecay<const T &>   { using type = T; };
0892 
0893     template <typename T> struct IsPointerDeclaredOpaque  :
0894             std::disjunction<std::is_member_pointer<T>,
0895                              std::is_function<std::remove_pointer_t<T>>>
0896     {};
0897     template <> struct IsPointerDeclaredOpaque<void *>      : std::true_type {};
0898     template <> struct IsPointerDeclaredOpaque<const void *> : std::true_type {};
0899 
0900     // Note: this does not check that T = U* isn't pointing to a
0901     // forward-declared type. You may want to combine with
0902     // checkTypeIsSuitableForMetaType().
0903     template<typename T>
0904     struct IsPointerToTypeDerivedFromQObject
0905     {
0906         enum { Value = false };
0907     };
0908 
0909     // Specialize to avoid sizeof(void) warning
0910     template<>
0911     struct IsPointerToTypeDerivedFromQObject<void*>
0912     {
0913         enum { Value = false };
0914     };
0915     template<>
0916     struct IsPointerToTypeDerivedFromQObject<const void*>
0917     {
0918         enum { Value = false };
0919     };
0920     template<>
0921     struct IsPointerToTypeDerivedFromQObject<QObject*>
0922     {
0923         enum { Value = true };
0924     };
0925 
0926     template<typename T>
0927     struct IsPointerToTypeDerivedFromQObject<T*>
0928     {
0929         typedef qint8 yes_type;
0930         typedef qint64 no_type;
0931 
0932 #ifndef QT_NO_QOBJECT
0933         static yes_type checkType(QObject* );
0934         static yes_type checkType(const QObject* );
0935 #endif
0936         static no_type checkType(...);
0937         enum { Value = sizeof(checkType(static_cast<T*>(nullptr))) == sizeof(yes_type) };
0938     };
0939 
0940     template<typename T, typename Enable = void>
0941     struct IsGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; };
0942 
0943     template<typename T>
0944     struct IsGadgetHelper<T, typename T::QtGadgetHelper>
0945     {
0946         template <typename X>
0947         static char checkType(void (X::*)());
0948         static void *checkType(void (T::*)());
0949         enum {
0950             IsRealGadget = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *),
0951             IsGadgetOrDerivedFrom = true
0952         };
0953     };
0954 
0955     template <typename T>
0956     using IsRealGadget = std::bool_constant<IsGadgetHelper<T>::IsRealGadget>;
0957 
0958     template<typename T, typename Enable = void>
0959     struct IsPointerToGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; };
0960 
0961     template<typename T>
0962     struct IsPointerToGadgetHelper<T*, typename T::QtGadgetHelper>
0963     {
0964         using BaseType = T;
0965         template <typename X>
0966         static char checkType(void (X::*)());
0967         static void *checkType(void (T::*)());
0968         enum {
0969             IsRealGadget = !IsPointerToTypeDerivedFromQObject<T*>::Value && sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *),
0970             IsGadgetOrDerivedFrom = !IsPointerToTypeDerivedFromQObject<T*>::Value
0971         };
0972     };
0973 
0974 
0975     template<typename T> char qt_getEnumMetaObject(const T&);
0976 
0977     template<typename T>
0978     struct IsQEnumHelper {
0979         static const T &declval();
0980         // If the type was declared with Q_ENUM, the friend qt_getEnumMetaObject() declared in the
0981         // Q_ENUM macro will be chosen by ADL, and the return type will be QMetaObject*.
0982         // Otherwise the chosen overload will be the catch all template function
0983         // qt_getEnumMetaObject(T) which returns 'char'
0984         enum { Value = sizeof(qt_getEnumMetaObject(declval())) == sizeof(QMetaObject*) };
0985     };
0986     template<> struct IsQEnumHelper<void> { enum { Value = false }; };
0987 
0988     template<typename T, typename Enable = void>
0989     struct MetaObjectForType
0990     {
0991         static constexpr const QMetaObject *value() { return nullptr; }
0992         using MetaObjectFn = const QMetaObject *(*)(const QMetaTypeInterface *);
0993         static constexpr MetaObjectFn metaObjectFunction = nullptr;
0994     };
0995 #ifndef QT_NO_QOBJECT
0996     template<typename T>
0997     struct MetaObjectForType<T*, typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value>::type>
0998     {
0999         static constexpr const QMetaObject *value() { return &T::staticMetaObject; }
1000         static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return &T::staticMetaObject; }
1001     };
1002     template<typename T>
1003     struct MetaObjectForType<T, std::enable_if_t<
1004         std::disjunction_v<
1005             std::bool_constant<IsGadgetHelper<T>::IsGadgetOrDerivedFrom>,
1006             std::is_base_of<QObject, T>
1007         >
1008     >>
1009     {
1010         static constexpr const QMetaObject *value() { return &T::staticMetaObject; }
1011         static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return &T::staticMetaObject; }
1012     };
1013     template<typename T>
1014     struct MetaObjectForType<T, typename std::enable_if<IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
1015     {
1016         static constexpr const QMetaObject *value()
1017         {
1018             return &IsPointerToGadgetHelper<T>::BaseType::staticMetaObject;
1019         }
1020         static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return value(); }
1021     };
1022     template<typename T>
1023     struct MetaObjectForType<T, typename std::enable_if<IsQEnumHelper<T>::Value>::type >
1024     {
1025         static constexpr const QMetaObject *value() { return qt_getEnumMetaObject(T()); }
1026         static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return value(); }
1027     };
1028 #endif
1029 
1030     template<typename T>
1031     struct IsSharedPointerToTypeDerivedFromQObject
1032     {
1033         enum { Value = false };
1034     };
1035 
1036     template<typename T>
1037     struct IsSharedPointerToTypeDerivedFromQObject<QSharedPointer<T> > : IsPointerToTypeDerivedFromQObject<T*>
1038     {
1039     };
1040 
1041     template<typename T>
1042     struct IsWeakPointerToTypeDerivedFromQObject
1043     {
1044         enum { Value = false };
1045     };
1046 
1047     template<typename T>
1048     struct IsWeakPointerToTypeDerivedFromQObject<QWeakPointer<T> > : IsPointerToTypeDerivedFromQObject<T*>
1049     {
1050     };
1051 
1052     template<typename T>
1053     struct IsTrackingPointerToTypeDerivedFromQObject
1054     {
1055         enum { Value = false };
1056     };
1057 
1058     template<typename T>
1059     struct IsTrackingPointerToTypeDerivedFromQObject<QPointer<T> >
1060     {
1061         enum { Value = true };
1062     };
1063 
1064     template<typename T>
1065     struct IsSequentialContainer
1066     {
1067         enum { Value = false };
1068     };
1069 
1070     template<typename T>
1071     struct IsAssociativeContainer
1072     {
1073         enum { Value = false };
1074     };
1075 
1076     template<typename T, bool = QtPrivate::IsSequentialContainer<T>::Value>
1077     struct SequentialContainerTransformationHelper
1078     {
1079         static bool registerConverter()
1080         {
1081             return false;
1082         }
1083 
1084         static bool registerMutableView()
1085         {
1086             return false;
1087         }
1088     };
1089 
1090     template<typename T, bool = QMetaTypeId2<typename T::value_type>::Defined>
1091     struct SequentialValueTypeIsMetaType
1092     {
1093         static bool registerConverter()
1094         {
1095             return false;
1096         }
1097 
1098         static bool registerMutableView()
1099         {
1100             return false;
1101         }
1102     };
1103 
1104     template<typename T>
1105     struct SequentialContainerTransformationHelper<T, true> : SequentialValueTypeIsMetaType<T>
1106     {
1107     };
1108 
1109     template<typename T, bool = QtPrivate::IsAssociativeContainer<T>::Value>
1110     struct AssociativeContainerTransformationHelper
1111     {
1112         static bool registerConverter()
1113         {
1114             return false;
1115         }
1116 
1117         static bool registerMutableView()
1118         {
1119             return false;
1120         }
1121     };
1122 
1123     template<typename T, bool = QMetaTypeId2<typename T::key_type>::Defined>
1124     struct AssociativeKeyTypeIsMetaType
1125     {
1126         static bool registerConverter()
1127         {
1128             return false;
1129         }
1130 
1131         static bool registerMutableView()
1132         {
1133             return false;
1134         }
1135     };
1136 
1137     template<typename T, bool = QMetaTypeId2<typename T::mapped_type>::Defined>
1138     struct AssociativeMappedTypeIsMetaType
1139     {
1140         static bool registerConverter()
1141         {
1142             return false;
1143         }
1144 
1145         static bool registerMutableView()
1146         {
1147             return false;
1148         }
1149     };
1150 
1151     template<typename T>
1152     struct AssociativeContainerTransformationHelper<T, true> : AssociativeKeyTypeIsMetaType<T>
1153     {
1154     };
1155 
1156     template<typename T, bool = QMetaTypeId2<typename T::first_type>::Defined
1157                                 && QMetaTypeId2<typename T::second_type>::Defined>
1158     struct IsMetaTypePair
1159     {
1160         static bool registerConverter()
1161         {
1162             return false;
1163         }
1164     };
1165 
1166     template<typename T>
1167     struct IsMetaTypePair<T, true>
1168     {
1169         inline static bool registerConverter();
1170     };
1171 
1172     template<typename T>
1173     struct IsPair
1174     {
1175         static bool registerConverter()
1176         {
1177             return false;
1178         }
1179     };
1180     template<typename T, typename U>
1181     struct IsPair<std::pair<T, U> > : IsMetaTypePair<std::pair<T, U> > {};
1182 
1183     template<typename T>
1184     struct MetaTypePairHelper : IsPair<T> {};
1185 
1186     template<typename T, typename = void>
1187     struct MetaTypeSmartPointerHelper
1188     {
1189         static bool registerConverter() { return false; }
1190     };
1191 
1192 #if QT_CONFIG(future)
1193     template<typename T>
1194     struct MetaTypeQFutureHelper
1195     {
1196         static bool registerConverter() { return false; }
1197     };
1198 #endif
1199 
1200     template <typename X> static constexpr bool checkTypeIsSuitableForMetaType()
1201     {
1202         using T = typename MetatypeDecay<X>::type;
1203         static_assert(is_complete<T, void>::value || std::is_void_v<T>,
1204                 "Meta Types must be fully defined");
1205         static_assert(!std::is_reference_v<T>,
1206                 "Meta Types cannot be non-const references or rvalue references.");
1207         if constexpr (std::is_pointer_v<T> && !IsPointerDeclaredOpaque<T>::value) {
1208             using Pointed = std::remove_pointer_t<T>;
1209             static_assert(is_complete<Pointed, void>::value,
1210                     "Pointer Meta Types must either point to fully-defined types "
1211                     "or be declared with Q_DECLARE_OPAQUE_POINTER(T *)");
1212         }
1213         return true;
1214     }
1215 
1216     Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type);
1217 } // namespace QtPrivate
1218 
1219 template <typename T, int =
1220     QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject :
1221     QtPrivate::IsRealGadget<T>::value                      ? QMetaType::IsGadget :
1222     QtPrivate::IsPointerToGadgetHelper<T>::IsRealGadget    ? QMetaType::PointerToGadget :
1223     QtPrivate::IsQEnumHelper<T>::Value                     ? QMetaType::IsEnumeration : 0>
1224 struct QMetaTypeIdQObject
1225 {
1226     enum {
1227         Defined = 0
1228     };
1229 };
1230 
1231 template <typename T>
1232 struct QMetaTypeId : public QMetaTypeIdQObject<T>
1233 {
1234 };
1235 
1236 template <typename T>
1237 struct QMetaTypeId2
1238 {
1239     using NameAsArrayType = void;
1240     enum { Defined = QMetaTypeId<T>::Defined, IsBuiltIn=false };
1241     static inline constexpr int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }
1242 };
1243 
1244 template <typename T>
1245 struct QMetaTypeId2<const T&> : QMetaTypeId2<T> {};
1246 
1247 template <typename T>
1248 struct QMetaTypeId2<T&>
1249 {
1250     using NameAsArrayType = void;
1251     enum { Defined = false, IsBuiltIn = false };
1252     static inline constexpr int qt_metatype_id() { return 0; }
1253 };
1254 
1255 namespace QtPrivate {
1256     template <typename T, bool Defined = QMetaTypeId2<T>::Defined>
1257     struct QMetaTypeIdHelper {
1258         static inline constexpr int qt_metatype_id()
1259         { return QMetaTypeId2<T>::qt_metatype_id(); }
1260     };
1261     template <typename T> struct QMetaTypeIdHelper<T, false> {
1262         static inline constexpr int qt_metatype_id()
1263         { return -1; }
1264     };
1265 
1266     // Function pointers don't derive from QObject
1267     template <typename Result, typename... Args>
1268     struct IsPointerToTypeDerivedFromQObject<Result(*)(Args...)> { enum { Value = false }; };
1269 
1270     template<typename T>
1271     inline constexpr bool IsQmlListType = false;
1272 
1273     template<typename T, bool = std::is_enum<T>::value>
1274     constexpr bool IsUnsignedEnum = false;
1275     template<typename T>
1276     constexpr bool IsUnsignedEnum<T, true> = !std::is_signed_v<std::underlying_type_t<T>>;
1277 
1278     template<typename T, bool defined>
1279     struct MetaTypeDefinedHelper
1280     {
1281         enum DefinedType { Defined = defined };
1282     };
1283 
1284     template<typename SmartPointer>
1285     struct QSmartPointerConvertFunctor
1286     {
1287         QObject* operator()(const SmartPointer &p) const
1288         {
1289             return p.operator->();
1290         }
1291     };
1292 
1293     // hack to delay name lookup to instantiation time by making
1294     // EnableInternalData a dependent name:
1295     template <typename T>
1296     struct EnableInternalDataWrap;
1297 
1298     template<typename T>
1299     struct QSmartPointerConvertFunctor<QWeakPointer<T> >
1300     {
1301         QObject* operator()(const QWeakPointer<T> &p) const
1302         {
1303             return QtPrivate::EnableInternalDataWrap<T>::internalData(p);
1304         }
1305     };
1306 }
1307 
1308 template <typename T>
1309 int qRegisterNormalizedMetaTypeImplementation(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName)
1310 {
1311 #ifndef QT_NO_QOBJECT
1312     Q_ASSERT_X(normalizedTypeName == QMetaObject::normalizedType(normalizedTypeName.constData()),
1313                "qRegisterNormalizedMetaType",
1314                "qRegisterNormalizedMetaType was called with a not normalized type name, "
1315                "please call qRegisterMetaType instead.");
1316 #endif
1317 
1318     const QMetaType metaType = QMetaType::fromType<T>();
1319     const int id = metaType.id();
1320 
1321     QtPrivate::SequentialContainerTransformationHelper<T>::registerConverter();
1322     QtPrivate::SequentialContainerTransformationHelper<T>::registerMutableView();
1323     QtPrivate::AssociativeContainerTransformationHelper<T>::registerConverter();
1324     QtPrivate::AssociativeContainerTransformationHelper<T>::registerMutableView();
1325     QtPrivate::MetaTypePairHelper<T>::registerConverter();
1326     QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter();
1327 #if QT_CONFIG(future)
1328     QtPrivate::MetaTypeQFutureHelper<T>::registerConverter();
1329 #endif
1330 
1331     if (normalizedTypeName != metaType.name())
1332         QMetaType::registerNormalizedTypedef(normalizedTypeName, metaType);
1333 
1334     return id;
1335 }
1336 
1337 // This primary template calls the -Implementation, like all other specialisations should.
1338 // But the split allows to
1339 // - in a header:
1340 //   - define a specialization of this template calling an out-of-line function
1341 //     (QT_DECL_METATYPE_EXTERN{,_TAGGED})
1342 // - in the .cpp file:
1343 //   - define the out-of-line wrapper to call the -Implementation
1344 //     (QT_IMPL_METATYPE_EXTERN{,_TAGGED})
1345 // The _TAGGED variants let you choose a tag (must be a C identifier) to disambiguate
1346 // the out-of-line function; the non-_TAGGED variants use the passed class name as tag.
1347 template <typename T>
1348 int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName)
1349 {
1350     return qRegisterNormalizedMetaTypeImplementation<T>(normalizedTypeName);
1351 }
1352 
1353 #define QT_DECL_METATYPE_EXTERN_TAGGED(TYPE, TAG, EXPORT) \
1354     QT_BEGIN_NAMESPACE \
1355     EXPORT int qRegisterNormalizedMetaType_ ## TAG (const QByteArray &); \
1356     template <> inline int qRegisterNormalizedMetaType< TYPE >(const QByteArray &name) \
1357     { return qRegisterNormalizedMetaType_ ## TAG (name); } \
1358     QT_END_NAMESPACE \
1359     Q_DECLARE_METATYPE(TYPE) \
1360     /* end */
1361 #define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG) \
1362     int qRegisterNormalizedMetaType_ ## TAG (const QByteArray &name) \
1363     { return qRegisterNormalizedMetaTypeImplementation< TYPE >(name); } \
1364     /* end */
1365 #define QT_DECL_METATYPE_EXTERN(TYPE, EXPORT) \
1366     QT_DECL_METATYPE_EXTERN_TAGGED(TYPE, TYPE, EXPORT)
1367 #define QT_IMPL_METATYPE_EXTERN(TYPE) \
1368     QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TYPE)
1369 
1370 template <typename T>
1371 int qRegisterMetaType(const char *typeName)
1372 {
1373 #ifdef QT_NO_QOBJECT
1374     QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = typeName;
1375 #else
1376     QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
1377 #endif
1378     return qRegisterNormalizedMetaType<T>(normalizedTypeName);
1379 }
1380 
1381 template <typename T>
1382 inline constexpr int qMetaTypeId()
1383 {
1384     if constexpr (bool(QMetaTypeId2<T>::IsBuiltIn)) {
1385         // this has the same result as the below code, but avoids asking the
1386         // compiler to load a global variable whose value we know at compile
1387         // time
1388         return QMetaTypeId2<T>::MetaType;
1389     } else {
1390         return QMetaType::fromType<T>().id();
1391     }
1392 }
1393 
1394 template <typename T>
1395 inline constexpr int qRegisterMetaType()
1396 {
1397     int id = qMetaTypeId<T>();
1398     return id;
1399 }
1400 
1401 inline int qRegisterMetaType(QMetaType meta)
1402 {
1403     return meta.registerHelper();
1404 }
1405 
1406 #ifndef QT_NO_QOBJECT
1407 template <typename T>
1408 struct QMetaTypeIdQObject<T*, QMetaType::PointerToQObject>
1409 {
1410     enum {
1411         Defined = 1
1412     };
1413 
1414     static int qt_metatype_id()
1415     {
1416         Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1417         if (const int id = metatype_id.loadAcquire())
1418             return id;
1419         const char *const cName = T::staticMetaObject.className();
1420         QByteArray typeName;
1421         typeName.reserve(strlen(cName) + 1);
1422         typeName.append(cName).append('*');
1423         const int newId = qRegisterNormalizedMetaType<T *>(typeName);
1424         metatype_id.storeRelease(newId);
1425         return newId;
1426     }
1427 };
1428 
1429 template <typename T>
1430 struct QMetaTypeIdQObject<T, QMetaType::IsGadget>
1431 {
1432     enum {
1433         Defined = std::is_default_constructible<T>::value
1434     };
1435 
1436     static int qt_metatype_id()
1437     {
1438         Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1439         if (const int id = metatype_id.loadAcquire())
1440             return id;
1441         const char *const cName = T::staticMetaObject.className();
1442         const int newId = qRegisterNormalizedMetaType<T>(cName);
1443         metatype_id.storeRelease(newId);
1444         return newId;
1445     }
1446 };
1447 
1448 template <typename T>
1449 struct QMetaTypeIdQObject<T*, QMetaType::PointerToGadget>
1450 {
1451     enum {
1452         Defined = 1
1453     };
1454 
1455     static int qt_metatype_id()
1456     {
1457         Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1458         if (const int id = metatype_id.loadAcquire())
1459             return id;
1460         const char *const cName = T::staticMetaObject.className();
1461         QByteArray typeName;
1462         typeName.reserve(strlen(cName) + 1);
1463         typeName.append(cName).append('*');
1464         const int newId = qRegisterNormalizedMetaType<T *>(typeName);
1465         metatype_id.storeRelease(newId);
1466         return newId;
1467     }
1468 };
1469 
1470 template <typename T>
1471 struct QMetaTypeIdQObject<T, QMetaType::IsEnumeration>
1472 {
1473     enum {
1474         Defined = 1
1475     };
1476 
1477     static int qt_metatype_id()
1478     {
1479         Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1480         if (const int id = metatype_id.loadAcquire())
1481             return id;
1482         const char *eName = qt_getEnumName(T());
1483         const char *cName = qt_getEnumMetaObject(T())->className();
1484         QByteArray typeName;
1485         typeName.reserve(strlen(cName) + 2 + strlen(eName));
1486         typeName.append(cName).append("::").append(eName);
1487         const int newId = qRegisterNormalizedMetaType<T>(typeName);
1488         metatype_id.storeRelease(newId);
1489         return newId;
1490     }
1491 };
1492 #endif
1493 
1494 #define Q_DECLARE_OPAQUE_POINTER(POINTER)                               \
1495     QT_BEGIN_NAMESPACE namespace QtPrivate {                            \
1496     template <> struct IsPointerDeclaredOpaque<POINTER>                 \
1497         : std::true_type {};                                            \
1498     } QT_END_NAMESPACE                                                  \
1499     /**/
1500 
1501 #ifndef Q_MOC_RUN
1502 #define Q_DECLARE_METATYPE(TYPE) Q_DECLARE_METATYPE_IMPL(TYPE)
1503 #define Q_DECLARE_METATYPE_IMPL(TYPE)                                   \
1504     QT_BEGIN_NAMESPACE                                                  \
1505     template <>                                                         \
1506     struct QMetaTypeId< TYPE >                                          \
1507     {                                                                   \
1508         enum { Defined = 1 };                                           \
1509         static_assert(QtPrivate::checkTypeIsSuitableForMetaType<TYPE>());   \
1510         static int qt_metatype_id()                                     \
1511             {                                                           \
1512                 Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
1513                 if (const int id = metatype_id.loadAcquire())           \
1514                     return id;                                          \
1515                 constexpr auto arr = QtPrivate::typenameHelper<TYPE>(); \
1516                 auto name = arr.data();                                 \
1517                 if (QByteArrayView(name) == (#TYPE)) {                  \
1518                     const int id = qRegisterNormalizedMetaType<TYPE>(name); \
1519                     metatype_id.storeRelease(id);                       \
1520                     return id;                                          \
1521                 }                                                       \
1522                 const int newId = qRegisterMetaType< TYPE >(#TYPE);     \
1523                 metatype_id.storeRelease(newId);                        \
1524                 return newId;                                           \
1525             }                                                           \
1526     };                                                                  \
1527     QT_END_NAMESPACE
1528 #endif // Q_MOC_RUN
1529 
1530 #define Q_DECLARE_BUILTIN_METATYPE(TYPE, METATYPEID, NAME) \
1531     QT_BEGIN_NAMESPACE \
1532     template<> struct QMetaTypeId2<NAME> \
1533     { \
1534         using NameAsArrayType = std::array<char, sizeof(#NAME)>; \
1535         enum { Defined = 1, IsBuiltIn = true, MetaType = METATYPEID };   \
1536         static inline constexpr int qt_metatype_id() { return METATYPEID; } \
1537         static constexpr NameAsArrayType nameAsArray = { #NAME }; \
1538     }; \
1539     QT_END_NAMESPACE
1540 
1541 #define QT_FORWARD_DECLARE_STATIC_TYPES_ITER(TypeName, TypeId, Name) \
1542     class Name;
1543 
1544 QT_FOR_EACH_STATIC_CORE_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1545 QT_FOR_EACH_STATIC_GUI_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1546 QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1547 
1548 #undef QT_FORWARD_DECLARE_STATIC_TYPES_ITER
1549 
1550 #define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE) \
1551 QT_BEGIN_NAMESPACE \
1552 template <typename T> \
1553 struct QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \
1554 { \
1555     enum { \
1556         Defined = QMetaTypeId2<T>::Defined \
1557     }; \
1558     static int qt_metatype_id() \
1559     { \
1560         Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
1561         if (const int id = metatype_id.loadRelaxed()) \
1562             return id; \
1563         const char *tName = QMetaType::fromType<T>().name(); \
1564         Q_ASSERT(tName); \
1565         const size_t tNameLen = qstrlen(tName); \
1566         QByteArray typeName; \
1567         typeName.reserve(sizeof(#SINGLE_ARG_TEMPLATE) + 1 + tNameLen + 1 + 1); \
1568         typeName.append(#SINGLE_ARG_TEMPLATE, int(sizeof(#SINGLE_ARG_TEMPLATE)) - 1) \
1569             .append('<').append(tName, tNameLen); \
1570         typeName.append('>'); \
1571         const int newId = qRegisterNormalizedMetaType< SINGLE_ARG_TEMPLATE<T> >(typeName); \
1572         metatype_id.storeRelease(newId); \
1573         return newId; \
1574     } \
1575 }; \
1576 QT_END_NAMESPACE
1577 
1578 #define Q_DECLARE_METATYPE_TEMPLATE_2ARG(DOUBLE_ARG_TEMPLATE) \
1579 QT_BEGIN_NAMESPACE \
1580 template<typename T, typename U> \
1581 struct QMetaTypeId< DOUBLE_ARG_TEMPLATE<T, U> > \
1582 { \
1583     enum { \
1584         Defined = QMetaTypeId2<T>::Defined && QMetaTypeId2<U>::Defined \
1585     }; \
1586     static int qt_metatype_id() \
1587     { \
1588         Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
1589         if (const int id = metatype_id.loadAcquire()) \
1590             return id; \
1591         const char *tName = QMetaType::fromType<T>().name(); \
1592         const char *uName = QMetaType::fromType<U>().name(); \
1593         Q_ASSERT(tName); \
1594         Q_ASSERT(uName); \
1595         const size_t tNameLen = qstrlen(tName); \
1596         const size_t uNameLen = qstrlen(uName); \
1597         QByteArray typeName; \
1598         typeName.reserve(sizeof(#DOUBLE_ARG_TEMPLATE) + 1 + tNameLen + 1 + uNameLen + 1 + 1); \
1599         typeName.append(#DOUBLE_ARG_TEMPLATE, int(sizeof(#DOUBLE_ARG_TEMPLATE)) - 1) \
1600             .append('<').append(tName, tNameLen).append(',').append(uName, uNameLen); \
1601         typeName.append('>'); \
1602         const int newId = qRegisterNormalizedMetaType< DOUBLE_ARG_TEMPLATE<T, U> >(typeName); \
1603         metatype_id.storeRelease(newId); \
1604         return newId; \
1605     } \
1606 }; \
1607 QT_END_NAMESPACE
1608 
1609 namespace QtPrivate {
1610 
1611 template<typename T, bool /* isSharedPointerToQObjectDerived */ = false>
1612 struct SharedPointerMetaTypeIdHelper
1613 {
1614     enum {
1615         Defined = 0
1616     };
1617     static int qt_metatype_id()
1618     {
1619         return -1;
1620     }
1621 };
1622 
1623 }
1624 
1625 #define Q_DECLARE_SMART_POINTER_METATYPE(SMART_POINTER) \
1626 QT_BEGIN_NAMESPACE \
1627 namespace QtPrivate { \
1628 template<typename T> \
1629 struct SharedPointerMetaTypeIdHelper<SMART_POINTER<T>, true> \
1630 { \
1631     enum { \
1632         Defined = 1 \
1633     }; \
1634     static int qt_metatype_id() \
1635     { \
1636         Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
1637         if (const int id = metatype_id.loadAcquire()) \
1638             return id; \
1639         const char * const cName = T::staticMetaObject.className(); \
1640         QByteArray typeName; \
1641         typeName.reserve(sizeof(#SMART_POINTER) + 1 + strlen(cName) + 1); \
1642         typeName.append(#SMART_POINTER, int(sizeof(#SMART_POINTER)) - 1) \
1643             .append('<').append(cName).append('>'); \
1644         const int newId = qRegisterNormalizedMetaType< SMART_POINTER<T> >(typeName); \
1645         metatype_id.storeRelease(newId); \
1646         return newId; \
1647     } \
1648 }; \
1649 template<typename T> \
1650 struct MetaTypeSmartPointerHelper<SMART_POINTER<T> , \
1651         typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value && !std::is_const_v<T>>::type> \
1652 { \
1653     static bool registerConverter() \
1654     { \
1655         const QMetaType to = QMetaType(QMetaType::QObjectStar); \
1656         if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<SMART_POINTER<T>>(), to)) { \
1657             QtPrivate::QSmartPointerConvertFunctor<SMART_POINTER<T> > o; \
1658             return QMetaType::registerConverter<SMART_POINTER<T>, QObject*>(o); \
1659         } \
1660         return true; \
1661     } \
1662 }; \
1663 } \
1664 template <typename T> \
1665 struct QMetaTypeId< SMART_POINTER<T> > \
1666     : QtPrivate::SharedPointerMetaTypeIdHelper< SMART_POINTER<T>, \
1667                                                 QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value> \
1668 { \
1669 };\
1670 QT_END_NAMESPACE
1671 
1672 #define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(SINGLE_ARG_TEMPLATE) \
1673     QT_BEGIN_NAMESPACE \
1674     namespace QtPrivate { \
1675     template<typename T> \
1676     struct IsSequentialContainer<SINGLE_ARG_TEMPLATE<T> > \
1677     { \
1678         enum { Value = true }; \
1679     }; \
1680     } \
1681     QT_END_NAMESPACE \
1682     Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE)
1683 
1684 #define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER(TEMPLATENAME) \
1685     Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(TEMPLATENAME)
1686 
1687 QT_END_NAMESPACE
1688 
1689 QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER)
1690 
1691 #undef Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER
1692 
1693 Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::vector)
1694 Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::list)
1695 
1696 #define Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(TEMPLATENAME) \
1697     QT_BEGIN_NAMESPACE \
1698     namespace QtPrivate { \
1699     template<typename T, typename U> \
1700     struct IsAssociativeContainer<TEMPLATENAME<T, U> > \
1701     { \
1702         enum { Value = true }; \
1703     }; \
1704     } \
1705     QT_END_NAMESPACE \
1706     Q_DECLARE_METATYPE_TEMPLATE_2ARG(TEMPLATENAME)
1707 
1708 Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QHash)
1709 Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QMap)
1710 Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(std::map)
1711 
1712 Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::pair)
1713 
1714 #define Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER(TEMPLATENAME) \
1715     Q_DECLARE_SMART_POINTER_METATYPE(TEMPLATENAME)
1716 
1717 QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER)
1718 
1719 QT_BEGIN_NAMESPACE
1720 
1721 #undef Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER
1722 
1723 QT_END_NAMESPACE
1724 
1725 QT_FOR_EACH_STATIC_TYPE(Q_DECLARE_BUILTIN_METATYPE)
1726 
1727 
1728 QT_BEGIN_NAMESPACE
1729 
1730 namespace QtPrivate {
1731 // out-of-line helpers to reduce template code bloat ("SCARY") and improve compile times:
1732 Q_CORE_EXPORT bool hasRegisteredConverterFunctionToPairVariantInterface(QMetaType m);
1733 Q_CORE_EXPORT bool hasRegisteredConverterFunctionToIterableMetaSequence(QMetaType m);
1734 Q_CORE_EXPORT bool hasRegisteredMutableViewFunctionToIterableMetaSequence(QMetaType m);
1735 Q_CORE_EXPORT bool hasRegisteredConverterFunctionToIterableMetaAssociation(QMetaType m);
1736 Q_CORE_EXPORT bool hasRegisteredMutableViewFunctionToIterableMetaAssociation(QMetaType m);
1737 }
1738 
1739 template <typename T>
1740 inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter()
1741 {
1742     if (!QtPrivate::hasRegisteredConverterFunctionToPairVariantInterface(QMetaType::fromType<T>())) {
1743         QtMetaTypePrivate::QPairVariantInterfaceConvertFunctor<T> o;
1744         return QMetaType::registerConverter<T, QtMetaTypePrivate::QPairVariantInterfaceImpl>(o);
1745     }
1746     return true;
1747 }
1748 
1749 namespace QtPrivate {
1750 
1751 template<typename From>
1752 struct QSequentialIterableConvertFunctor
1753 {
1754     QIterable<QMetaSequence> operator()(const From &f) const
1755     {
1756         return QIterable<QMetaSequence>(QMetaSequence::fromContainer<From>(), &f);
1757     }
1758 };
1759 
1760 template<typename From>
1761 struct QSequentialIterableMutableViewFunctor
1762 {
1763     QIterable<QMetaSequence> operator()(From &f) const
1764     {
1765         return QIterable<QMetaSequence>(QMetaSequence::fromContainer<From>(), &f);
1766     }
1767 };
1768 
1769 template<typename T>
1770 struct SequentialValueTypeIsMetaType<T, true>
1771 {
1772     static bool registerConverter()
1773     {
1774         if (!QtPrivate::hasRegisteredConverterFunctionToIterableMetaSequence(QMetaType::fromType<T>())) {
1775             QSequentialIterableConvertFunctor<T> o;
1776             return QMetaType::registerConverter<T, QIterable<QMetaSequence>>(o);
1777         }
1778         return true;
1779     }
1780 
1781     static bool registerMutableView()
1782     {
1783         if (!QtPrivate::hasRegisteredMutableViewFunctionToIterableMetaSequence(QMetaType::fromType<T>())) {
1784             QSequentialIterableMutableViewFunctor<T> o;
1785             return QMetaType::registerMutableView<T, QIterable<QMetaSequence>>(o);
1786         }
1787         return true;
1788     }
1789 };
1790 
1791 template<typename From>
1792 struct QAssociativeIterableConvertFunctor
1793 {
1794     QIterable<QMetaAssociation> operator()(const From &f) const
1795     {
1796         return QIterable<QMetaAssociation>(QMetaAssociation::fromContainer<From>(), &f);
1797     }
1798 };
1799 
1800 template<typename From>
1801 struct QAssociativeIterableMutableViewFunctor
1802 {
1803     QIterable<QMetaAssociation> operator()(From &f) const
1804     {
1805         return QIterable<QMetaAssociation>(QMetaAssociation::fromContainer<From>(), &f);
1806     }
1807 };
1808 
1809 // Mapped type can be omitted, for example in case of a set.
1810 // However, if it is available, we want to instantiate the metatype here.
1811 template<typename T>
1812 struct AssociativeKeyTypeIsMetaType<T, true> : AssociativeMappedTypeIsMetaType<T>
1813 {
1814     static bool registerConverter()
1815     {
1816         if (!QtPrivate::hasRegisteredConverterFunctionToIterableMetaAssociation(QMetaType::fromType<T>())) {
1817             QAssociativeIterableConvertFunctor<T> o;
1818             return QMetaType::registerConverter<T, QIterable<QMetaAssociation>>(o);
1819         }
1820         return true;
1821     }
1822 
1823     static bool registerMutableView()
1824     {
1825         if (!QtPrivate::hasRegisteredMutableViewFunctionToIterableMetaAssociation(QMetaType::fromType<T>())) {
1826             QAssociativeIterableMutableViewFunctor<T> o;
1827             return QMetaType::registerMutableView<T, QIterable<QMetaAssociation>>(o);
1828         }
1829         return true;
1830     }
1831 };
1832 
1833 struct QTypeNormalizer
1834 {
1835     char *output;
1836     int len = 0;
1837     char last = 0;
1838 
1839 private:
1840     static constexpr bool is_ident_char(char s)
1841     {
1842         return ((s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z') || (s >= '0' && s <= '9')
1843                 || s == '_');
1844     }
1845     static constexpr bool is_space(char s) { return (s == ' ' || s == '\t' || s == '\n'); }
1846     static constexpr bool is_number(char s) { return s >= '0' && s <= '9'; }
1847     static constexpr bool starts_with_token(const char *b, const char *e, const char *token,
1848                                             bool msvcKw = false)
1849     {
1850         while (b != e && *token && *b == *token) {
1851             b++;
1852             token++;
1853         }
1854         if (*token)
1855             return false;
1856 #ifdef Q_CC_MSVC
1857         /// On MSVC, keywords like class or struct are not separated with spaces in constexpr
1858         /// context
1859         if (msvcKw && !is_ident_char(*b))
1860             return true;
1861 #endif
1862         Q_UNUSED(msvcKw);
1863         return b == e || !is_ident_char(*b);
1864     }
1865     static constexpr bool skipToken(const char *&x, const char *e, const char *token,
1866                                     bool msvcKw = false)
1867     {
1868         if (!starts_with_token(x, e, token, msvcKw))
1869             return false;
1870         while (*token++)
1871             x++;
1872         while (x != e && is_space(*x))
1873             x++;
1874         return true;
1875     }
1876     static constexpr const char *skipString(const char *x, const char *e)
1877     {
1878         char delim = *x;
1879         x++;
1880         while (x != e && *x != delim) {
1881             if (*x == '\\') {
1882                 x++;
1883                 if (x == e)
1884                     return e;
1885             }
1886             x++;
1887         }
1888         if (x != e)
1889             x++;
1890         return x;
1891     }
1892     static constexpr const char *skipTemplate(const char *x, const char *e, bool stopAtComa = false)
1893     {
1894         int scopeDepth = 0;
1895         int templateDepth = 0;
1896         while (x != e) {
1897             switch (*x) {
1898             case '<':
1899                 if (!scopeDepth)
1900                     templateDepth++;
1901                 break;
1902             case ',':
1903                 if (stopAtComa && !scopeDepth && !templateDepth)
1904                     return x;
1905                 break;
1906             case '>':
1907                 if (!scopeDepth)
1908                     if (--templateDepth < 0)
1909                         return x;
1910                 break;
1911             case '(':
1912             case '[':
1913             case '{':
1914                 scopeDepth++;
1915                 break;
1916             case '}':
1917             case ']':
1918             case ')':
1919                 scopeDepth--;
1920                 break;
1921             case '\'':
1922                 if (is_number(x[-1]))
1923                     break;
1924                 Q_FALLTHROUGH();
1925             case '\"':
1926                 x = skipString(x, e);
1927                 continue;
1928             }
1929             x++;
1930         }
1931         return x;
1932     }
1933 
1934     constexpr void append(char x)
1935     {
1936         last = x;
1937         len++;
1938         if (output)
1939             *output++ = x;
1940     }
1941 
1942     constexpr void replaceLast(char x)
1943     {
1944         last = x;
1945         if (output)
1946             *(output - 1) = x;
1947     }
1948 
1949     constexpr void appendStr(const char *x)
1950     {
1951         while (*x)
1952             append(*x++);
1953     }
1954 
1955     constexpr void normalizeIntegerTypes(const char *&begin, const char *end)
1956     {
1957         int numLong = 0;
1958         int numSigned = 0;
1959         int numUnsigned = 0;
1960         int numInt = 0;
1961         int numShort = 0;
1962         int numChar = 0;
1963         while (begin < end) {
1964             if (skipToken(begin, end, "long")) {
1965                 numLong++;
1966                 continue;
1967             }
1968             if (skipToken(begin, end, "int")) {
1969                 numInt++;
1970                 continue;
1971             }
1972             if (skipToken(begin, end, "short")) {
1973                 numShort++;
1974                 continue;
1975             }
1976             if (skipToken(begin, end, "unsigned")) {
1977                 numUnsigned++;
1978                 continue;
1979             }
1980             if (skipToken(begin, end, "signed")) {
1981                 numSigned++;
1982                 continue;
1983             }
1984             if (skipToken(begin, end, "char")) {
1985                 numChar++;
1986                 continue;
1987             }
1988 #ifdef Q_CC_MSVC
1989             if (skipToken(begin, end, "__int64")) {
1990                 numLong = 2;
1991                 continue;
1992             }
1993 #endif
1994             break;
1995         }
1996         if (numLong == 2)
1997             append('q'); // q(u)longlong
1998         if (numSigned && numChar)
1999             appendStr("signed ");
2000         else if (numUnsigned)
2001             appendStr("u");
2002         if (numChar)
2003             appendStr("char");
2004         else if (numShort)
2005             appendStr("short");
2006         else if (numLong == 1)
2007             appendStr("long");
2008         else if (numLong == 2)
2009             appendStr("longlong");
2010         else if (numUnsigned || numSigned || numInt)
2011             appendStr("int");
2012     }
2013 
2014     constexpr void skipStructClassOrEnum(const char *&begin, const char *end)
2015     {
2016         // discard 'struct', 'class', and 'enum'; they are optional
2017         // and we don't want them in the normalized signature
2018         skipToken(begin, end, "struct", true) || skipToken(begin, end, "class", true)
2019                 || skipToken(begin, end, "enum", true);
2020     }
2021 
2022     constexpr void skipQtNamespace(const char *&begin, const char *end)
2023     {
2024 #ifdef QT_NAMESPACE
2025         const char *nsbeg = begin;
2026         if (skipToken(nsbeg, end, QT_STRINGIFY(QT_NAMESPACE)) && nsbeg + 2 < end && nsbeg[0] == ':'
2027             && nsbeg[1] == ':') {
2028             begin = nsbeg + 2;
2029             while (begin != end && is_space(*begin))
2030                 begin++;
2031         }
2032 #else
2033         Q_UNUSED(begin);
2034         Q_UNUSED(end);
2035 #endif
2036     }
2037 
2038 public:
2039 #if defined(Q_CC_CLANG) || defined (Q_CC_GNU)
2040     // this is much simpler than the full type normalization below
2041     // the reason is that the signature returned by Q_FUNC_INFO is already
2042     // normalized to the largest degree, and we need to do only small adjustments
2043     constexpr int normalizeTypeFromSignature(const char *begin, const char *end)
2044     {
2045         // bail out if there is an anonymous struct
2046         std::string_view name(begin, end-begin);
2047 #if defined (Q_CC_CLANG)
2048         if (name.find("anonymous ") != std::string_view::npos)
2049             return normalizeType(begin, end);
2050 #endif
2051         if (name.find("unnamed ") != std::string_view::npos)
2052             return normalizeType(begin, end);
2053         while (begin < end) {
2054             if (*begin == ' ') {
2055                 if (last == ',' || last == '>' || last == '<' || last == '*' || last == '&') {
2056                     ++begin;
2057                     continue;
2058                 }
2059             }
2060             if (last == ' ') {
2061                 if (*begin == '*' || *begin == '&' || *begin == '(') {
2062                     replaceLast(*begin);
2063                     ++begin;
2064                     continue;
2065                 }
2066             }
2067             if (!is_ident_char(last)) {
2068                 skipStructClassOrEnum(begin, end);
2069                 if (begin == end)
2070                     break;
2071 
2072                 skipQtNamespace(begin, end);
2073                 if (begin == end)
2074                     break;
2075 
2076                 normalizeIntegerTypes(begin, end);
2077                 if (begin == end)
2078                     break;
2079             }
2080             append(*begin);
2081             ++begin;
2082         }
2083         return len;
2084     }
2085 #else
2086     // MSVC needs the full normalization, as it puts the const in a different
2087     // place than we expect
2088     constexpr int normalizeTypeFromSignature(const char *begin, const char *end)
2089     { return normalizeType(begin, end); }
2090 #endif
2091 
2092     constexpr int normalizeType(const char *begin, const char *end, bool adjustConst = true)
2093     {
2094         // Trim spaces
2095         while (begin != end && is_space(*begin))
2096             begin++;
2097         while (begin != end && is_space(*(end - 1)))
2098             end--;
2099 
2100         // Convert 'char const *' into 'const char *'. Start at index 1,
2101         // not 0, because 'const char *' is already OK.
2102         const char *cst = begin + 1;
2103         if (*begin == '\'' || *begin == '"')
2104             cst = skipString(begin, end);
2105         bool seenStar = false;
2106         bool hasMiddleConst = false;
2107         while (cst < end) {
2108             if (*cst == '\"' || (*cst == '\'' && !is_number(cst[-1]))) {
2109                 cst = skipString(cst, end);
2110                 if (cst == end)
2111                     break;
2112             }
2113 
2114             // We mustn't convert 'char * const *' into 'const char **'
2115             // and we must beware of 'Bar<const Bla>'.
2116             if (*cst == '&' || *cst == '*' || *cst == '[') {
2117                 seenStar = *cst != '&' || cst != (end - 1);
2118                 break;
2119             }
2120             if (*cst == '<') {
2121                 cst = skipTemplate(cst + 1, end);
2122                 if (cst == end)
2123                     break;
2124             }
2125             cst++;
2126             const char *skipedCst = cst;
2127             if (!is_ident_char(*(cst - 1)) && skipToken(skipedCst, end, "const")) {
2128                 const char *testEnd = end;
2129                 while (skipedCst < testEnd--) {
2130                     if (*testEnd == '*' || *testEnd == '['
2131                         || (*testEnd == '&' && testEnd != (end - 1))) {
2132                         seenStar = true;
2133                         break;
2134                     }
2135                     if (*testEnd == '>')
2136                         break;
2137                 }
2138                 if (adjustConst && !seenStar) {
2139                     if (*(end - 1) == '&')
2140                         end--;
2141                 } else {
2142                     appendStr("const ");
2143                 }
2144                 normalizeType(begin, cst, false);
2145                 begin = skipedCst;
2146                 hasMiddleConst = true;
2147                 break;
2148             }
2149         }
2150         if (skipToken(begin, end, "const")) {
2151             if (adjustConst && !seenStar) {
2152                 if (*(end - 1) == '&')
2153                     end--;
2154             } else {
2155                 appendStr("const ");
2156             }
2157         }
2158         if (seenStar && adjustConst) {
2159             const char *e = end;
2160             if (*(end - 1) == '&' && *(end - 2) != '&')
2161                 e--;
2162             while (begin != e && is_space(*(e - 1)))
2163                 e--;
2164             const char *token = "tsnoc"; // 'const' reverse, to check if it ends with const
2165             while (*token && begin != e && *(--e) == *token++)
2166                 ;
2167             if (!*token && begin != e && !is_ident_char(*(e - 1))) {
2168                 while (begin != e && is_space(*(e - 1)))
2169                     e--;
2170                 end = e;
2171             }
2172         }
2173 
2174         skipStructClassOrEnum(begin, end);
2175         skipQtNamespace(begin, end);
2176 
2177         if (skipToken(begin, end, "QVector")) {
2178             // Replace QVector by QList
2179             appendStr("QList");
2180         }
2181 
2182         if (skipToken(begin, end, "QPair")) {
2183             // replace QPair by std::pair
2184             appendStr("std::pair");
2185         }
2186 
2187         if (!hasMiddleConst)
2188             // Normalize the integer types
2189             normalizeIntegerTypes(begin, end);
2190 
2191         bool spaceSkiped = true;
2192         while (begin != end) {
2193             char c = *begin++;
2194             if (is_space(c)) {
2195                 spaceSkiped = true;
2196             } else if ((c == '\'' && !is_number(last)) || c == '\"') {
2197                 begin--;
2198                 auto x = skipString(begin, end);
2199                 while (begin < x)
2200                     append(*begin++);
2201             } else {
2202                 if (spaceSkiped && is_ident_char(last) && is_ident_char(c))
2203                     append(' ');
2204                 append(c);
2205                 spaceSkiped = false;
2206                 if (c == '<') {
2207                     do {
2208                         // template recursion
2209                         const char *tpl = skipTemplate(begin, end, true);
2210                         normalizeType(begin, tpl, false);
2211                         if (tpl == end)
2212                             return len;
2213                         append(*tpl);
2214                         begin = tpl;
2215                     } while (*begin++ == ',');
2216                 }
2217             }
2218         }
2219         return len;
2220     }
2221 };
2222 
2223 // Normalize the type between begin and end, and store the data in the output. Returns the length.
2224 // The idea is to first run this function with nullptr as output to allocate the output with the
2225 // size
2226 constexpr int qNormalizeType(const char *begin, const char *end, char *output)
2227 {
2228     return QTypeNormalizer { output }.normalizeType(begin, end);
2229 }
2230 
2231 template<typename T>
2232 struct is_std_pair : std::false_type {};
2233 
2234 template <typename T1_, typename T2_>
2235 struct is_std_pair<std::pair<T1_, T2_>> : std::true_type {
2236     using T1 = T1_;
2237     using T2 = T2_;
2238 };
2239 
2240 namespace TypeNameHelper {
2241 template<typename T>
2242 constexpr auto typenameHelper()
2243 {
2244     if constexpr (is_std_pair<T>::value) {
2245         using T1 = typename is_std_pair<T>::T1;
2246         using T2 = typename is_std_pair<T>::T2;
2247         std::remove_const_t<std::conditional_t<bool (QMetaTypeId2<T1>::IsBuiltIn), typename QMetaTypeId2<T1>::NameAsArrayType, decltype(typenameHelper<T1>())>> t1Name {};
2248         std::remove_const_t<std::conditional_t<bool (QMetaTypeId2<T2>::IsBuiltIn), typename QMetaTypeId2<T2>::NameAsArrayType, decltype(typenameHelper<T2>())>> t2Name {};
2249         if constexpr (bool (QMetaTypeId2<T1>::IsBuiltIn) ) {
2250             t1Name = QMetaTypeId2<T1>::nameAsArray;
2251         } else {
2252             t1Name = typenameHelper<T1>();
2253         }
2254         if constexpr (bool(QMetaTypeId2<T2>::IsBuiltIn)) {
2255             t2Name = QMetaTypeId2<T2>::nameAsArray;
2256         } else {
2257             t2Name = typenameHelper<T2>();
2258         }
2259         constexpr auto nonTypeDependentLen = sizeof("std::pair<,>");
2260         constexpr auto t1Len = t1Name.size() - 1;
2261         constexpr auto t2Len = t2Name.size() - 1;
2262         constexpr auto length = nonTypeDependentLen + t1Len + t2Len;
2263         std::array<char, length + 1> result {};
2264         constexpr auto prefix = "std::pair<";
2265         int currentLength = 0;
2266         for (; currentLength < int(sizeof("std::pair<") - 1); ++currentLength)
2267             result[currentLength] = prefix[currentLength];
2268         for (int i = 0; i < int(t1Len); ++currentLength, ++i)
2269             result[currentLength] = t1Name[i];
2270         result[currentLength++] = ',';
2271         for (int i = 0; i < int(t2Len); ++currentLength, ++i)
2272             result[currentLength] = t2Name[i];
2273         result[currentLength++] = '>';
2274         result[currentLength++] = '\0';
2275         return result;
2276     } else {
2277         constexpr auto prefix = sizeof(
2278 #ifdef QT_NAMESPACE
2279             QT_STRINGIFY(QT_NAMESPACE) "::"
2280 #endif
2281 #if defined(Q_CC_MSVC) && defined(Q_CC_CLANG)
2282             "auto __cdecl QtPrivate::TypeNameHelper::typenameHelper(void) [T = "
2283 #elif defined(Q_CC_MSVC)
2284             "auto __cdecl QtPrivate::TypeNameHelper::typenameHelper<"
2285 #elif defined(Q_CC_CLANG)
2286             "auto QtPrivate::TypeNameHelper::typenameHelper() [T = "
2287 #elif defined(Q_CC_GHS)
2288             "auto QtPrivate::TypeNameHelper::typenameHelper<T>()[with T="
2289 #else
2290             "constexpr auto QtPrivate::TypeNameHelper::typenameHelper() [with T = "
2291 #endif
2292             ) - 1;
2293 #if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
2294         constexpr int suffix = sizeof(">(void)");
2295 #else
2296         constexpr int suffix = sizeof("]");
2297 #endif
2298 
2299 #if defined(Q_CC_GNU_ONLY) && Q_CC_GNU_ONLY < 804
2300         auto func = Q_FUNC_INFO;
2301         const char *begin = func + prefix;
2302         const char *end = func + sizeof(Q_FUNC_INFO) - suffix;
2303         // This is an upper bound of the size since the normalized signature should always be smaller
2304         constexpr int len = sizeof(Q_FUNC_INFO) - suffix - prefix;
2305 #else
2306         constexpr auto func = Q_FUNC_INFO;
2307         constexpr const char *begin = func + prefix;
2308         constexpr const char *end = func + sizeof(Q_FUNC_INFO) - suffix;
2309         constexpr int len = QTypeNormalizer{ nullptr }.normalizeTypeFromSignature(begin, end);
2310 #endif
2311         std::array<char, len + 1> result {};
2312         QTypeNormalizer{ result.data() }.normalizeTypeFromSignature(begin, end);
2313         return result;
2314     }
2315 }
2316 } // namespace TypeNameHelper
2317 using TypeNameHelper::typenameHelper;
2318 
2319 template<typename T, typename = void>
2320 struct BuiltinMetaType : std::integral_constant<int, 0>
2321 {
2322 };
2323 template<typename T>
2324 struct BuiltinMetaType<T, std::enable_if_t<QMetaTypeId2<T>::IsBuiltIn>>
2325     : std::integral_constant<int, QMetaTypeId2<T>::MetaType>
2326 {
2327 };
2328 
2329 template<typename T, bool = (QTypeTraits::has_operator_equal_v<T> && !std::is_pointer_v<T>)>
2330 struct QEqualityOperatorForType
2331 {
2332 QT_WARNING_PUSH
2333 QT_WARNING_DISABLE_FLOAT_COMPARE
2334     static bool equals(const QMetaTypeInterface *, const void *a, const void *b)
2335     { return *reinterpret_cast<const T *>(a) == *reinterpret_cast<const T *>(b); }
2336 QT_WARNING_POP
2337 };
2338 
2339 template<typename T>
2340 struct QEqualityOperatorForType <T, false>
2341 {
2342     static constexpr QMetaTypeInterface::EqualsFn equals = nullptr;
2343 };
2344 
2345 template<typename T, bool = (QTypeTraits::has_operator_less_than_v<T> && !std::is_pointer_v<T>)>
2346 struct QLessThanOperatorForType
2347 {
2348     static bool lessThan(const QMetaTypeInterface *, const void *a, const void *b)
2349     { return *reinterpret_cast<const T *>(a) < *reinterpret_cast<const T *>(b); }
2350 };
2351 
2352 template<typename T>
2353 struct QLessThanOperatorForType <T, false>
2354 {
2355     static constexpr QMetaTypeInterface::LessThanFn lessThan = nullptr;
2356 };
2357 
2358 template<typename T, bool = (QTypeTraits::has_ostream_operator_v<QDebug, T> && !std::is_pointer_v<T>)>
2359 struct QDebugStreamOperatorForType
2360 {
2361     static void debugStream(const QMetaTypeInterface *, QDebug &dbg, const void *a)
2362     { dbg << *reinterpret_cast<const T *>(a); }
2363 };
2364 
2365 template<typename T>
2366 struct QDebugStreamOperatorForType <T, false>
2367 {
2368     static constexpr QMetaTypeInterface::DebugStreamFn debugStream = nullptr;
2369 };
2370 
2371 template<typename T, bool = QTypeTraits::has_stream_operator_v<QDataStream, T>>
2372 struct QDataStreamOperatorForType
2373 {
2374     static constexpr QMetaTypeInterface::DataStreamOutFn dataStreamOut = nullptr;
2375     static constexpr QMetaTypeInterface::DataStreamInFn dataStreamIn = nullptr;
2376 };
2377 
2378 #ifndef QT_NO_DATASTREAM
2379 template<typename T>
2380 struct QDataStreamOperatorForType <T, true>
2381 {
2382     static void dataStreamOut(const QMetaTypeInterface *, QDataStream &ds, const void *a)
2383     { ds << *reinterpret_cast<const T *>(a); }
2384     static void dataStreamIn(const QMetaTypeInterface *, QDataStream &ds, void *a)
2385     { ds >> *reinterpret_cast<T *>(a); }
2386 };
2387 #endif
2388 
2389 // Performance optimization:
2390 //
2391 // Don't add all these symbols to the dynamic symbol tables on ELF systems and
2392 // on Darwin. Each library is going to have a copy anyway and QMetaType already
2393 // copes with some of these being "hidden" (see QMetaType::idHelper()). We may
2394 // as well let the linker know it can always use the local copy.
2395 //
2396 // This is currently not enabled for GCC due to
2397 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106023
2398 
2399 #if !defined(Q_OS_WIN) && defined(Q_CC_CLANG)
2400 #  pragma GCC visibility push(hidden)
2401 #endif
2402 
2403 // ### Qt 7: consider removing this infrastructure if nothing uses it
2404 // (see also getCopyCtr())
2405 namespace QMetaTypeCopyTraits
2406 {
2407     // Hack to suppress deprecation warnings from types
2408     // with deprecated copy operations, cf. QTBUG-132752
2409     template <typename T>
2410     using HasDeprecatedCopyConstructorTest = typename T::_q_hasDeprecatedCopyConstructor;
2411 
2412 #if !defined(QT_BOOTSTRAPPED)
2413     Q_CORE_EXPORT void warnAboutDeprecatedCopy(const char *name);
2414 #endif
2415 } // namespace QMetaTypeCopyTraits
2416 
2417 template<typename S>
2418 class QMetaTypeForType
2419 {
2420 public:
2421     static constexpr decltype(typenameHelper<S>()) name = typenameHelper<S>();
2422 
2423     static constexpr unsigned flags()
2424     {
2425         uint flags = 0;
2426         if constexpr (QTypeInfo<S>::isRelocatable)
2427             flags |= QMetaType::RelocatableType;
2428         if constexpr (!std::is_default_constructible_v<S> || !QTypeInfo<S>::isValueInitializationBitwiseZero)
2429             flags |= QMetaType::NeedsConstruction;
2430         if constexpr (!std::is_trivially_destructible_v<S>)
2431             flags |= QMetaType::NeedsDestruction;
2432         if constexpr (!std::is_trivially_copy_constructible_v<S>)
2433             flags |= QMetaType::NeedsCopyConstruction;
2434         if constexpr (!std::is_trivially_move_constructible_v<S>)
2435             flags |= QMetaType::NeedsMoveConstruction;
2436         if constexpr (IsPointerToTypeDerivedFromQObject<S>::Value)
2437             flags |= QMetaType::PointerToQObject;
2438         if constexpr (IsSharedPointerToTypeDerivedFromQObject<S>::Value)
2439             flags |= QMetaType::SharedPointerToQObject;
2440         if constexpr (IsWeakPointerToTypeDerivedFromQObject<S>::Value)
2441             flags |= QMetaType::WeakPointerToQObject;
2442         if constexpr (IsTrackingPointerToTypeDerivedFromQObject<S>::Value)
2443             flags |= QMetaType::TrackingPointerToQObject;
2444         if constexpr (IsEnumOrFlags<S>::value)
2445             flags |= QMetaType::IsEnumeration;
2446         if constexpr (IsGadgetHelper<S>::IsGadgetOrDerivedFrom)
2447             flags |= QMetaType::IsGadget;
2448         if constexpr (IsPointerToGadgetHelper<S>::IsGadgetOrDerivedFrom)
2449             flags |= QMetaType::PointerToGadget;
2450         if constexpr (std::is_pointer_v<S>)
2451             flags |= QMetaType::IsPointer;
2452         if constexpr (IsUnsignedEnum<S>)
2453             flags |= QMetaType::IsUnsignedEnumeration;
2454         if constexpr (IsQmlListType<S>)
2455             flags |= QMetaType::IsQmlList;
2456         if constexpr (std::is_const_v<std::remove_pointer_t<S>>)
2457             flags |= QMetaType::IsConst;
2458         return flags;
2459     }
2460 
2461     static constexpr QMetaTypeInterface::DefaultCtrFn getDefaultCtr()
2462     {
2463         if constexpr (std::is_default_constructible_v<S> && !QTypeInfo<S>::isValueInitializationBitwiseZero) {
2464             return [](const QMetaTypeInterface *, void *addr) { new (addr) S(); };
2465         } else {
2466             return nullptr;
2467         }
2468     }
2469 
2470     static constexpr QMetaTypeInterface::CopyCtrFn getCopyCtr()
2471     {
2472         if constexpr (std::is_copy_constructible_v<S> && !std::is_trivially_copy_constructible_v<S>) {
2473             return [](const QMetaTypeInterface *, void *addr, const void *other) {
2474                 if constexpr (qxp::is_detected_v<QMetaTypeCopyTraits::HasDeprecatedCopyConstructorTest, S>) {
2475 #if !defined(QT_BOOTSTRAPPED)
2476                     QMetaTypeCopyTraits::warnAboutDeprecatedCopy(getName());
2477 #endif
2478                     QT_IGNORE_DEPRECATIONS(new (addr) S(*reinterpret_cast<const S *>(other));)
2479                 } else {
2480                     new (addr) S(*reinterpret_cast<const S *>(other));
2481                 }
2482             };
2483         } else {
2484             return nullptr;
2485         }
2486     }
2487 
2488     static constexpr QMetaTypeInterface::MoveCtrFn getMoveCtr()
2489     {
2490         if constexpr (std::is_move_constructible_v<S> && !std::is_trivially_move_constructible_v<S>) {
2491             return [](const QMetaTypeInterface *, void *addr, void *other) {
2492                 new (addr) S(std::move(*reinterpret_cast<S *>(other)));
2493             };
2494         } else {
2495             return nullptr;
2496         }
2497     }
2498 
2499     static constexpr QMetaTypeInterface::DtorFn getDtor()
2500     {
2501         if constexpr (std::is_destructible_v<S> && !std::is_trivially_destructible_v<S>)
2502             return [](const QMetaTypeInterface *, void *addr) {
2503                 reinterpret_cast<S *>(addr)->~S();
2504             };
2505         else
2506             return nullptr;
2507     }
2508 
2509     static constexpr QMetaTypeInterface::LegacyRegisterOp getLegacyRegister()
2510     {
2511         if constexpr (QMetaTypeId2<S>::Defined && !QMetaTypeId2<S>::IsBuiltIn) {
2512             return []() { QMetaTypeId2<S>::qt_metatype_id(); };
2513         } else {
2514             return nullptr;
2515         }
2516     }
2517 
2518     static constexpr const char *getName()
2519     {
2520         if constexpr (bool(QMetaTypeId2<S>::IsBuiltIn)) {
2521             return QMetaTypeId2<S>::nameAsArray.data();
2522         } else {
2523             return name.data();
2524         }
2525     }
2526 };
2527 
2528 template<typename T>
2529 struct QMetaTypeInterfaceWrapper
2530 {
2531     // if the type ID for T is known at compile-time, then we can declare
2532     // the QMetaTypeInterface object const; otherwise, we declare it as
2533     // non-const and the .typeId is updated by QMetaType::idHelper().
2534     static constexpr bool IsConstMetaTypeInterface = !!BuiltinMetaType<T>::value;
2535     using InterfaceType = std::conditional_t<IsConstMetaTypeInterface, const QMetaTypeInterface, NonConstMetaTypeInterface>;
2536 
2537     static inline InterfaceType metaType = {
2538         /*.revision=*/ QMetaTypeInterface::CurrentRevision,
2539         /*.alignment=*/ alignof(T),
2540         /*.size=*/ sizeof(T),
2541         /*.flags=*/ QMetaTypeForType<T>::flags(),
2542         /*.typeId=*/ BuiltinMetaType<T>::value,
2543         /*.metaObjectFn=*/ MetaObjectForType<T>::metaObjectFunction,
2544         /*.name=*/ QMetaTypeForType<T>::getName(),
2545         /*.defaultCtr=*/ QMetaTypeForType<T>::getDefaultCtr(),
2546         /*.copyCtr=*/ QMetaTypeForType<T>::getCopyCtr(),
2547         /*.moveCtr=*/ QMetaTypeForType<T>::getMoveCtr(),
2548         /*.dtor=*/ QMetaTypeForType<T>::getDtor(),
2549         /*.equals=*/ QEqualityOperatorForType<T>::equals,
2550         /*.lessThan=*/ QLessThanOperatorForType<T>::lessThan,
2551         /*.debugStream=*/ QDebugStreamOperatorForType<T>::debugStream,
2552         /*.dataStreamOut=*/ QDataStreamOperatorForType<T>::dataStreamOut,
2553         /*.dataStreamIn=*/ QDataStreamOperatorForType<T>::dataStreamIn,
2554         /*.legacyRegisterOp=*/ QMetaTypeForType<T>::getLegacyRegister()
2555     };
2556 };
2557 template<typename T> struct QMetaTypeInterfaceWrapper<T &> {};
2558 
2559 
2560 #if !defined(Q_OS_WIN) && defined(Q_CC_CLANG)
2561 #  pragma GCC visibility pop
2562 #endif
2563 
2564 template<>
2565 class QMetaTypeInterfaceWrapper<void>
2566 {
2567 public:
2568     static constexpr QMetaTypeInterface metaType =
2569     {
2570         /*.revision=*/ 0,
2571         /*.alignment=*/ 0,
2572         /*.size=*/ 0,
2573         /*.flags=*/ 0,
2574         /*.typeId=*/ BuiltinMetaType<void>::value,
2575         /*.metaObjectFn=*/ nullptr,
2576         /*.name=*/ "void",
2577         /*.defaultCtr=*/ nullptr,
2578         /*.copyCtr=*/ nullptr,
2579         /*.moveCtr=*/ nullptr,
2580         /*.dtor=*/ nullptr,
2581         /*.equals=*/ nullptr,
2582         /*.lessThan=*/ nullptr,
2583         /*.debugStream=*/ nullptr,
2584         /*.dataStreamOut=*/ nullptr,
2585         /*.dataStreamIn=*/ nullptr,
2586         /*.legacyRegisterOp=*/ nullptr
2587     };
2588 };
2589 
2590 /*
2591  MSVC instantiates extern templates
2592 (https://developercommunity.visualstudio.com/t/c11-extern-templates-doesnt-work-for-class-templat/157868)
2593 
2594  The INTEGRITY compiler apparently does too.
2595 
2596  On Windows (with other compilers or whenever MSVC is fixed), we can't declare
2597  QMetaTypeInterfaceWrapper with __declspec(dllimport) because taking its
2598  address is not a core constant expression.
2599  */
2600 #if !defined(QT_BOOTSTRAPPED) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY)
2601 
2602 #ifdef QT_NO_DATA_RELOCATION
2603 #  define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name)          \
2604     extern template class Q_CORE_EXPORT QMetaTypeForType<Name>;
2605 #else
2606 #  define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name)          \
2607     extern template class Q_CORE_EXPORT QMetaTypeForType<Name>;                 \
2608     extern template struct Q_CORE_EXPORT QMetaTypeInterfaceWrapper<Name>;
2609 #endif
2610 
2611 QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
2612 QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
2613 QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
2614 QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
2615 QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
2616 #undef QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER
2617 #endif
2618 
2619 template<typename T>
2620 struct QRemovePointerLike
2621 {
2622     using type = std::remove_pointer_t<T>;
2623 };
2624 
2625 #define Q_REMOVE_POINTER_LIKE_IMPL(Pointer) \
2626 template <typename T> \
2627 struct QRemovePointerLike<Pointer<T>> \
2628 { \
2629     using type = T; \
2630 };
2631 
2632 QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(Q_REMOVE_POINTER_LIKE_IMPL)
2633 #undef Q_REMOVE_POINTER_LIKE_IMPL
2634 
2635 template<typename T>
2636 constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType()
2637 {
2638     // don't check the type is suitable here
2639     using Ty = typename MetatypeDecay<T>::type;
2640     return &QMetaTypeInterfaceWrapper<Ty>::metaType;
2641 }
2642 
2643 // Relaxed vesion of the above, used by moc-generated code to create the
2644 // metatype array without requiring types to be complete and allowing
2645 // references. Unique is passed to is_complete and must be a different unique
2646 // type; if it is void, this function is equal to qMetaTypeInterfaceForType()
2647 // above.
2648 template<typename Unique, typename T>
2649 constexpr const QMetaTypeInterface *qTryMetaTypeInterfaceForType()
2650 {
2651     using Ty = typename MetatypeDecay<T>::type;
2652     using Tz = typename QRemovePointerLike<Ty>::type;
2653 
2654     if constexpr (std::is_void_v<Tz>) {
2655         // early out to avoid expanding the rest of the templates
2656         return &QMetaTypeInterfaceWrapper<Ty>::metaType;
2657     } else if constexpr (std::is_void_v<Unique>) {
2658         checkTypeIsSuitableForMetaType<Ty>();
2659         return &QMetaTypeInterfaceWrapper<Ty>::metaType;
2660     } else if constexpr (std::is_reference_v<Tz>) {
2661         return nullptr;
2662     } else if constexpr (!is_complete<Tz, Unique>::value) {
2663         return nullptr;
2664     } else {
2665         // don't check the type is suitable here
2666         return &QMetaTypeInterfaceWrapper<Ty>::metaType;
2667     }
2668 }
2669 
2670 } // namespace QtPrivate
2671 
2672 template<typename T>
2673 constexpr QMetaType QMetaType::fromType()
2674 {
2675     QtPrivate::checkTypeIsSuitableForMetaType<T>();
2676     return QMetaType(QtPrivate::qMetaTypeInterfaceForType<T>());
2677 }
2678 
2679 constexpr bool QMetaType::isValid(QT6_IMPL_NEW_OVERLOAD) const noexcept
2680 {
2681     return d_ptr;
2682 }
2683 
2684 bool QMetaType::isRegistered(QT6_IMPL_NEW_OVERLOAD) const noexcept
2685 {
2686     return d_ptr && d_ptr->typeId.loadRelaxed();
2687 }
2688 
2689 constexpr qsizetype QMetaType::sizeOf() const
2690 {
2691     return d_ptr ? d_ptr->size : 0;
2692 }
2693 
2694 constexpr qsizetype QMetaType::alignOf() const
2695 {
2696     return d_ptr ? d_ptr->alignment : 0;
2697 }
2698 
2699 constexpr QMetaType::TypeFlags QMetaType::flags() const
2700 {
2701     return d_ptr ? TypeFlags(d_ptr->flags) : TypeFlags{};
2702 }
2703 
2704 constexpr const QMetaObject *QMetaType::metaObject() const
2705 {
2706     return d_ptr && d_ptr->metaObjectFn ? d_ptr->metaObjectFn(d_ptr) : nullptr;
2707 }
2708 
2709 constexpr const char *QMetaType::name() const
2710 {
2711     return d_ptr ? d_ptr->name : nullptr;
2712 }
2713 
2714 inline size_t qHash(QMetaType type, size_t seed = 0)
2715 {
2716     // We cannot use d_ptr here since the same type in different DLLs
2717     // might result in different pointers!
2718     return qHash(type.id(), seed);
2719 }
2720 
2721 QT_END_NAMESPACE
2722 
2723 QT_DECL_METATYPE_EXTERN_TAGGED(QtMetaTypePrivate::QPairVariantInterfaceImpl,
2724                                QPairVariantInterfaceImpl, Q_CORE_EXPORT)
2725 
2726 #endif // QMETATYPE_H