Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/QtCore/qmetatype.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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