Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:07:31

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