Back to home page

EIC code displayed by LXR

 
 

    


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

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