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