Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qmetatype.h
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2018 Intel Corporation.
3// Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
4// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
5// Qt-Security score:significant reason:default
6
7#ifndef QMETATYPE_H
8#define QMETATYPE_H
9
10#include <QtCore/qglobal.h>
11#include <QtCore/qatomic.h>
12#include <QtCore/qbytearray.h>
13#include <QtCore/qcompare.h>
14#include <QtCore/qdatastream.h>
15#include <QtCore/qflags.h>
16#include <QtCore/qfloat16.h>
17#include <QtCore/qhashfunctions.h>
18#include <QtCore/qiterable.h>
19#include <QtCore/qmetacontainer.h>
20#ifndef QT_NO_QOBJECT
21#include <QtCore/qobjectdefs.h>
22#endif
23#include <QtCore/qscopeguard.h>
24#include <QtCore/qttypetraits.h>
25
26#include <array>
27#include <new>
28#include <vector>
29#include <list>
30#include <map>
31#include <functional>
32#include <optional>
33#include <QtCore/qxptype_traits.h>
34
35#ifdef Bool
36#error qmetatype.h must be included before any header file that defines Bool
37#endif
38
39QT_BEGIN_NAMESPACE
40
41// from qcborcommon.h
42enum class QCborSimpleType : quint8;
43
44template <typename T>
45struct QMetaTypeId2;
46
47template <typename T>
48inline constexpr int qMetaTypeId();
49
50// F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, RealType)
51#define QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(F)
52 F(Bool, 1, bool)
53 F(Int, 2, int)
54 F(UInt, 3, uint)
55 F(LongLong, 4, qlonglong)
56 F(ULongLong, 5, qulonglong)
57 F(Double, 6, double)
58 F(Long, 32, long)
59 F(Short, 33, short)
60 F(Char, 34, char)
61 F(Char16, 56, char16_t)
62 F(Char32, 57, char32_t)
63 F(ULong, 35, ulong)
64 F(UShort, 36, ushort)
65 F(UChar, 37, uchar)
66 F(Float, 38, float)
67 F(SChar, 40, signed char)
68 F(Nullptr, 51, std::nullptr_t)
69 F(QCborSimpleType, 52, QCborSimpleType)
70
71#define QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)
73 F(Void, 43, void)
74
75#define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)
76 F(VoidStar, 31, void*)
77
78#if QT_CONFIG(easingcurve)
79#define QT_FOR_EACH_STATIC_EASINGCURVE(F)
80 F(QEasingCurve, 29, QEasingCurve)
81#else
82#define QT_FOR_EACH_STATIC_EASINGCURVE(F)
83#endif
84
85#if QT_CONFIG(itemmodel)
86#define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
87 F(QModelIndex, 42, QModelIndex)
88 F(QPersistentModelIndex, 50, QPersistentModelIndex)
89#else
90#define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
91#endif
92
93#if QT_CONFIG(regularexpression)
94# define QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F)
95 F(QRegularExpression, 44, QRegularExpression)
96#else
97# define QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F)
98#endif
99#ifndef QT_NO_VARIANT
100# define QT_FOR_EACH_STATIC_QVARIANT(F)
101 F(QVariant, 41, QVariant)
102#else
103# define QT_FOR_EACH_STATIC_QVARIANT(F)
104#endif
105
106#define QT_FOR_EACH_STATIC_CORE_CLASS(F)
107 F(QChar, 7, QChar)
108 F(QString, 10, QString)
109 F(QByteArray, 12, QByteArray)
110 F(QBitArray, 13, QBitArray)
111 F(QDate, 14, QDate)
112 F(QTime, 15, QTime)
113 F(QDateTime, 16, QDateTime)
114 F(QUrl, 17, QUrl)
115 F(QLocale, 18, QLocale)
116 F(QRect, 19, QRect)
117 F(QRectF, 20, QRectF)
118 F(QSize, 21, QSize)
119 F(QSizeF, 22, QSizeF)
120 F(QLine, 23, QLine)
121 F(QLineF, 24, QLineF)
122 F(QPoint, 25, QPoint)
123 F(QPointF, 26, QPointF)
125 F(QUuid, 30, QUuid)
128 F(QJsonValue, 45, QJsonValue)
129 F(QJsonObject, 46, QJsonObject)
130 F(QJsonArray, 47, QJsonArray)
131 F(QJsonDocument, 48, QJsonDocument)
132 F(QCborValue, 53, QCborValue)
133 F(QCborArray, 54, QCborArray)
134 F(QCborMap, 55, QCborMap)
135 F(Float16, 63, qfloat16)
137
138#define QT_FOR_EACH_STATIC_CORE_POINTER(F)
139 F(QObjectStar, 39, QObject*)
140
141#ifndef QT_NO_VARIANT
142# define QT_FOR_EACH_STATIC_CORE_QVARIANT_TEMPLATE(F)
143 F(QVariantMap, 8, QVariantMap)
144 F(QVariantList, 9, QVariantList)
145 F(QVariantHash, 28, QVariantHash)
146 F(QVariantPair, 58, QVariantPair)
147 /**/
148#else
149# define QT_FOR_EACH_STATIC_CORE_QVARIANT_TEMPLATE(F)
150#endif // QT_NO_VARIANT
151
152#define QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)
154 F(QByteArrayList, 49, QByteArrayList)
155 F(QStringList, 11, QStringList)
156
157#if QT_CONFIG(shortcut)
158#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)
159 F(QKeySequence, 0x100b, QKeySequence)
160#else
161#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)
162#endif
163
164#define QT_FOR_EACH_STATIC_GUI_CLASS(F)
165 F(QFont, 0x1000, QFont)
166 F(QPixmap, 0x1001, QPixmap)
167 F(QBrush, 0x1002, QBrush)
168 F(QColor, 0x1003, QColor)
169 F(QPalette, 0x1004, QPalette)
170 F(QIcon, 0x1005, QIcon)
171 F(QImage, 0x1006, QImage)
172 F(QPolygon, 0x1007, QPolygon)
173 F(QRegion, 0x1008, QRegion)
174 F(QBitmap, 0x1009, QBitmap)
175 F(QCursor, 0x100a, QCursor)
177 F(QPen, 0x100c, QPen)
178 F(QTextLength, 0x100d, QTextLength)
179 F(QTextFormat, 0x100e, QTextFormat)
180 F(QTransform, 0x1010, QTransform)
181 F(QMatrix4x4, 0x1011, QMatrix4x4)
182 F(QVector2D, 0x1012, QVector2D)
183 F(QVector3D, 0x1013, QVector3D)
184 F(QVector4D, 0x1014, QVector4D)
185 F(QQuaternion, 0x1015, QQuaternion)
186 F(QPolygonF, 0x1016, QPolygonF)
187 F(QColorSpace, 0x1017, QColorSpace)
188
189
190#define QT_FOR_EACH_STATIC_WIDGETS_CLASS(F)
191 F(QSizePolicy, 0x2000, QSizePolicy)
192
193// F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, AliasingType, "RealType")
194#define QT_FOR_EACH_STATIC_ALIAS_TYPE(F)
195 F(ULong, -1, ulong, "unsigned long")
196 F(UInt, -1, uint, "unsigned int")
197 F(UShort, -1, ushort, "unsigned short")
198 F(UChar, -1, uchar, "unsigned char")
199 F(LongLong, -1, qlonglong, "long long")
200 F(ULongLong, -1, qulonglong, "unsigned long long")
201 F(SChar, -1, signed char, "qint8")
202 F(UChar, -1, uchar, "quint8")
203 F(Short, -1, short, "qint16")
204 F(UShort, -1, ushort, "quint16")
205 F(Int, -1, int, "qint32")
206 F(UInt, -1, uint, "quint32")
207 F(LongLong, -1, qlonglong, "qint64")
208 F(ULongLong, -1, qulonglong, "quint64")
209 F(QByteArrayList, -1, QByteArrayList, "QList<QByteArray>")
210 F(QStringList, -1, QStringList, "QList<QString>")
212
213#ifndef QT_NO_VARIANT
214#define QT_FOR_EACH_STATIC_VARIANT_ALIAS_TYPE(F)
215 F(QVariantList, -1, QVariantList, "QList<QVariant>")
216 F(QVariantMap, -1, QVariantMap, "QMap<QString,QVariant>")
217 F(QVariantHash, -1, QVariantHash, "QHash<QString,QVariant>")
218 F(QVariantPair, -1, QVariantPair, "QPair<QVariant,QVariant>")
219 /**/
220#else
221#define QT_FOR_EACH_STATIC_VARIANT_ALIAS_TYPE(F)
222#endif
223
233#define QT_DEFINE_METATYPE_ID(TypeName, Id, Name)
234 TypeName = Id,
235
236#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(F)
237 F(QList)
238 F(QQueue)
239 F(QStack)
240 F(QSet)
241 /*end*/
242
243#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(F)
244 F(QHash, class)
245 F(QMap, class)
246
247#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(F)
248 F(QSharedPointer)
249 F(QWeakPointer)
250 F(QPointer)
251
252class QDataStream;
253struct QMetaObject;
254
255namespace QtPrivate
256{
257
259
260// MSVC is the only supported compiler that includes the type of a variable in
261// its mangled form, so it's not binary-compatible to drop the const in
262// QMetaTypeInterfaceWrapper::metaType for it, which means we must keep the
263// mutable field until Qt 7.
264#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) || !defined(Q_CC_MSVC)
265# define QMTI_MUTABLE
267#else
268# define QMTI_MUTABLE mutable
269using NonConstMetaTypeInterface = const QMetaTypeInterface;
270#endif
271
273{
274public:
275
276 /* Revision: Can increase if new field are added, or if semantics changes
277 0: Initial Revision
278 1: the meaning of the NeedsDestruction flag changed
279 */
280 static inline constexpr ushort CurrentRevision = 1;
281
282 ushort revision;
283 ushort alignment;
284 uint size;
285 uint flags;
287
288 using MetaObjectFn = const QMetaObject *(*)(const QMetaTypeInterface *);
290
291 const char *name;
292
293 using DefaultCtrFn = void (*)(const QMetaTypeInterface *, void *);
295 using CopyCtrFn = void (*)(const QMetaTypeInterface *, void *, const void *);
297 using MoveCtrFn = void (*)(const QMetaTypeInterface *, void *, void *);
299 using DtorFn = void (*)(const QMetaTypeInterface *, void *);
301 using EqualsFn = bool (*)(const QMetaTypeInterface *, const void *, const void *);
303 using LessThanFn = bool (*)(const QMetaTypeInterface *, const void *, const void *);
305 using DebugStreamFn = void (*)(const QMetaTypeInterface *, QDebug &, const void *);
307 using DataStreamOutFn = void (*)(const QMetaTypeInterface *, QDataStream &, const void *);
309 using DataStreamInFn = void (*)(const QMetaTypeInterface *, QDataStream &, void *);
311
312 using LegacyRegisterOp = void (*)();
314};
315#undef QMTI_MUTABLE
316
317/*!
318 This template is used for implicit conversion from type From to type To.
319 \internal
320*/
321template<typename From, typename To>
322To convertImplicit(const From& from)
323{
324 return from;
325}
326
327 template<typename T, bool>
329 template<typename T, bool>
331 template<typename T, bool>
332 struct IsMetaTypePair;
333 template<typename, typename>
335
336 template<typename T>
338
339 namespace detail {
340 template<typename T, typename ODR_VIOLATION_PREVENTER>
342 {
343 template<typename U>
344 static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
345 static auto check(...) -> std::false_type;
346 using type = decltype(check(static_cast<T *>(nullptr)));
347 };
348 } // namespace detail
349
350 template <typename T, typename ODR_VIOLATION_PREVENTER = void>
354
355 template <typename T> struct MetatypeDecay { using type = T; };
356 template <typename T> struct MetatypeDecay<const T> { using type = T; };
357 template <typename T> struct MetatypeDecay<const T &> { using type = T; };
358
359 template <typename T> struct IsPointerDeclaredOpaque :
362 {};
363 template <> struct IsPointerDeclaredOpaque<void *> : std::true_type {};
364 template <> struct IsPointerDeclaredOpaque<const void *> : std::true_type {};
365
366 template <typename T, typename UniqueType = void> constexpr inline
368 template <typename T> constexpr inline
372 template <typename T, typename UniqueType = void> constexpr inline
375 && !std::is_reference_v<T>
377
378 template <typename X> static constexpr bool checkTypeIsSuitableForMetaType()
379 {
380 using T = typename MetatypeDecay<X>::type;
381 static_assert(TypeIsCompleteOrVoid<T>, "Meta Types must be fully defined");
382 static_assert(!std::is_reference_v<T>,
383 "Meta Types cannot be non-const references or rvalue references.");
384 if constexpr (std::is_pointer_v<T>) {
385 static_assert(PointerIsSuitableForMetaTypeHelper<T>,
386 "Pointer Meta Types must either point to fully-defined types "
387 "or be declared with Q_DECLARE_OPAQUE_POINTER(T *)");
388 }
389 // final check
390 static_assert(TypeIsSuitableForMetaType<T>);
391 return true;
392 }
393} // namespace QtPrivate
394
395class Q_CORE_EXPORT QMetaType {
396public:
397#ifndef Q_QDOC
398 // The code that actually gets compiled.
399 enum Type {
400 // these are merged with QVariant
401 QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID)
402
403 FirstCoreType = Bool,
404 LastCoreType = Float16,
405 FirstGuiType = QFont,
406 LastGuiType = QColorSpace,
407 FirstWidgetsType = QSizePolicy,
408 LastWidgetsType = QSizePolicy,
409 HighestInternalId = LastWidgetsType,
410
411 QReal = sizeof(qreal) == sizeof(double) ? Double : Float,
412
413 UnknownType = 0,
414 User = 65536
415 };
416#else
417 // If we are using QDoc it fakes the Type enum looks like this.
418 enum Type {
419 UnknownType = 0, Bool = 1, Int = 2, UInt = 3, LongLong = 4, ULongLong = 5,
420 Double = 6, Long = 32, Short = 33, Char = 34, ULong = 35, UShort = 36,
421 UChar = 37, Float = 38,
422 VoidStar = 31,
423 QChar = 7, QString = 10, QStringList = 11, QByteArray = 12,
424 QBitArray = 13, QDate = 14, QTime = 15, QDateTime = 16, QUrl = 17,
425 QLocale = 18, QRect = 19, QRectF = 20, QSize = 21, QSizeF = 22,
426 QLine = 23, QLineF = 24, QPoint = 25, QPointF = 26,
427 QEasingCurve = 29, QUuid = 30, QVariant = 41, QModelIndex = 42,
428 QPersistentModelIndex = 50, QRegularExpression = 44,
429 QJsonValue = 45, QJsonObject = 46, QJsonArray = 47, QJsonDocument = 48,
430 QByteArrayList = 49, QObjectStar = 39, SChar = 40,
431 Void = 43,
432 Nullptr = 51,
433 QVariantMap = 8, QVariantList = 9, QVariantHash = 28, QVariantPair = 58,
434 QCborSimpleType = 52, QCborValue = 53, QCborArray = 54, QCborMap = 55,
435 Char16 = 56, Char32 = 57,
436 Int128 = 59, UInt128 = 60, Float128 = 61, BFloat16 = 62, Float16 = 63,
437
438 // Gui types
439 QFont = 0x1000, QPixmap = 0x1001, QBrush = 0x1002, QColor = 0x1003, QPalette = 0x1004,
440 QIcon = 0x1005, QImage = 0x1006, QPolygon = 0x1007, QRegion = 0x1008, QBitmap = 0x1009,
441 QCursor = 0x100a, QKeySequence = 0x100b, QPen = 0x100c, QTextLength = 0x100d, QTextFormat = 0x100e,
442 QTransform = 0x1010, QMatrix4x4 = 0x1011, QVector2D = 0x1012,
443 QVector3D = 0x1013, QVector4D = 0x1014, QQuaternion = 0x1015, QPolygonF = 0x1016, QColorSpace = 0x1017,
444
445 // Widget types
446 QSizePolicy = 0x2000,
447
448 // Start-point for client-code types:
449 User = 65536
450 };
451#endif
452
453 enum TypeFlag {
454 NeedsConstruction = 0x1,
455 NeedsDestruction = 0x2,
456 RelocatableType = 0x4,
457#if QT_DEPRECATED_SINCE(6, 0)
458 MovableType Q_DECL_ENUMERATOR_DEPRECATED_X("Use RelocatableType instead.") = RelocatableType,
459#endif
460 PointerToQObject = 0x8,
461 IsEnumeration = 0x10,
462 SharedPointerToQObject = 0x20,
463 WeakPointerToQObject = 0x40,
464 TrackingPointerToQObject = 0x80,
465 IsUnsignedEnumeration = 0x100,
466 IsGadget = 0x200,
467 PointerToGadget = 0x400,
468 IsPointer = 0x800,
469 IsQmlList =0x1000, // used in the QML engine to recognize QQmlListProperty<T> and list<T>
470 IsConst = 0x2000,
471 // since 6.5:
472 NeedsCopyConstruction = 0x4000,
473 NeedsMoveConstruction = 0x8000,
474 };
475 Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
476
477 static void registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, QMetaType type);
478
479#if QT_DEPRECATED_SINCE(6, 0)
480 QT_DEPRECATED_VERSION_6_0
481 static int type(const char *typeName)
482 { return QMetaType::fromName(typeName).rawId(); }
483 QT_DEPRECATED_VERSION_6_0
484 static int type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName)
485 { return QMetaType::fromName(typeName).rawId(); }
486 QT_DEPRECATED_VERSION_6_0
487 static const char *typeName(int type)
488 { return QMetaType(type).name(); }
489 QT_DEPRECATED_VERSION_6_0
490 static int sizeOf(int type)
491 { return int(QMetaType(type).sizeOf()); }
492 QT_DEPRECATED_VERSION_6_0
493 static TypeFlags typeFlags(int type)
494 { return QMetaType(type).flags(); }
495 QT_DEPRECATED_VERSION_6_0
496 static const QMetaObject *metaObjectForType(int type)
497 { return QMetaType(type).metaObject(); }
498 QT_DEPRECATED_VERSION_6_0
499 static void *create(int type, const void *copy = nullptr)
500 { return QMetaType(type).create(copy); }
501 QT_DEPRECATED_VERSION_6_0
502 static void destroy(int type, void *data)
503 { return QMetaType(type).destroy(data); }
504 QT_DEPRECATED_VERSION_6_0
505 static void *construct(int type, void *where, const void *copy)
506 { return QMetaType(type).construct(where, copy); }
507 QT_DEPRECATED_VERSION_6_0
508 static void destruct(int type, void *where)
509 { return QMetaType(type).destruct(where); }
510#endif
511 static bool isRegistered(int type);
512
513 explicit QMetaType(int type);
514 explicit constexpr QMetaType(const QtPrivate::QMetaTypeInterface *d) : d_ptr(d) {}
515 constexpr QMetaType() = default;
516
517#if QT_CORE_REMOVED_SINCE(6, 9)
518 bool isValid() const;
519 bool isRegistered() const;
520#endif
521 constexpr bool isValid(QT6_DECL_NEW_OVERLOAD) const noexcept;
522 inline bool isRegistered(QT6_DECL_NEW_OVERLOAD) const noexcept;
523 void registerType() const
524 {
525 // "register" is a reserved keyword
526 registerHelper();
527 }
528#if QT_CORE_REMOVED_SINCE(6, 1) || defined(Q_QDOC)
529 int id() const;
530#else
531 // ### Qt 7: Remove traces of out of line version
532 // unused int parameter is used to avoid ODR violation
533 int id(int = 0) const
534 {
535 return registerHelper();
536 }
537#endif
538 int rawId() const
539 {
540 Q_PRE(!isValid(QT6_CALL_NEW_OVERLOAD) || isRegistered(QT6_CALL_NEW_OVERLOAD));
541 return d_ptr ? d_ptr->typeId.loadRelaxed() : 0;
542 }
543
544 template <typename Type> constexpr bool isSameType() const
545 {
546 using T = typename QtPrivate::MetatypeDecay<Type>::type;
547 QMetaType other = fromType<T>();
548 if (q20::is_constant_evaluated()) {
549 // There's no registration at constant evaluation time, so equality
550 // only happens if the pointers are equal.
551 return d_ptr == other.iface();
552 } else {
553 using IsBuiltIn = std::bool_constant<QMetaTypeId2<T>::IsBuiltIn>;
554 return isSameTypeHelper<T>(other.iface(), IsBuiltIn{});
555 }
556 }
557
558 constexpr qsizetype sizeOf() const;
559 constexpr qsizetype alignOf() const;
560 constexpr TypeFlags flags() const;
561 constexpr const QMetaObject *metaObject() const;
562 constexpr const char *name() const;
563
564 void *create(const void *copy = nullptr) const;
565 void destroy(void *data) const;
566 void *construct(void *where, const void *copy = nullptr) const;
567 void destruct(void *data) const;
568 QPartialOrdering compare(const void *lhs, const void *rhs) const;
569 bool equals(const void *lhs, const void *rhs) const;
570
571 bool isDefaultConstructible() const noexcept { return d_ptr && isDefaultConstructible(d_ptr); }
572 bool isCopyConstructible() const noexcept { return d_ptr && isCopyConstructible(d_ptr); }
573 bool isMoveConstructible() const noexcept { return d_ptr && isMoveConstructible(d_ptr); }
574 bool isDestructible() const noexcept { return d_ptr && isDestructible(d_ptr); }
575 bool isEqualityComparable() const;
576 bool isOrdered() const;
577
578#ifndef QT_NO_DATASTREAM
579 bool save(QDataStream &stream, const void *data) const;
580 bool load(QDataStream &stream, void *data) const;
581 bool hasRegisteredDataStreamOperators() const;
582
583#if QT_DEPRECATED_SINCE(6, 0)
584 QT_DEPRECATED_VERSION_6_0
585 static bool save(QDataStream &stream, int type, const void *data)
586 { return QMetaType(type).save(stream, data); }
587 QT_DEPRECATED_VERSION_6_0
588 static bool load(QDataStream &stream, int type, void *data)
589 { return QMetaType(type).load(stream, data); }
590#endif
591#endif
592
593 QMetaType underlyingType() const;
594
595 template<typename T>
596 constexpr static QMetaType fromType();
597 static QMetaType fromName(QByteArrayView name);
598private:
599 friend bool comparesEqual(const QMetaType &lhs,
600 const QMetaType &rhs)
601 {
602 if (lhs.d_ptr == rhs.d_ptr)
603 return true;
604 if (!lhs.d_ptr || !rhs.d_ptr)
605 return false; // one type is undefined, the other is defined
606 // avoid id call if we already have the id
607 const int aId = lhs.id();
608 const int bId = rhs.id();
609 return aId == bId;
610 }
611 Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(QMetaType)
612#ifndef QT_NO_DEBUG_STREAM
613private:
614 friend Q_CORE_EXPORT QDebug operator<<(QDebug d, QMetaType m);
615public:
616 bool debugStream(QDebug& dbg, const void *rhs);
617 bool hasRegisteredDebugStreamOperator() const;
618
619#if QT_DEPRECATED_SINCE(6, 0)
620 QT_DEPRECATED_VERSION_6_0
621 static bool debugStream(QDebug& dbg, const void *rhs, int typeId)
622 { return QMetaType(typeId).debugStream(dbg, rhs); }
623 template<typename T>
624 QT_DEPRECATED_VERSION_6_0
625 static bool hasRegisteredDebugStreamOperator()
626 { return QMetaType::fromType<T>().hasRegisteredDebugStreamOperator(); }
627 QT_DEPRECATED_VERSION_6_0
628 static bool hasRegisteredDebugStreamOperator(int typeId)
629 { return QMetaType(typeId).hasRegisteredDebugStreamOperator(); }
630#endif
631#endif
632
633public:
634 // type erased converter function
635 using ConverterFunction = std::function<bool(const void *src, void *target)>;
636
637 // type erased mutable view, primarily for containers
638 using MutableViewFunction = std::function<bool(void *src, void *target)>;
639
640 // implicit conversion supported like double -> float
641 template<typename From, typename To>
642 static bool registerConverter()
643 {
644 return registerConverter<From, To>(QtPrivate::convertImplicit<From, To>);
645 }
646
647 // member function as in "QString QFont::toString() const"
648 template<typename From, typename To>
649 static bool registerConverter(To(From::*function)() const)
650 {
651 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
652 "QMetaType::registerConverter: At least one of the types must be a custom type.");
653
654 const QMetaType fromType = QMetaType::fromType<From>();
655 const QMetaType toType = QMetaType::fromType<To>();
656 auto converter = [function](const void *from, void *to) -> bool {
657 const From *f = static_cast<const From *>(from);
658 To *t = static_cast<To *>(to);
659 *t = (f->*function)();
660 return true;
661 };
662 return registerConverterImpl<From, To>(converter, fromType, toType);
663 }
664
665 // member function
666 template<typename From, typename To>
667 static bool registerMutableView(To(From::*function)())
668 {
669 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
670 "QMetaType::registerMutableView: At least one of the types must be a custom type.");
671
672 const QMetaType fromType = QMetaType::fromType<From>();
673 const QMetaType toType = QMetaType::fromType<To>();
674 auto view = [function](void *from, void *to) -> bool {
675 From *f = static_cast<From *>(from);
676 To *t = static_cast<To *>(to);
677 *t = (f->*function)();
678 return true;
679 };
680 return registerMutableViewImpl<From, To>(view, fromType, toType);
681 }
682
683 // member function as in "double QString::toDouble(bool *ok = nullptr) const"
684 template<typename From, typename To>
685 static bool registerConverter(To(From::*function)(bool*) const)
686 {
687 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
688 "QMetaType::registerConverter: At least one of the types must be a custom type.");
689
690 const QMetaType fromType = QMetaType::fromType<From>();
691 const QMetaType toType = QMetaType::fromType<To>();
692 auto converter = [function](const void *from, void *to) -> bool {
693 const From *f = static_cast<const From *>(from);
694 To *t = static_cast<To *>(to);
695 bool result = true;
696 *t = (f->*function)(&result);
697 if (!result)
698 *t = To();
699 return result;
700 };
701 return registerConverterImpl<From, To>(converter, fromType, toType);
702 }
703
704 // functor or function pointer
705 template<typename From, typename To, typename UnaryFunction>
706 static bool registerConverter(UnaryFunction function)
707 {
708 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
709 "QMetaType::registerConverter: At least one of the types must be a custom type.");
710
711 const QMetaType fromType = QMetaType::fromType<From>();
712 const QMetaType toType = QMetaType::fromType<To>();
713 auto converter = [function = std::move(function)](const void *from, void *to) -> bool {
714 const From *f = static_cast<const From *>(from);
715 To *t = static_cast<To *>(to);
716 decltype(auto) r = function(*f);
717 if constexpr (std::is_same_v<q20::remove_cvref_t<decltype(r)>, std::optional<To>>) {
718 if (!r)
719 return false;
720 *t = *std::forward<decltype(r)>(r);
721 } else {
722 *t = std::forward<decltype(r)>(r);
723 }
724 return true;
725 };
726 return registerConverterImpl<From, To>(std::move(converter), fromType, toType);
727 }
728
729 // functor or function pointer
730 template<typename From, typename To, typename UnaryFunction>
731 static bool registerMutableView(UnaryFunction function)
732 {
733 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
734 "QMetaType::registerMutableView: At least one of the types must be a custom type.");
735
736 const QMetaType fromType = QMetaType::fromType<From>();
737 const QMetaType toType = QMetaType::fromType<To>();
738 auto view = [function = std::move(function)](void *from, void *to) -> bool {
739 From *f = static_cast<From *>(from);
740 To *t = static_cast<To *>(to);
741 *t = function(*f);
742 return true;
743 };
744 return registerMutableViewImpl<From, To>(std::move(view), fromType, toType);
745 }
746
747private:
748 template<typename From, typename To>
749 static bool registerConverterImpl(ConverterFunction converter, QMetaType fromType, QMetaType toType)
750 {
751 if (registerConverterFunction(std::move(converter), fromType, toType)) {
752 static const auto unregister = qScopeGuard([=] {
753 unregisterConverterFunction(fromType, toType);
754 });
755 return true;
756 } else {
757 return false;
758 }
759 }
760
761 template<typename From, typename To>
762 static bool registerMutableViewImpl(MutableViewFunction view, QMetaType fromType, QMetaType toType)
763 {
764 if (registerMutableViewFunction(std::move(view), fromType, toType)) {
765 static const auto unregister = qScopeGuard([=] {
766 unregisterMutableViewFunction(fromType, toType);
767 });
768 return true;
769 } else {
770 return false;
771 }
772 }
773public:
774
775 static bool convert(QMetaType fromType, const void *from, QMetaType toType, void *to);
776 static bool canConvert(QMetaType fromType, QMetaType toType);
777
778 static bool view(QMetaType fromType, void *from, QMetaType toType, void *to);
779 static bool canView(QMetaType fromType, QMetaType toType);
780#if QT_DEPRECATED_SINCE(6, 0)
781 QT_DEPRECATED_VERSION_6_0
782 static bool convert(const void *from, int fromTypeId, void *to, int toTypeId)
783 { return convert(QMetaType(fromTypeId), from, QMetaType(toTypeId), to); }
784 QT_DEPRECATED_VERSION_6_0
785 static bool compare(const void *lhs, const void *rhs, int typeId, int *result)
786 {
787 QMetaType t(typeId);
788 auto c = t.compare(lhs, rhs);
789 if (c == QPartialOrdering::Unordered) {
790 *result = 0;
791 return false;
792 } else if (c == QPartialOrdering::Less) {
793 *result = -1;
794 return true;
795 } else if (c == QPartialOrdering::Equivalent) {
796 *result = 0;
797 return true;
798 } else {
799 *result = 1;
800 return true;
801 }
802 }
803 QT_DEPRECATED_VERSION_6_0
804 static bool equals(const void *lhs, const void *rhs, int typeId, int *result)
805 {
806 QMetaType t(typeId);
807 if (!t.isEqualityComparable())
808 return false;
809 *result = t.equals(lhs, rhs) ? 0 : -1;
810 return true;
811 }
812#endif
813
814 template<typename From, typename To>
815 static bool hasRegisteredConverterFunction()
816 {
817 return hasRegisteredConverterFunction(
818 QMetaType::fromType<From>(), QMetaType::fromType<To>());
819 }
820
821 static bool hasRegisteredConverterFunction(QMetaType fromType, QMetaType toType);
822
823 template<typename From, typename To>
824 static bool hasRegisteredMutableViewFunction()
825 {
826 return hasRegisteredMutableViewFunction(
827 QMetaType::fromType<From>(), QMetaType::fromType<To>());
828 }
829
830 static bool hasRegisteredMutableViewFunction(QMetaType fromType, QMetaType toType);
831
832#ifndef Q_QDOC
833 template<typename, bool> friend struct QtPrivate::SequentialValueTypeIsMetaType;
834 template<typename, bool> friend struct QtPrivate::AssociativeValueTypeIsMetaType;
835 template<typename, bool> friend struct QtPrivate::IsMetaTypePair;
836 template<typename, typename> friend struct QtPrivate::MetaTypeSmartPointerHelper;
837#endif
838 static bool registerConverterFunction(const ConverterFunction &f, QMetaType from, QMetaType to);
839 static void unregisterConverterFunction(QMetaType from, QMetaType to);
840
841 static bool registerMutableViewFunction(const MutableViewFunction &f, QMetaType from, QMetaType to);
842 static void unregisterMutableViewFunction(QMetaType from, QMetaType to);
843
844 static void unregisterMetaType(QMetaType type);
845
846#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
847 constexpr const QtPrivate::QMetaTypeInterface *iface() { return d_ptr; }
848#endif
849 constexpr const QtPrivate::QMetaTypeInterface *iface() const { return d_ptr; }
850
851private:
852 Q_DECL_PURE_FUNCTION static bool isDefaultConstructible(const QtPrivate::QMetaTypeInterface *) noexcept;
853 Q_DECL_PURE_FUNCTION static bool isCopyConstructible(const QtPrivate::QMetaTypeInterface *) noexcept;
854 Q_DECL_PURE_FUNCTION static bool isMoveConstructible(const QtPrivate::QMetaTypeInterface *) noexcept;
855 Q_DECL_PURE_FUNCTION static bool isDestructible(const QtPrivate::QMetaTypeInterface *) noexcept;
856
857 template <typename T> bool
858 isSameTypeHelper(const QtPrivate::QMetaTypeInterface *iface, std::true_type) const noexcept;
859 template <typename T> bool
860 isSameTypeHelper(const QtPrivate::QMetaTypeInterface *iface, std::false_type) const;
861#if QT_CORE_REMOVED_SINCE(6, 5)
862 int idHelper() const;
863#endif
864 static int registerHelper(const QtPrivate::QMetaTypeInterface *iface);
865 int registerHelper() const
866 {
867 if (d_ptr) {
868 if (int id = d_ptr->typeId.loadRelaxed(); Q_LIKELY(id))
869 return id;
870 return registerHelper(d_ptr);
871 }
872 return 0;
873 }
874
875 friend int qRegisterMetaType(QMetaType meta);
876
877 friend class QVariant;
878 const QtPrivate::QMetaTypeInterface *d_ptr = nullptr;
879};
880
881#undef QT_DEFINE_METATYPE_ID
882
883Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags)
884
885#define QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(C, F)
886 }
887 Q_DECLARE_TYPEINFO(QtMetaTypePrivate:: C, (F));
888 namespace QtMetaTypePrivate {
889
890
892
894{
895public:
896 const void *_pair;
899
900 typedef void (*getFunc)(const void * const *p, void *);
901
904
905 template<class T>
906 static void getFirstImpl(const void * const *pair, void *dataPtr)
907 { *static_cast<typename T::first_type *>(dataPtr) = static_cast<const T*>(*pair)->first; }
908 template<class T>
909 static void getSecondImpl(const void * const *pair, void *dataPtr)
910 { *static_cast<typename T::second_type *>(dataPtr) = static_cast<const T*>(*pair)->second; }
911
912public:
913 template<class T> QPairVariantInterfaceImpl(const T*p)
914 : _pair(p)
917 , _getFirst(getFirstImpl<T>)
918 , _getSecond(getSecondImpl<T>)
919 {
920 }
921
923 : _pair(nullptr)
924 , _getFirst(nullptr)
925 , _getSecond(nullptr)
926 {
927 }
928
929 inline void first(void *dataPtr) const { _getFirst(&_pair, dataPtr); }
930 inline void second(void *dataPtr) const { _getSecond(&_pair, dataPtr); }
931};
933
934template<typename From>
936
937template<typename T, typename U>
939{
940 QPairVariantInterfaceImpl operator()(const std::pair<T, U>& f) const
941 {
942 return QPairVariantInterfaceImpl(&f);
943 }
944};
945
946}
947
948class QObject;
949
950#define QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER(Name)
951 template <class T> class Name;
952
953QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER)
954
955namespace QtPrivate
956{
957 // Note: this does not check that T = U* isn't pointing to a
958 // forward-declared type. You may want to combine with
959 // checkTypeIsSuitableForMetaType().
960 template<typename T>
962 {
963 enum { Value = false };
964 };
965
966 // Specialize to avoid sizeof(void) warning
967 template<>
969 {
970 enum { Value = false };
971 };
972 template<>
974 {
975 enum { Value = false };
976 };
977 template<>
979 {
980 enum { Value = true };
981 };
982
983 template<typename T>
985 {
988
989#ifndef QT_NO_QOBJECT
990 static yes_type checkType(QObject* );
991 static yes_type checkType(const QObject* );
992#endif
993 static no_type checkType(...);
994 enum { Value = sizeof(checkType(static_cast<T*>(nullptr))) == sizeof(yes_type) };
995 };
996
997 template<typename T, typename Enable = void>
998 struct IsGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; };
999
1000 template<typename T>
1001 struct IsGadgetHelper<T, typename T::QtGadgetHelper>
1002 {
1003 template <typename X>
1004 static char checkType(void (X::*)());
1005 static void *checkType(void (T::*)());
1006 enum {
1007 IsRealGadget = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *),
1009 };
1010 };
1011
1012 template <typename T>
1014
1015 template<typename T, typename Enable = void>
1016 struct IsPointerToGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; };
1017
1018 template<typename T>
1020 {
1021 using BaseType = T;
1022 template <typename X>
1023 static char checkType(void (X::*)());
1024 static void *checkType(void (T::*)());
1025 enum {
1026 IsRealGadget = !IsPointerToTypeDerivedFromQObject<T*>::Value && sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *),
1028 };
1029 };
1030
1031
1032 template<typename T> char qt_getEnumMetaObject(const T&);
1033
1034 template<typename T>
1036 static const T &declval();
1037 // If the type was declared with Q_ENUM, the friend qt_getEnumMetaObject() declared in the
1038 // Q_ENUM macro will be chosen by ADL, and the return type will be QMetaObject*.
1039 // Otherwise the chosen overload will be the catch all template function
1040 // qt_getEnumMetaObject(T) which returns 'char'
1041 enum { Value = sizeof(qt_getEnumMetaObject(declval())) == sizeof(QMetaObject*) };
1042 };
1043 template<> struct IsQEnumHelper<void> { enum { Value = false }; };
1044
1045 template<typename T, typename Enable = void>
1047 {
1048 static constexpr const QMetaObject *value() { return nullptr; }
1049 using MetaObjectFn = const QMetaObject *(*)(const QMetaTypeInterface *);
1050 static constexpr MetaObjectFn metaObjectFunction = nullptr;
1051 };
1052#ifndef QT_NO_QOBJECT
1053 template<typename T>
1055 {
1056 static constexpr const QMetaObject *value() { return &T::staticMetaObject; }
1057 static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return &T::staticMetaObject; }
1058 };
1059 template<typename T>
1064 >
1065 >>
1066 {
1067 static constexpr const QMetaObject *value() { return &T::staticMetaObject; }
1068 static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return &T::staticMetaObject; }
1069 };
1070 template<typename T>
1072 {
1073 static constexpr const QMetaObject *value()
1074 {
1076 }
1077 static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return value(); }
1078 };
1079 template<typename T>
1081 {
1082 static constexpr const QMetaObject *value() { return qt_getEnumMetaObject(T()); }
1083 static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return value(); }
1084 };
1085#endif
1086
1087 template<typename T>
1089 {
1090 enum { Value = false };
1091 };
1092
1093 template<typename T>
1097
1098 template<typename T>
1100 {
1101 enum { Value = false };
1102 };
1103
1104 template<typename T>
1108
1109 template<typename T>
1111 {
1112 enum { Value = false };
1113 };
1114
1115 template<typename T>
1117 {
1118 enum { Value = true };
1119 };
1120
1121 template<typename T>
1123 {
1124 enum { Value = false };
1125 };
1126
1127 template<typename T>
1129 {
1130 enum { Value = false };
1131 };
1132
1133 /* Used to check whether we need to register a converter function
1134 for associative and sequential containers.
1135 The rule is that for any registered container (template), we register
1136 the conversion function if the element type is "defined" in the sense
1137 of QMetaTypeId2, or if it's a pointer to a QObject subclass or a
1138 default-constructible gadget (for the rare non-default constructible gadgets,
1139 we can't create the converter.
1140 */
1141 template<typename T>
1149
1150 template<typename T, bool = QtPrivate::IsSequentialContainer<T>::Value>
1152 {
1153 static bool registerConverter()
1154 {
1155 return false;
1156 }
1157
1159 {
1160 return false;
1161 }
1162 };
1163
1164 template<typename T, bool = IsContainerElementWhichNeedsConverter<typename T::value_type>::value>
1166 {
1167 static bool registerConverter()
1168 {
1169 return false;
1170 }
1171
1173 {
1174 return false;
1175 }
1176 };
1177
1178 template<typename T>
1182
1183 template<typename T, bool = QtPrivate::IsAssociativeContainer<T>::Value>
1185 {
1186 static bool registerConverter()
1187 {
1188 return false;
1189 }
1190
1192 {
1193 return false;
1194 }
1195 };
1196
1197 template<typename T, bool = IsContainerElementWhichNeedsConverter<typename T::key_type>::value>
1199 {
1200 static bool registerConverter()
1201 {
1202 return false;
1203 }
1204
1206 {
1207 return false;
1208 }
1209 };
1210
1211 template<typename T, bool = IsContainerElementWhichNeedsConverter<typename T::mapped_type>::value>
1213 {
1214 static bool registerConverter()
1215 {
1216 return false;
1217 }
1218
1220 {
1221 return false;
1222 }
1223 };
1224
1225 template<typename T>
1229
1230 template<typename T, bool = IsContainerElementWhichNeedsConverter<typename T::first_type>::value
1231 && IsContainerElementWhichNeedsConverter<typename T::second_type>::value>
1233 {
1234 static bool registerConverter()
1235 {
1236 return false;
1237 }
1238 };
1239
1240 template<typename T>
1241 struct IsMetaTypePair<T, true>
1242 {
1243 inline static bool registerConverter();
1244 };
1245
1246 template<typename T>
1247 struct IsPair
1248 {
1249 static bool registerConverter()
1250 {
1251 return false;
1252 }
1253 };
1254 template<typename T, typename U>
1255 struct IsPair<std::pair<T, U> > : IsMetaTypePair<std::pair<T, U> > {};
1256
1257 template<typename T>
1259
1260 template<typename T, typename = void>
1262 {
1263 static bool registerConverter() { return false; }
1264 };
1265
1266#if QT_CONFIG(future)
1267 template<typename T>
1269 {
1270 static bool registerConverter() { return false; }
1271 };
1272#endif
1273
1274} // namespace QtPrivate
1275
1276template <typename T, int =
1280{
1281 enum {
1283 };
1284};
1285
1286template <typename T>
1288{
1289};
1290
1291template <typename T>
1293{
1294 using NameAsArrayType = void;
1295 enum { Defined = QMetaTypeId<T>::Defined, IsBuiltIn=false };
1296 static inline constexpr int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }
1297};
1298
1299template <typename T>
1300struct QMetaTypeId2<const T&> : QMetaTypeId2<T> {};
1301
1302template <typename T>
1304{
1305 using NameAsArrayType = void;
1306 enum { Defined = false, IsBuiltIn = false };
1307 static inline constexpr int qt_metatype_id() { return 0; }
1308};
1309
1310namespace QtPrivate {
1311 template <typename T, bool Defined = QMetaTypeId2<T>::Defined>
1313 static inline constexpr int qt_metatype_id()
1314 { return QMetaTypeId2<T>::qt_metatype_id(); }
1315 };
1316 template <typename T> struct QMetaTypeIdHelper<T, false> {
1317 static inline constexpr int qt_metatype_id()
1318 { return -1; }
1319 };
1320
1321 // Function pointers don't derive from QObject
1322 template <typename Result, typename... Args>
1323 struct IsPointerToTypeDerivedFromQObject<Result(*)(Args...)> { enum { Value = false }; };
1324
1325 template<typename T>
1326 inline constexpr bool IsQmlListType = false;
1327
1328 template<typename T, bool = std::is_enum<T>::value>
1329 constexpr bool IsUnsignedEnum = false;
1330 template<typename T>
1331 constexpr bool IsUnsignedEnum<T, true> = !std::is_signed_v<std::underlying_type_t<T>>;
1332
1333 template<typename T, bool defined>
1335 {
1336 enum DefinedType { Defined = defined };
1337 };
1338
1339 template<typename SmartPointer>
1341 {
1342 QObject* operator()(const SmartPointer &p) const
1343 {
1344 return p.operator->();
1345 }
1346 };
1347
1348 // hack to delay name lookup to instantiation time by making
1349 // EnableInternalData a dependent name:
1350 template <typename T>
1352
1353 template<typename T>
1355 {
1356 QObject* operator()(const QWeakPointer<T> &p) const
1357 {
1358 return QtPrivate::EnableInternalDataWrap<T>::internalData(p);
1359 }
1360 };
1361}
1362
1363template <typename T>
1364int qRegisterNormalizedMetaTypeImplementation(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName)
1365{
1366#ifndef QT_NO_QOBJECT
1367 Q_ASSERT_X(normalizedTypeName == QMetaObject::normalizedType(normalizedTypeName.constData()),
1368 "qRegisterNormalizedMetaType",
1369 "qRegisterNormalizedMetaType was called with a not normalized type name, "
1370 "please call qRegisterMetaType instead.");
1371#endif
1372
1373 const QMetaType metaType = QMetaType::fromType<T>();
1374 const int id = metaType.id();
1375
1376 QtPrivate::SequentialContainerTransformationHelper<T>::registerConverter();
1377 QtPrivate::SequentialContainerTransformationHelper<T>::registerMutableView();
1378 QtPrivate::AssociativeContainerTransformationHelper<T>::registerConverter();
1379 QtPrivate::AssociativeContainerTransformationHelper<T>::registerMutableView();
1380 QtPrivate::MetaTypePairHelper<T>::registerConverter();
1381 QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter();
1382#if QT_CONFIG(future)
1383 QtPrivate::MetaTypeQFutureHelper<T>::registerConverter();
1384#endif
1385
1386 if (normalizedTypeName != metaType.name())
1387 QMetaType::registerNormalizedTypedef(normalizedTypeName, metaType);
1388
1389 return id;
1390}
1391
1392// This primary template calls the -Implementation, like all other specialisations should.
1393// But the split allows to
1394// - in a header:
1395// - define a specialization of this template calling an out-of-line function
1396// (QT_DECL_METATYPE_EXTERN{,_TAGGED})
1397// - in the .cpp file:
1398// - define the out-of-line wrapper to call the -Implementation
1399// (QT_IMPL_METATYPE_EXTERN{,_TAGGED})
1400// The _TAGGED variants let you choose a tag (must be a C identifier) to disambiguate
1401// the out-of-line function; the non-_TAGGED variants use the passed class name as tag.
1402template <typename T>
1403int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName)
1404{
1405 return qRegisterNormalizedMetaTypeImplementation<T>(normalizedTypeName);
1406}
1407
1408#if defined(QT_BOOTSTRAPPED)
1409#define QT_DECL_METATYPE_EXTERN_TAGGED(TYPE, TAG, EXPORT)
1410#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG)
1411#else
1412#define QT_DECL_METATYPE_EXTERN_TAGGED(TYPE, TAG, EXPORT)
1413 QT_BEGIN_NAMESPACE
1414 EXPORT int qRegisterNormalizedMetaType_ ## TAG (const QByteArray &);
1415 template <> inline int qRegisterNormalizedMetaType< TYPE >(const QByteArray &name)
1416 { return qRegisterNormalizedMetaType_ ## TAG (name); }
1417 QT_END_NAMESPACE
1418 Q_DECLARE_METATYPE(TYPE)
1419 /* end */
1420#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG)
1421 int qRegisterNormalizedMetaType_ ## TAG (const QByteArray &name)
1422 { return qRegisterNormalizedMetaTypeImplementation< TYPE >(name); }
1423 /* end */
1424#endif
1425#define QT_DECL_METATYPE_EXTERN(TYPE, EXPORT)
1426 QT_DECL_METATYPE_EXTERN_TAGGED(TYPE, TYPE, EXPORT)
1427#define QT_IMPL_METATYPE_EXTERN(TYPE)
1429
1430template <typename T>
1431int qRegisterMetaType(const char *typeName)
1432{
1433#ifdef QT_NO_QOBJECT
1434 QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = typeName;
1435#else
1436 QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
1437#endif
1438 return qRegisterNormalizedMetaType<T>(normalizedTypeName);
1439}
1440
1441template <typename T>
1442inline constexpr int qMetaTypeId()
1443{
1444 if constexpr (bool(QMetaTypeId2<T>::IsBuiltIn)) {
1445 // this has the same result as the below code, but avoids asking the
1446 // compiler to load a global variable whose value we know at compile
1447 // time
1448 return QMetaTypeId2<T>::MetaType;
1449 } else {
1450 return QMetaType::fromType<T>().id();
1451 }
1452}
1453
1454template <typename T>
1455inline constexpr int qRegisterMetaType()
1456{
1457 int id = qMetaTypeId<T>();
1458 return id;
1459}
1460
1461inline int qRegisterMetaType(QMetaType meta)
1462{
1463 return meta.registerHelper();
1464}
1465
1466#ifndef QT_NO_QOBJECT
1467template <typename T>
1468struct QMetaTypeIdQObject<T*, QMetaType::PointerToGadget>
1469{
1470 enum {
1471 Defined = 1
1472 };
1473
1474 static int qt_metatype_id()
1475 {
1476 // register the actual gadget type too
1477 QMetaType::fromType<std::remove_cv_t<T>>().registerType();
1478 if constexpr (std::is_const_v<T>)
1479 QMetaType::fromType<T>().registerType();
1480 return QMetaType::fromType<T *>().id();
1481 }
1482};
1483
1484template <typename T>
1485struct QMetaTypeIdQObject<T, QMetaType::IsEnumeration>
1486{
1487 enum {
1488 Defined = 1
1489 };
1490
1491 static int qt_metatype_id()
1492 {
1493 Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1494 if (const int id = metatype_id.loadAcquire())
1495 return id;
1496 // qt_getEnumName returns what was passed to Q_ENUM/Q_FLAG
1497 // which might be different from the actual name
1498 const char *eName = qt_getEnumName(T());
1499 const char *cName = qt_getEnumMetaObject(T())->className();
1500 QByteArray typeName;
1501 constexpr bool isConst = std::is_const_v<T>;
1502 typeName.reserve(strlen(cName) + 2 + strlen(eName) + (isConst ? strlen("const ") : 0));
1503 if constexpr (isConst)
1504 typeName.append("const ");
1505 typeName.append(cName).append("::").append(eName);
1506 const int newId = qRegisterNormalizedMetaType<T>(typeName);
1507 metatype_id.storeRelease(newId);
1508 return newId;
1509 }
1510};
1511#endif
1512
1513#define Q_DECLARE_OPAQUE_POINTER(POINTER)
1514 QT_BEGIN_NAMESPACE namespace QtPrivate {
1515 template <> struct IsPointerDeclaredOpaque<POINTER>
1516 : std::true_type {};
1517 } QT_END_NAMESPACE
1518 /**/
1519
1520#ifndef Q_MOC_RUN
1521#define Q_DECLARE_METATYPE(TYPE) Q_DECLARE_METATYPE_IMPL(TYPE)
1522#define Q_DECLARE_METATYPE_IMPL(TYPE)
1523 QT_BEGIN_NAMESPACE
1524 template <>
1525 struct QMetaTypeId< TYPE >
1526 {
1527 enum { Defined = 1 };
1528 static_assert(QtPrivate::checkTypeIsSuitableForMetaType<TYPE>());
1529 static int qt_metatype_id()
1530 {
1531 Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1532 if (const int id = metatype_id.loadAcquire())
1533 return id;
1534 constexpr auto arr = QtPrivate::typenameHelper<TYPE>();
1535 auto name = arr.data();
1536 if (QByteArrayView(name) == (#TYPE)) {
1537 const int id = qRegisterNormalizedMetaType<TYPE>(name);
1538 metatype_id.storeRelease(id);
1539 return id;
1540 }
1541 const int newId = qRegisterMetaType< TYPE >(#TYPE);
1542 metatype_id.storeRelease(newId);
1543 return newId;
1544 }
1545 };
1546 QT_END_NAMESPACE
1547#endif // Q_MOC_RUN
1548
1549#define Q_DECLARE_BUILTIN_METATYPE(TYPE, METATYPEID, NAME)
1550 QT_BEGIN_NAMESPACE
1551 template<> struct QMetaTypeId2<NAME>
1552 {
1553 using NameAsArrayType = std::array<char, sizeof(#NAME)>;
1554 enum { Defined = 1, IsBuiltIn = true, MetaType = METATYPEID };
1555 static inline constexpr int qt_metatype_id() { return METATYPEID; }
1556 static constexpr NameAsArrayType nameAsArray = { #NAME };
1557 };
1558 QT_END_NAMESPACE
1559
1560#define QT_FORWARD_DECLARE_STATIC_TYPES_ITER(TypeName, TypeId, Name)
1561 class Name;
1562
1563QT_FOR_EACH_STATIC_CORE_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1564QT_FOR_EACH_STATIC_GUI_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1565QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1566
1567#undef QT_FORWARD_DECLARE_STATIC_TYPES_ITER
1568
1569#define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE) QT_BEGIN_NAMESPACE
1570 template
1571 <typename T> struct
1572 QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \
1573{
1574 enum {
1575 Defined = QtPrivate::IsContainerElementWhichNeedsConverter<T>::value
1576 };
1577 static int qt_metatype_id()
1578 {
1579 Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1580 if (const int id = metatype_id.loadRelaxed())
1581 return id;
1582 const char *tName = QMetaType::fromType<T>().name();
1583 Q_ASSERT(tName);
1584 const size_t tNameLen = qstrlen(tName);
1585 QByteArray typeName;
1586 typeName.reserve(sizeof(#SINGLE_ARG_TEMPLATE) + 1 + tNameLen + 1 + 1);
1587 typeName.append(#SINGLE_ARG_TEMPLATE, int(sizeof(#SINGLE_ARG_TEMPLATE)) - 1)
1588 .append('<').append(tName, tNameLen);
1589 typeName.append('>');
1590 const int newId = qRegisterNormalizedMetaType< SINGLE_ARG_TEMPLATE<T> >(typeName);
1591 metatype_id.storeRelease(newId);
1592 return newId;
1593 } \
1594};QT_END_NAMESPACE
1595
1596
1597#define Q_DECLARE_METATYPE_TEMPLATE_2ARG(DOUBLE_ARG_TEMPLATE) QT_BEGIN_NAMESPACE
1598 template
1599 <typename T, typename U> struct
1600 QMetaTypeId< DOUBLE_ARG_TEMPLATE<T, U> > \
1601{
1602 enum {
1603 Defined = QtPrivate::IsContainerElementWhichNeedsConverter<T>::value
1604 && QtPrivate::IsContainerElementWhichNeedsConverter<U>::value
1605 };
1606 static int qt_metatype_id()
1607 {
1608 Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1609 if (const int id = metatype_id.loadAcquire())
1610 return id;
1611 const char *tName = QMetaType::fromType<T>().name();
1612 const char *uName = QMetaType::fromType<U>().name();
1613 Q_ASSERT(tName);
1614 Q_ASSERT(uName);
1615 const size_t tNameLen = qstrlen(tName);
1616 const size_t uNameLen = qstrlen(uName);
1617 QByteArray typeName;
1618 typeName.reserve(sizeof(#DOUBLE_ARG_TEMPLATE) + 1 + tNameLen + 1 + uNameLen + 1 + 1);
1619 typeName.append(#DOUBLE_ARG_TEMPLATE, int(sizeof(#DOUBLE_ARG_TEMPLATE)) - 1)
1620 .append('<').append(tName, tNameLen).append(',').append(uName, uNameLen);
1621 typeName.append('>');
1622 const int newId = qRegisterNormalizedMetaType< DOUBLE_ARG_TEMPLATE<T, U> >(typeName);
1623 metatype_id.storeRelease(newId);
1624 return newId;
1625 } \
1626};QT_END_NAMESPACE
1627
1628
1629namespace QtPrivate {
1630
1631template<typename T, bool /* isSharedPointerToQObjectDerived */ = false>
1633{
1634 enum {
1636 };
1637 static int qt_metatype_id()
1638 {
1639 return -1;
1640 }
1641};
1642
1643}
1644
1645#define Q_DECLARE_SMART_POINTER_METATYPE(SMART_POINTER) QT_BEGIN_NAMESPACE
1646 namespace
1647 QtPrivate { template
1648 <typename T> struct
1649 SharedPointerMetaTypeIdHelper<SMART_POINTER<T>, true> \
1650{
1651 enum {
1652 Defined = 1
1653 };
1654 static int qt_metatype_id()
1655 {
1656 Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1657 if (const int id = metatype_id.loadAcquire())
1658 return id;
1659 const char * const cName = T::staticMetaObject.className();
1660 QByteArray typeName;
1661 typeName.reserve(sizeof(#SMART_POINTER) + 1 + strlen(cName) + 1);
1662 typeName.append(#SMART_POINTER, int(sizeof(#SMART_POINTER)) - 1)
1663 .append('<').append(cName).append('>');
1664 const int newId = qRegisterNormalizedMetaType< SMART_POINTER<T> >(typeName);
1665 metatype_id.storeRelease(newId);
1666 return newId;
1667 } \
1668};template
1669 <typename T> struct
1670 MetaTypeSmartPointerHelper<SMART_POINTER<T> ,
1671 typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value && !std::is_const_v<T>>::type> \
1672{
1673 static bool registerConverter()
1674 {
1675 const QMetaType to = QMetaType(QMetaType::QObjectStar);
1676 if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<SMART_POINTER<T>>(), to)) {
1677 QtPrivate::QSmartPointerConvertFunctor<SMART_POINTER<T> > o;
1678 return QMetaType::registerConverter<SMART_POINTER<T>, QObject*>(o);
1679 }
1680 return true;
1681 } \
1682};\
1683}template
1684 <typename T> struct
1685 QMetaTypeId< SMART_POINTER<T> >
1686 : QtPrivate::SharedPointerMetaTypeIdHelper< SMART_POINTER<T>,
1687 QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value> \
1688{\
1689};QT_END_NAMESPACE
1690
1691
1692#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(SINGLE_ARG_TEMPLATE)
1693 QT_BEGIN_NAMESPACE
1694 namespace QtPrivate {
1695 template<typename T>
1696 struct IsSequentialContainer<SINGLE_ARG_TEMPLATE<T> >
1697 {
1698 enum { Value = true };
1699 };
1700 }
1701 QT_END_NAMESPACE
1702 Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE)
1703
1704#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER(TEMPLATENAME)
1706
1708
1710
1711#undef Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER
1712
1715
1716#define Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(TEMPLATENAME)
1717 QT_BEGIN_NAMESPACE
1718 namespace QtPrivate {
1719 template<typename T, typename U>
1720 struct IsAssociativeContainer<TEMPLATENAME<T, U> >
1721 {
1722 enum { Value = true };
1723 };
1724 }
1725 QT_END_NAMESPACE
1727
1731
1733
1734#define Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER(TEMPLATENAME)
1736
1738
1740
1741#undef Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER
1742
1743QT_END_NAMESPACE
1744
1746
1747
1749
1750namespace QtPrivate {
1751// out-of-line helpers to reduce template code bloat ("SCARY") and improve compile times:
1752Q_CORE_EXPORT bool hasRegisteredConverterFunctionToPairVariantInterface(QMetaType m);
1753Q_CORE_EXPORT bool hasRegisteredConverterFunctionToIterableMetaSequence(QMetaType m);
1754Q_CORE_EXPORT bool hasRegisteredMutableViewFunctionToIterableMetaSequence(QMetaType m);
1755Q_CORE_EXPORT bool hasRegisteredConverterFunctionToIterableMetaAssociation(QMetaType m);
1756Q_CORE_EXPORT bool hasRegisteredMutableViewFunctionToIterableMetaAssociation(QMetaType m);
1757}
1758
1759template <typename T>
1761{
1764 return QMetaType::registerConverter<T, QtMetaTypePrivate::QPairVariantInterfaceImpl>(o);
1765 }
1766 return true;
1767}
1768
1769namespace QtPrivate {
1770
1771template<typename From>
1773{
1774 QIterable<QMetaSequence> operator()(const From &f) const
1775 {
1776 return QIterable<QMetaSequence>(QMetaSequence::fromContainer<From>(), &f);
1777 }
1778};
1779
1780template<typename From>
1782{
1784 {
1785 return QIterable<QMetaSequence>(QMetaSequence::fromContainer<From>(), &f);
1786 }
1787};
1788
1789template<typename T>
1791{
1792 static bool registerConverter()
1793 {
1796 return QMetaType::registerConverter<T, QIterable<QMetaSequence>>(o);
1797 }
1798 return true;
1799 }
1800
1802 {
1805 return QMetaType::registerMutableView<T, QIterable<QMetaSequence>>(o);
1806 }
1807 return true;
1808 }
1809};
1810
1811template<typename From>
1813{
1814 QIterable<QMetaAssociation> operator()(const From &f) const
1815 {
1816 return QIterable<QMetaAssociation>(QMetaAssociation::fromContainer<From>(), &f);
1817 }
1818};
1819
1820template<typename From>
1822{
1824 {
1825 return QIterable<QMetaAssociation>(QMetaAssociation::fromContainer<From>(), &f);
1826 }
1827};
1828
1829// Mapped type can be omitted, for example in case of a set.
1830// However, if it is available, we want to instantiate the metatype here.
1831template<typename T>
1833{
1834 static bool registerConverter()
1835 {
1838 return QMetaType::registerConverter<T, QIterable<QMetaAssociation>>(o);
1839 }
1840 return true;
1841 }
1842
1844 {
1847 return QMetaType::registerMutableView<T, QIterable<QMetaAssociation>>(o);
1848 }
1849 return true;
1850 }
1851};
1852
1854{
1855 char *output;
1856 int len = 0;
1857 char last = 0;
1858
1859private:
1860 static constexpr bool is_ident_char(char s)
1861 {
1862 return ((s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z') || (s >= '0' && s <= '9')
1863 || s == '_');
1864 }
1865 static constexpr bool is_space(char s) { return (s == ' ' || s == '\t' || s == '\n'); }
1866 static constexpr bool is_number(char s) { return s >= '0' && s <= '9'; }
1867 static constexpr bool starts_with_token(const char *b, const char *e, const char *token,
1868 bool msvcKw = false)
1869 {
1870 while (b != e && *token && *b == *token) {
1871 b++;
1872 token++;
1873 }
1874 if (*token)
1875 return false;
1876#ifdef Q_CC_MSVC
1877 /// On MSVC, keywords like class or struct are not separated with spaces in constexpr
1878 /// context
1879 if (msvcKw && !is_ident_char(*b))
1880 return true;
1881#endif
1882 Q_UNUSED(msvcKw);
1883 return b == e || !is_ident_char(*b);
1884 }
1885 static constexpr bool skipToken(const char *&x, const char *e, const char *token,
1886 bool msvcKw = false)
1887 {
1888 if (!starts_with_token(x, e, token, msvcKw))
1889 return false;
1890 while (*token++)
1891 x++;
1892 while (x != e && is_space(*x))
1893 x++;
1894 return true;
1895 }
1896 static constexpr const char *skipString(const char *x, const char *e)
1897 {
1898 char delim = *x;
1899 x++;
1900 while (x != e && *x != delim) {
1901 if (*x == '\\') {
1902 x++;
1903 if (x == e)
1904 return e;
1905 }
1906 x++;
1907 }
1908 if (x != e)
1909 x++;
1910 return x;
1911 }
1912 static constexpr const char *skipTemplate(const char *x, const char *e, bool stopAtComa = false)
1913 {
1914 int scopeDepth = 0;
1915 int templateDepth = 0;
1916 while (x != e) {
1917 switch (*x) {
1918 case '<':
1919 if (!scopeDepth)
1920 templateDepth++;
1921 break;
1922 case ',':
1923 if (stopAtComa && !scopeDepth && !templateDepth)
1924 return x;
1925 break;
1926 case '>':
1927 if (!scopeDepth)
1928 if (--templateDepth < 0)
1929 return x;
1930 break;
1931 case '(':
1932 case '[':
1933 case '{':
1934 scopeDepth++;
1935 break;
1936 case '}':
1937 case ']':
1938 case ')':
1939 scopeDepth--;
1940 break;
1941 case '\'':
1942 if (is_number(x[-1]))
1943 break;
1944 Q_FALLTHROUGH();
1945 case '\"':
1946 x = skipString(x, e);
1947 continue;
1948 }
1949 x++;
1950 }
1951 return x;
1952 }
1953
1954 constexpr void append(char x)
1955 {
1956 last = x;
1957 len++;
1958 if (output)
1959 *output++ = x;
1960 }
1961
1962 constexpr void replaceLast(char x)
1963 {
1964 last = x;
1965 if (output)
1966 *(output - 1) = x;
1967 }
1968
1969 constexpr void appendStr(const char *x)
1970 {
1971 while (*x)
1972 append(*x++);
1973 }
1974
1975 constexpr void normalizeIntegerTypes(const char *&begin, const char *end)
1976 {
1977 int numLong = 0;
1978 int numSigned = 0;
1979 int numUnsigned = 0;
1980 int numInt = 0;
1981 int numShort = 0;
1982 int numChar = 0;
1983 while (begin < end) {
1984 if (skipToken(begin, end, "long")) {
1985 numLong++;
1986 continue;
1987 }
1988 if (skipToken(begin, end, "int")) {
1989 numInt++;
1990 continue;
1991 }
1992 if (skipToken(begin, end, "short")) {
1993 numShort++;
1994 continue;
1995 }
1996 if (skipToken(begin, end, "unsigned")) {
1997 numUnsigned++;
1998 continue;
1999 }
2000 if (skipToken(begin, end, "signed")) {
2001 numSigned++;
2002 continue;
2003 }
2004 if (skipToken(begin, end, "char")) {
2005 numChar++;
2006 continue;
2007 }
2008#ifdef Q_CC_MSVC
2009 if (skipToken(begin, end, "__int64")) {
2010 numLong = 2;
2011 continue;
2012 }
2013#endif
2014 break;
2015 }
2016 if (numLong == 2)
2017 append('q'); // q(u)longlong
2018 if (numSigned && numChar)
2019 appendStr("signed ");
2020 else if (numUnsigned)
2021 appendStr("u");
2022 if (numChar)
2023 appendStr("char");
2024 else if (numShort)
2025 appendStr("short");
2026 else if (numLong == 1)
2027 appendStr("long");
2028 else if (numLong == 2)
2029 appendStr("longlong");
2030 else if (numUnsigned || numSigned || numInt)
2031 appendStr("int");
2032 }
2033
2034 constexpr void skipStructClassOrEnum(const char *&begin, const char *end)
2035 {
2036 // discard 'struct', 'class', and 'enum'; they are optional
2037 // and we don't want them in the normalized signature
2038 skipToken(begin, end, "struct", true) || skipToken(begin, end, "class", true)
2039 || skipToken(begin, end, "enum", true);
2040 }
2041
2042 constexpr void skipQtNamespace(const char *&begin, const char *end)
2043 {
2044#ifdef QT_NAMESPACE
2045 const char *nsbeg = begin;
2046 if (skipToken(nsbeg, end, QT_STRINGIFY(QT_NAMESPACE)) && nsbeg + 2 < end && nsbeg[0] == ':'
2047 && nsbeg[1] == ':') {
2048 begin = nsbeg + 2;
2049 while (begin != end && is_space(*begin))
2050 begin++;
2051 }
2052#else
2053 Q_UNUSED(begin);
2054 Q_UNUSED(end);
2055#endif
2056 }
2057
2058public:
2059#if defined(Q_CC_CLANG) || defined (Q_CC_GNU)
2060 // this is much simpler than the full type normalization below
2061 // the reason is that the signature returned by Q_FUNC_INFO is already
2062 // normalized to the largest degree, and we need to do only small adjustments
2063 constexpr int normalizeTypeFromSignature(const char *begin, const char *end)
2064 {
2065 // bail out if there is an anonymous struct
2067#if defined (Q_CC_CLANG)
2068 if (name.find("anonymous ") != std::string_view::npos)
2069 return normalizeType(begin, end);
2070#endif
2071 if (name.find("unnamed ") != std::string_view::npos)
2072 return normalizeType(begin, end);
2073 while (begin < end) {
2074 if (*begin == ' ') {
2075 if (last == ',' || last == '>' || last == '<' || last == '*' || last == '&') {
2076 ++begin;
2077 continue;
2078 }
2079 }
2080 if (last == ' ') {
2081 if (*begin == '*' || *begin == '&' || *begin == '(') {
2083 ++begin;
2084 continue;
2085 }
2086 }
2087 if (!is_ident_char(last)) {
2089 if (begin == end)
2090 break;
2091
2093 if (begin == end)
2094 break;
2095
2097 if (begin == end)
2098 break;
2099 }
2100 append(*begin);
2101 ++begin;
2102 }
2103 return len;
2104 }
2105#else
2106 // MSVC needs the full normalization, as it puts the const in a different
2107 // place than we expect
2108 constexpr int normalizeTypeFromSignature(const char *begin, const char *end)
2109 { return normalizeType(begin, end); }
2110#endif
2111
2112 constexpr int normalizeType(const char *begin, const char *end, bool adjustConst = true)
2113 {
2114 // Trim spaces
2115 while (begin != end && is_space(*begin))
2116 begin++;
2117 while (begin != end && is_space(*(end - 1)))
2118 end--;
2119
2120 if (begin == end)
2121 return len;
2122
2123 // Convert 'char const *' into 'const char *'. Start at index 1,
2124 // not 0, because 'const char *' is already OK.
2125 const char *cst = begin + 1;
2126 if (*begin == '\'' || *begin == '"')
2127 cst = skipString(begin, end);
2128 bool seenStar = false;
2129 bool hasMiddleConst = false;
2130 while (cst < end) {
2131 if (*cst == '\"' || (*cst == '\'' && !is_number(cst[-1]))) {
2132 cst = skipString(cst, end);
2133 if (cst == end)
2134 break;
2135 }
2136
2137 // We mustn't convert 'char * const *' into 'const char **'
2138 // and we must beware of 'Bar<const Bla>'.
2139 if (*cst == '&' || *cst == '*' || *cst == '[') {
2140 seenStar = *cst != '&' || cst != (end - 1);
2141 break;
2142 }
2143 if (*cst == '<') {
2144 cst = skipTemplate(cst + 1, end);
2145 if (cst == end)
2146 break;
2147 }
2148 cst++;
2149 const char *skipedCst = cst;
2150 if (!is_ident_char(*(cst - 1)) && skipToken(skipedCst, end, "const")) {
2151 const char *testEnd = end;
2152 while (skipedCst < testEnd--) {
2153 if (*testEnd == '*' || *testEnd == '['
2154 || (*testEnd == '&' && testEnd != (end - 1))) {
2155 seenStar = true;
2156 break;
2157 }
2158 if (*testEnd == '>')
2159 break;
2160 }
2161 if (adjustConst && !seenStar) {
2162 if (*(end - 1) == '&')
2163 end--;
2164 } else {
2165 appendStr("const ");
2166 }
2167 normalizeType(begin, cst, false);
2168 begin = skipedCst;
2169 hasMiddleConst = true;
2170 break;
2171 }
2172 }
2173 if (skipToken(begin, end, "const")) {
2174 if (adjustConst && !seenStar) {
2175 if (*(end - 1) == '&')
2176 end--;
2177 } else {
2178 appendStr("const ");
2179 }
2180 }
2181 if (seenStar && adjustConst) {
2182 const char *e = end;
2183 if (*(end - 1) == '&' && *(end - 2) != '&')
2184 e--;
2185 while (begin != e && is_space(*(e - 1)))
2186 e--;
2187 const char *token = "tsnoc"; // 'const' reverse, to check if it ends with const
2188 while (*token && begin != e && *(--e) == *token++)
2189 ;
2190 if (!*token && begin != e && !is_ident_char(*(e - 1))) {
2191 while (begin != e && is_space(*(e - 1)))
2192 e--;
2193 end = e;
2194 }
2195 }
2196
2197 skipStructClassOrEnum(begin, end);
2198 skipQtNamespace(begin, end);
2199
2200 if (skipToken(begin, end, "QVector")) {
2201 // Replace QVector by QList
2202 appendStr("QList");
2203 }
2204
2205 if (skipToken(begin, end, "QPair")) {
2206 // replace QPair by std::pair
2207 appendStr("std::pair");
2208 }
2209
2210 if (!hasMiddleConst)
2211 // Normalize the integer types
2212 normalizeIntegerTypes(begin, end);
2213
2214 bool spaceSkiped = true;
2215 while (begin != end) {
2216 char c = *begin++;
2217 if (is_space(c)) {
2218 spaceSkiped = true;
2219 } else if ((c == '\'' && !is_number(last)) || c == '\"') {
2220 begin--;
2221 auto x = skipString(begin, end);
2222 while (begin < x)
2223 append(*begin++);
2224 } else {
2225 if (spaceSkiped && is_ident_char(last) && is_ident_char(c))
2226 append(' ');
2227 append(c);
2228 spaceSkiped = false;
2229 if (c == '<') {
2230 do {
2231 // template recursion
2232 const char *tpl = skipTemplate(begin, end, true);
2233 normalizeType(begin, tpl, false);
2234 if (tpl == end)
2235 return len;
2236 append(*tpl);
2237 begin = tpl;
2238 } while (*begin++ == ',');
2239 }
2240 }
2241 }
2242 return len;
2243 }
2244};
2245
2246// Normalize the type between begin and end, and store the data in the output. Returns the length.
2247// The idea is to first run this function with nullptr as output to allocate the output with the
2248// size
2249constexpr int qNormalizeType(const char *begin, const char *end, char *output)
2250{
2251 return QTypeNormalizer { output }.normalizeType(begin, end);
2252}
2253
2254template<typename T>
2256
2257template <typename T1_, typename T2_>
2258struct is_std_pair<std::pair<T1_, T2_>> : std::true_type {
2259 using T1 = T1_;
2260 using T2 = T2_;
2261};
2262
2264template<typename T>
2265constexpr auto typenameHelper()
2266{
2267 if constexpr (is_std_pair<T>::value) {
2268 using T1 = typename is_std_pair<T>::T1;
2269 using T2 = typename is_std_pair<T>::T2;
2270 std::remove_const_t<std::conditional_t<bool (QMetaTypeId2<T1>::IsBuiltIn), typename QMetaTypeId2<T1>::NameAsArrayType, decltype(typenameHelper<T1>())>> t1Name {};
2271 std::remove_const_t<std::conditional_t<bool (QMetaTypeId2<T2>::IsBuiltIn), typename QMetaTypeId2<T2>::NameAsArrayType, decltype(typenameHelper<T2>())>> t2Name {};
2272 if constexpr (bool (QMetaTypeId2<T1>::IsBuiltIn) ) {
2273 t1Name = QMetaTypeId2<T1>::nameAsArray;
2274 } else {
2275 t1Name = typenameHelper<T1>();
2276 }
2277 if constexpr (bool(QMetaTypeId2<T2>::IsBuiltIn)) {
2278 t2Name = QMetaTypeId2<T2>::nameAsArray;
2279 } else {
2280 t2Name = typenameHelper<T2>();
2281 }
2282 constexpr auto nonTypeDependentLen = sizeof("std::pair<,>");
2283 constexpr auto t1Len = t1Name.size() - 1;
2284 constexpr auto t2Len = t2Name.size() - 1;
2285 constexpr auto length = nonTypeDependentLen + t1Len + t2Len;
2286 std::array<char, length + 1> result {};
2287 constexpr auto prefix = "std::pair<";
2288 int currentLength = 0;
2289 for (; currentLength < int(sizeof("std::pair<") - 1); ++currentLength)
2290 result[currentLength] = prefix[currentLength];
2291 for (int i = 0; i < int(t1Len); ++currentLength, ++i)
2292 result[currentLength] = t1Name[i];
2293 result[currentLength++] = ',';
2294 for (int i = 0; i < int(t2Len); ++currentLength, ++i)
2295 result[currentLength] = t2Name[i];
2296 result[currentLength++] = '>';
2297 result[currentLength++] = '\0';
2298 return result;
2299 } else {
2300 constexpr auto prefix = sizeof(
2301#ifdef QT_NAMESPACE
2302 QT_STRINGIFY(QT_NAMESPACE) "::"
2303#endif
2304#if defined(Q_CC_MSVC) && defined(Q_CC_CLANG)
2305 "auto __cdecl QtPrivate::TypeNameHelper::typenameHelper(void) [T = "
2306#elif defined(Q_CC_MSVC)
2307 "auto __cdecl QtPrivate::TypeNameHelper::typenameHelper<"
2308#elif defined(Q_CC_CLANG)
2309 "auto QtPrivate::TypeNameHelper::typenameHelper() [T = "
2310#elif defined(Q_CC_GHS)
2311 "auto QtPrivate::TypeNameHelper::typenameHelper<T>()[with T="
2312#else
2313 "constexpr auto QtPrivate::TypeNameHelper::typenameHelper() [with T = "
2314#endif
2315 ) - 1;
2316#if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
2317 constexpr int suffix = sizeof(">(void)");
2318#else
2319 constexpr int suffix = sizeof("]");
2320#endif
2321
2322#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU_ONLY < 804
2323 auto func = Q_FUNC_INFO;
2324 const char *begin = func + prefix;
2325 const char *end = func + sizeof(Q_FUNC_INFO) - suffix;
2326 // This is an upper bound of the size since the normalized signature should always be smaller
2327 constexpr int len = sizeof(Q_FUNC_INFO) - suffix - prefix;
2328#else
2329 constexpr auto func = Q_FUNC_INFO;
2330 constexpr const char *begin = func + prefix;
2331 constexpr const char *end = func + sizeof(Q_FUNC_INFO) - suffix;
2332 constexpr int len = QTypeNormalizer{ nullptr }.normalizeTypeFromSignature(begin, end);
2333#endif
2334 std::array<char, len + 1> result {};
2335 QTypeNormalizer{ result.data() }.normalizeTypeFromSignature(begin, end);
2336 return result;
2337 }
2338}
2339} // namespace TypeNameHelper
2340using TypeNameHelper::typenameHelper;
2341
2342template<typename T, typename = void>
2344{
2345};
2346template<typename T>
2351
2352template<typename T, bool = (QTypeTraits::has_operator_equal_v<T> && !std::is_pointer_v<T>)>
2354{
2355QT_WARNING_PUSH
2356QT_WARNING_DISABLE_FLOAT_COMPARE
2357 static bool equals(const QMetaTypeInterface *, const void *a, const void *b)
2358 { return *reinterpret_cast<const T *>(a) == *reinterpret_cast<const T *>(b); }
2360};
2361
2362template<typename T>
2364{
2365 static constexpr QMetaTypeInterface::EqualsFn equals = nullptr;
2366};
2367
2368template<typename T, bool = (QTypeTraits::has_operator_less_than_v<T> && !std::is_pointer_v<T>)>
2370{
2371 static bool lessThan(const QMetaTypeInterface *, const void *a, const void *b)
2372 { return *reinterpret_cast<const T *>(a) < *reinterpret_cast<const T *>(b); }
2373};
2374
2375template<typename T>
2377{
2378 static constexpr QMetaTypeInterface::LessThanFn lessThan = nullptr;
2379};
2380
2381template<typename T, bool = (QTypeTraits::has_ostream_operator_v<QDebug, T> && !std::is_pointer_v<T>)>
2383{
2384 static constexpr QMetaTypeInterface::DebugStreamFn debugStream = nullptr;
2385};
2386
2387#ifndef QT_NO_DEBUG_STREAM
2388template<typename T>
2390{
2391 static void debugStream(const QMetaTypeInterface *, QDebug &dbg, const void *a)
2392 { dbg << *reinterpret_cast<const T *>(a); }
2393};
2394#endif
2395
2396template<typename T, bool = QTypeTraits::has_stream_operator_v<QDataStream, T>>
2402
2403#ifndef QT_NO_DATASTREAM
2404template<typename T>
2406{
2407 static void dataStreamOut(const QMetaTypeInterface *, QDataStream &ds, const void *a)
2408 { ds << *reinterpret_cast<const T *>(a); }
2409 static void dataStreamIn(const QMetaTypeInterface *, QDataStream &ds, void *a)
2410 { ds >> *reinterpret_cast<T *>(a); }
2411};
2412#endif
2413
2414// Performance optimization:
2415//
2416// Don't add all these symbols to the dynamic symbol tables on ELF systems and
2417// on Darwin. Each library is going to have a copy anyway and QMetaType already
2418// copes with some of these being "hidden" (see QMetaType::idHelper()). We may
2419// as well let the linker know it can always use the local copy.
2420//
2421// This is currently not enabled for GCC due to
2422// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106023
2423
2424#if !defined(Q_OS_WIN) && defined(Q_CC_CLANG)
2425# pragma GCC visibility push(hidden)
2426#endif
2427
2428// ### Qt 7: consider removing this infrastructure if nothing uses it
2429// (see also getCopyCtr())
2431{
2432 // Hack to suppress deprecation warnings from types
2433 // with deprecated copy operations, cf. QTBUG-132752
2434 template <typename T>
2436
2437#if !defined(QT_BOOTSTRAPPED)
2438 Q_CORE_EXPORT void warnAboutDeprecatedCopy(const char *name);
2439#endif
2440} // namespace QMetaTypeCopyTraits
2441
2442template<typename S>
2444{
2445public:
2446 static constexpr decltype(typenameHelper<S>()) name = typenameHelper<S>();
2447
2448 static constexpr unsigned flags()
2449 {
2450 uint flags = 0;
2451 if constexpr (QTypeInfo<S>::isRelocatable)
2452 flags |= QMetaType::RelocatableType;
2453 if constexpr (!std::is_default_constructible_v<S> || !QTypeInfo<S>::isValueInitializationBitwiseZero)
2454 flags |= QMetaType::NeedsConstruction;
2455 if constexpr (!std::is_trivially_destructible_v<S>)
2456 flags |= QMetaType::NeedsDestruction;
2457 if constexpr (!std::is_trivially_copy_constructible_v<S>)
2458 flags |= QMetaType::NeedsCopyConstruction;
2459 if constexpr (!std::is_trivially_move_constructible_v<S>)
2460 flags |= QMetaType::NeedsMoveConstruction;
2461 if constexpr (IsPointerToTypeDerivedFromQObject<S>::Value)
2462 flags |= QMetaType::PointerToQObject;
2463 if constexpr (IsSharedPointerToTypeDerivedFromQObject<S>::Value)
2464 flags |= QMetaType::SharedPointerToQObject;
2465 if constexpr (IsWeakPointerToTypeDerivedFromQObject<S>::Value)
2466 flags |= QMetaType::WeakPointerToQObject;
2467 if constexpr (IsTrackingPointerToTypeDerivedFromQObject<S>::Value)
2468 flags |= QMetaType::TrackingPointerToQObject;
2469 if constexpr (IsEnumOrFlags<S>::value)
2470 flags |= QMetaType::IsEnumeration;
2471 if constexpr (IsGadgetHelper<S>::IsGadgetOrDerivedFrom)
2472 flags |= QMetaType::IsGadget;
2473 if constexpr (IsPointerToGadgetHelper<S>::IsGadgetOrDerivedFrom)
2474 flags |= QMetaType::PointerToGadget;
2475 if constexpr (std::is_pointer_v<S>)
2476 flags |= QMetaType::IsPointer;
2477 if constexpr (IsUnsignedEnum<S>)
2478 flags |= QMetaType::IsUnsignedEnumeration;
2479 if constexpr (IsQmlListType<S>)
2480 flags |= QMetaType::IsQmlList;
2481 if constexpr (std::is_const_v<std::remove_pointer_t<S>>)
2482 flags |= QMetaType::IsConst;
2483 return flags;
2484 }
2485
2487 {
2488 if constexpr (std::is_default_constructible_v<S> && !QTypeInfo<S>::isValueInitializationBitwiseZero) {
2489 return [](const QMetaTypeInterface *, void *addr) { new (addr) S(); };
2490 } else {
2491 return nullptr;
2492 }
2493 }
2494
2496 {
2497 if constexpr (std::is_copy_constructible_v<S> && !std::is_trivially_copy_constructible_v<S>) {
2498 return [](const QMetaTypeInterface *, void *addr, const void *other) {
2499 if constexpr (qxp::is_detected_v<QMetaTypeCopyTraits::HasDeprecatedCopyConstructorTest, S>) {
2500#if !defined(QT_BOOTSTRAPPED)
2502#endif
2503 QT_IGNORE_DEPRECATIONS(new (addr) S(*reinterpret_cast<const S *>(other));)
2504 } else {
2505 new (addr) S(*reinterpret_cast<const S *>(other));
2506 }
2507 };
2508 } else {
2509 return nullptr;
2510 }
2511 }
2512
2514 {
2515 if constexpr (std::is_move_constructible_v<S> && !std::is_trivially_move_constructible_v<S>) {
2516 return [](const QMetaTypeInterface *, void *addr, void *other) {
2517 new (addr) S(std::move(*reinterpret_cast<S *>(other)));
2518 };
2519 } else {
2520 return nullptr;
2521 }
2522 }
2523
2525 {
2526 if constexpr (std::is_destructible_v<S> && !std::is_trivially_destructible_v<S>)
2527 return [](const QMetaTypeInterface *, void *addr) {
2528 reinterpret_cast<S *>(addr)->~S();
2529 };
2530 else
2531 return nullptr;
2532 }
2533
2535 {
2536 if constexpr (QMetaTypeId2<S>::Defined && !QMetaTypeId2<S>::IsBuiltIn) {
2537 return []() { QMetaTypeId2<S>::qt_metatype_id(); };
2538 } else {
2539 return nullptr;
2540 }
2541 }
2542
2543 static constexpr const char *getName()
2544 {
2545 if constexpr (bool(QMetaTypeId2<S>::IsBuiltIn)) {
2546 return QMetaTypeId2<S>::nameAsArray.data();
2547 } else {
2548 return name.data();
2549 }
2550 }
2551};
2552
2553template<typename T>
2555{
2556 // if the type ID for T is known at compile-time, then we can declare
2557 // the QMetaTypeInterface object const; otherwise, we declare it as
2558 // non-const and the .typeId is updated by QMetaType::idHelper().
2561
2562 static inline InterfaceType metaType = {
2563 /*.revision=*/ QMetaTypeInterface::CurrentRevision,
2564 /*.alignment=*/ alignof(T),
2565 /*.size=*/ sizeof(T),
2566 /*.flags=*/ QMetaTypeForType<T>::flags(),
2567 /*.typeId=*/ BuiltinMetaType<T>::value,
2568 /*.metaObjectFn=*/ MetaObjectForType<T>::metaObjectFunction,
2569 /*.name=*/ QMetaTypeForType<T>::getName(),
2570 /*.defaultCtr=*/ QMetaTypeForType<T>::getDefaultCtr(),
2571 /*.copyCtr=*/ QMetaTypeForType<T>::getCopyCtr(),
2572 /*.moveCtr=*/ QMetaTypeForType<T>::getMoveCtr(),
2573 /*.dtor=*/ QMetaTypeForType<T>::getDtor(),
2574 /*.equals=*/ QEqualityOperatorForType<T>::equals,
2575 /*.lessThan=*/ QLessThanOperatorForType<T>::lessThan,
2576 /*.debugStream=*/ QDebugStreamOperatorForType<T>::debugStream,
2577 /*.dataStreamOut=*/ QDataStreamOperatorForType<T>::dataStreamOut,
2578 /*.dataStreamIn=*/ QDataStreamOperatorForType<T>::dataStreamIn,
2579 /*.legacyRegisterOp=*/ QMetaTypeForType<T>::getLegacyRegister()
2580 };
2581};
2582template<typename T> struct QMetaTypeInterfaceWrapper<T &> {};
2583
2584
2585#if !defined(Q_OS_WIN) && defined(Q_CC_CLANG)
2586# pragma GCC visibility pop
2587#endif
2588
2589template<>
2591{
2592public:
2593 static constexpr QMetaTypeInterface metaType =
2594 {
2595 /*.revision=*/ 0,
2596 /*.alignment=*/ 0,
2597 /*.size=*/ 0,
2598 /*.flags=*/ 0,
2599 /*.typeId=*/ BuiltinMetaType<void>::value,
2600 /*.metaObjectFn=*/ nullptr,
2601 /*.name=*/ "void",
2602 /*.defaultCtr=*/ nullptr,
2603 /*.copyCtr=*/ nullptr,
2604 /*.moveCtr=*/ nullptr,
2605 /*.dtor=*/ nullptr,
2606 /*.equals=*/ nullptr,
2607 /*.lessThan=*/ nullptr,
2608 /*.debugStream=*/ nullptr,
2609 /*.dataStreamOut=*/ nullptr,
2610 /*.dataStreamIn=*/ nullptr,
2611 /*.legacyRegisterOp=*/ nullptr
2612 };
2613};
2614
2615/*
2616 MSVC instantiates extern templates
2617(https://developercommunity.visualstudio.com/t/c11-extern-templates-doesnt-work-for-class-templat/157868)
2618
2619 The INTEGRITY compiler apparently does too.
2620
2621 On Windows (with other compilers or whenever MSVC is fixed), we can't declare
2622 QMetaTypeInterfaceWrapper with __declspec(dllimport) because taking its
2623 address is not a core constant expression.
2624 */
2625#if !defined(QT_BOOTSTRAPPED) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY)
2626
2627#ifdef QT_NO_DATA_RELOCATION
2628# define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name)
2629 extern template class Q_CORE_EXPORT QMetaTypeForType<Name>;
2630#else
2631# define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name)
2632 extern template class Q_CORE_EXPORT QMetaTypeForType<Name>;
2633 extern template struct Q_CORE_EXPORT QMetaTypeInterfaceWrapper<Name>;
2634#endif
2635
2641#undef QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER
2642#endif
2643
2644template<typename T>
2646{
2648};
2649
2650#define Q_REMOVE_POINTER_LIKE_IMPL(Pointer) template
2651 <typename T> struct
2652 QRemovePointerLike<Pointer<T>> \
2653{
2654 using type = T; \
2655};
2656
2658#undef Q_REMOVE_POINTER_LIKE_IMPL
2659
2660template<typename T>
2662{
2663 // don't check the type is suitable here
2664 using Ty = typename MetatypeDecay<T>::type;
2665 return &QMetaTypeInterfaceWrapper<Ty>::metaType;
2666}
2667
2668// Relaxed vesion of the above, used by moc-generated code to create the
2669// metatype array without requiring types to be complete and allowing
2670// references. Unique is passed to is_complete and must be a different unique
2671// type; if it is void, this function is equal to qMetaTypeInterfaceForType()
2672// above.
2673template<typename Unique, typename T>
2675{
2676 using Ty = typename MetatypeDecay<T>::type;
2677 using Tz = typename QRemovePointerLike<Ty>::type;
2678
2679 if constexpr (std::is_void_v<Tz>) {
2680 // early out to avoid expanding the rest of the templates
2681 return &QMetaTypeInterfaceWrapper<Ty>::metaType;
2682 } else if constexpr (std::is_void_v<Unique>) {
2683 checkTypeIsSuitableForMetaType<Ty>();
2684 return &QMetaTypeInterfaceWrapper<Ty>::metaType;
2685 } else if constexpr (std::is_reference_v<Tz>) {
2686 return nullptr;
2687 } else if constexpr (!is_complete<Tz, Unique>::value) {
2688 return nullptr;
2689 } else {
2690 // don't check the type is suitable here
2691 return &QMetaTypeInterfaceWrapper<Ty>::metaType;
2692 }
2693}
2694
2695} // namespace QtPrivate
2696
2697template<typename T>
2698constexpr QMetaType QMetaType::fromType()
2699{
2700 QtPrivate::checkTypeIsSuitableForMetaType<T>();
2701 return QMetaType(QtPrivate::qMetaTypeInterfaceForType<T>());
2702}
2703
2704template <typename T> bool
2705QMetaType::isSameTypeHelper(const QtPrivate::QMetaTypeInterface *iface, std::true_type) const noexcept
2706{
2707 // built-in types have statically-known IDs and never need to be registered
2708 constexpr int Id = int(QMetaTypeId2<T>::MetaType); // qMetaTypeId<T>()
2709
2710#ifdef QT_NO_DATA_RELOCATION
2711 Q_UNUSED(iface);
2712#else
2713 if constexpr (!std::is_void_v<T> && QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)) {
2714 // pointer addresses are unique for QtCore built-in types only after
2715 // v6.4.0 and only for those made built-in on the release they were
2716 // first introduced
2717 if constexpr (Id <= int(LastCoreType))
2718 return d_ptr == iface;
2719 }
2720#endif
2721
2722 // For types from the other libraries, the pointer addresses aren't
2723 // guaranteed to be unique. Therefore, we need to compare IDs if the
2724 // pointers aren't equal, meaning the code will be emitted anyway. We may
2725 // as well go straight to comparing IDs.
2726
2727 if (!d_ptr)
2728 return false; // UnknownType
2729
2730 return d_ptr->typeId.loadRelaxed() == Id;
2731}
2732
2733template <typename T> bool
2734QMetaType::isSameTypeHelper(const QtPrivate::QMetaTypeInterface *iface, std::false_type) const
2735{
2736 if (!d_ptr)
2737 return false; // UnknownType
2738
2739 // This registers if needed.
2740 return *this == QMetaType(iface);
2741}
2742
2743constexpr bool QMetaType::isValid(QT6_IMPL_NEW_OVERLOAD) const noexcept
2744{
2745 return d_ptr;
2746}
2747
2748bool QMetaType::isRegistered(QT6_IMPL_NEW_OVERLOAD) const noexcept
2749{
2750 return d_ptr && Q_LIKELY(d_ptr->typeId.loadRelaxed());
2751}
2752
2753constexpr qsizetype QMetaType::sizeOf() const
2754{
2755 return d_ptr ? d_ptr->size : 0;
2756}
2757
2758constexpr qsizetype QMetaType::alignOf() const
2759{
2760 return d_ptr ? d_ptr->alignment : 0;
2761}
2762
2763constexpr QMetaType::TypeFlags QMetaType::flags() const
2764{
2765 return d_ptr ? TypeFlags(d_ptr->flags) : TypeFlags{};
2766}
2767
2768constexpr const QMetaObject *QMetaType::metaObject() const
2769{
2770 return d_ptr && d_ptr->metaObjectFn ? d_ptr->metaObjectFn(d_ptr) : nullptr;
2771}
2772
2773constexpr const char *QMetaType::name() const
2774{
2775 return d_ptr ? d_ptr->name : nullptr;
2776}
2777
2778inline size_t qHash(QMetaType type, size_t seed = 0)
2779{
2780 // We cannot use d_ptr here since the same type in different DLLs
2781 // might result in different pointers!
2782 return qHash(type.id(), seed);
2783}
2784
2786
2787QT_DECL_METATYPE_EXTERN_TAGGED(QtMetaTypePrivate::QPairVariantInterfaceImpl,
2788 QPairVariantInterfaceImpl, Q_CORE_EXPORT)
2789
2790#endif // QMETATYPE_H
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
Definition qmetatype.h:395
\inmodule QtCore
\inmodule QtCore
void(*)(void *, const void *, const void *) SetMappedAtKeyFn
void(*)(void *, const void *) EraseKeyAtIteratorFn
bool(*)(const void *, const void *) ContainsKeyFn
void(*)(const void *, const void *, void *) MappedAtKeyFn
void(*)(const void *, const void *) SetMappedAtIteratorFn
const QtPrivate::QMetaTypeInterface * keyMetaType
void *(*)(void *, const void *) CreateIteratorAtKeyFn
void *(*)(const void *, const void *) CreateConstIteratorAtKeyFn
const QtPrivate::QMetaTypeInterface * mappedMetaType
constexpr QMetaAssociationInterface(const MetaAssociation &m)
void(*)(const void *, qsizetype, void *) ValueAtIndexFn
void(*)(void *, qsizetype, const void *) SetValueAtIndexFn
void(*)(const void *, void *) ValueAtIteratorFn
void(*)(void *, const void *, const void *) InsertValueAtIteratorFn
const QtPrivate::QMetaTypeInterface * valueMetaType
void(*)(void *, const void *, Position) AddValueFn
void(*)(const void *, const void *) SetValueAtIteratorFn
void(*)(void *, const void *, const void *) EraseRangeAtIteratorFn
void(*)(void *, const void *) EraseValueAtIteratorFn
constexpr QMetaSequenceInterface(const MetaSequence &m)
static void getSecondImpl(const void *const *pair, void *dataPtr)
Definition qmetatype.h:909
void(* getFunc)(const void *const *p, void *)
Definition qmetatype.h:900
static void getFirstImpl(const void *const *pair, void *dataPtr)
Definition qmetatype.h:906
static constexpr QMetaTypeInterface::DtorFn getDtor()
Definition qmetatype.h:2524
static constexpr QMetaTypeInterface::CopyCtrFn getCopyCtr()
Definition qmetatype.h:2495
static constexpr QMetaTypeInterface::LegacyRegisterOp getLegacyRegister()
Definition qmetatype.h:2534
static constexpr unsigned flags()
Definition qmetatype.h:2448
static constexpr const char * getName()
Definition qmetatype.h:2543
static constexpr QMetaTypeInterface::DefaultCtrFn getDefaultCtr()
Definition qmetatype.h:2486
static constexpr decltype(typenameHelper< S >()) name
Definition qmetatype.h:2446
static constexpr QMetaTypeInterface::MoveCtrFn getMoveCtr()
Definition qmetatype.h:2513
static constexpr QMetaTypeInterface metaType
Definition qmetatype.h:2593
void(*)(const QMetaTypeInterface *, void *) DefaultCtrFn
Definition qmetatype.h:293
void(*)(const QMetaTypeInterface *, void *, const void *) CopyCtrFn
Definition qmetatype.h:295
DataStreamOutFn dataStreamOut
Definition qmetatype.h:308
QMTI_MUTABLE QBasicAtomicInt typeId
Definition qmetatype.h:286
void(*)(const QMetaTypeInterface *, QDataStream &, const void *) DataStreamOutFn
Definition qmetatype.h:307
void(*)(const QMetaTypeInterface *, QDataStream &, void *) DataStreamInFn
Definition qmetatype.h:309
void(*)(const QMetaTypeInterface *, void *, void *) MoveCtrFn
Definition qmetatype.h:297
const QMetaObject *(*)(const QMetaTypeInterface *) MetaObjectFn
Definition qmetatype.h:288
void(*)(const QMetaTypeInterface *, void *) DtorFn
Definition qmetatype.h:299
bool(*)(const QMetaTypeInterface *, const void *, const void *) LessThanFn
Definition qmetatype.h:303
LegacyRegisterOp legacyRegisterOp
Definition qmetatype.h:313
void(*)(const QMetaTypeInterface *, QDebug &, const void *) DebugStreamFn
Definition qmetatype.h:305
bool(*)(const QMetaTypeInterface *, const void *, const void *) EqualsFn
Definition qmetatype.h:301
static constexpr ushort CurrentRevision
Definition qmetatype.h:280
Combined button and popup list for selecting options.
typename T::_q_hasDeprecatedCopyConstructor HasDeprecatedCopyConstructorTest
Definition qmetatype.h:2435
Q_CORE_EXPORT void warnAboutDeprecatedCopy(const char *name)
constexpr auto typenameHelper()
Definition qmetatype.h:2265
Q_CORE_EXPORT bool hasRegisteredConverterFunctionToIterableMetaSequence(QMetaType m)
Q_CORE_EXPORT bool hasRegisteredMutableViewFunctionToIterableMetaSequence(QMetaType m)
static constexpr bool checkTypeIsSuitableForMetaType()
Definition qmetatype.h:378
constexpr bool IsQmlListType
Definition qmetatype.h:1326
constexpr int qNormalizeType(const char *begin, const char *end, char *output)
Definition qmetatype.h:2249
constexpr bool PointerIsSuitableForMetaTypeHelper
Definition qmetatype.h:369
constexpr bool IsUnsignedEnum
Definition qmetatype.h:1329
Q_CORE_EXPORT bool hasRegisteredConverterFunctionToPairVariantInterface(QMetaType m)
constexpr const QMetaTypeInterface * qTryMetaTypeInterfaceForType()
Definition qmetatype.h:2674
constexpr bool IsUnsignedEnum< T, true >
Definition qmetatype.h:1331
Q_CORE_EXPORT bool hasRegisteredConverterFunctionToIterableMetaAssociation(QMetaType m)
Q_CORE_EXPORT bool hasRegisteredMutableViewFunctionToIterableMetaAssociation(QMetaType m)
To convertImplicit(const From &from)
This template is used for implicit conversion from type From to type To.
Definition qmetatype.h:322
constexpr const QMetaTypeInterface * qMetaTypeInterfaceForType()
Definition qmetatype.h:2661
constexpr bool TypeIsSuitableForMetaType
Definition qmetatype.h:373
constexpr bool TypeIsCompleteOrVoid
Definition qmetatype.h:367
char qt_getEnumMetaObject(const T &)
constexpr int qMetaTypeId()
Definition qmetatype.h:1442
#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(SINGLE_ARG_TEMPLATE)
Definition qmetatype.h:1692
#define QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F)
Definition qmetatype.h:97
int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName)
Definition qmetatype.h:1403
#define QT_FOR_EACH_STATIC_GUI_CLASS(F)
Definition qmetatype.h:164
#define QT_FOR_EACH_STATIC_VARIANT_ALIAS_TYPE(F)
Definition qmetatype.h:214
#define QT_FOR_EACH_STATIC_EASINGCURVE(F)
Definition qmetatype.h:82
#define QT_FOR_EACH_STATIC_CORE_QVARIANT_TEMPLATE(F)
Definition qmetatype.h:142
#define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
Definition qmetatype.h:90
#define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE)
Definition qmetatype.h:1569
#define QT_FOR_EACH_STATIC_WIDGETS_CLASS(F)
Definition qmetatype.h:190
#define QT_DECL_METATYPE_EXTERN_TAGGED(TYPE, TAG, EXPORT)
Definition qmetatype.h:1412
#define QT_FOR_EACH_STATIC_CORE_POINTER(F)
Definition qmetatype.h:138
#define Q_DECLARE_METATYPE_IMPL(TYPE)
Definition qmetatype.h:1522
int qRegisterMetaType(const char *typeName)
Definition qmetatype.h:1431
#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(F)
Definition qmetatype.h:247
#define Q_DECLARE_METATYPE_TEMPLATE_2ARG(DOUBLE_ARG_TEMPLATE)
Definition qmetatype.h:1597
#define QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)
Definition qmetatype.h:71
#define QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(F)
Definition qmetatype.h:51
#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(F)
Definition qmetatype.h:236
#define QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)
Definition qmetatype.h:152
#define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)
Definition qmetatype.h:75
#define QT_FOR_EACH_STATIC_QVARIANT(F)
Definition qmetatype.h:100
#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG)
Definition qmetatype.h:1420
#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)
Definition qmetatype.h:161
int qRegisterMetaType(QMetaType meta)
Definition qmetatype.h:1461
#define QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(C, F)
Definition qmetatype.h:885
constexpr int qRegisterMetaType()
Definition qmetatype.h:1455
#define QT_FOR_EACH_STATIC_CORE_CLASS(F)
Definition qmetatype.h:106
#define Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(TEMPLATENAME)
Definition qmetatype.h:1716
size_t qHash(QMetaType type, size_t seed=0)
\qhashold{QMetaType}
Definition qmetatype.h:2778
int qRegisterNormalizedMetaTypeImplementation(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName)
Definition qmetatype.h:1364
#define QMTI_MUTABLE
Definition qmetatype.h:265
#define Q_DECLARE_METATYPE(TYPE)
Definition qmetatype.h:1521
#define Q_DECLARE_SMART_POINTER_METATYPE(SMART_POINTER)
Definition qmetatype.h:1645
#define QT_FOR_EACH_STATIC_TYPE(F)
Definition qmetatype.h:224
static constexpr int qt_metatype_id()
Definition qmetatype.h:1307
void NameAsArrayType
Definition qmetatype.h:1294
static constexpr int qt_metatype_id()
Definition qmetatype.h:1296
QPairVariantInterfaceImpl operator()(const std::pair< T, U > &f) const
Definition qmetatype.h:940
static bool registerConverter()
Definition qmetatype.h:1234
static bool registerConverter()
Definition qmetatype.h:1249
static yes_type checkType(const QObject *)
static const T & declval()
static constexpr const QMetaObject * value()
Definition qmetatype.h:1048
static constexpr MetaObjectFn metaObjectFunction
Definition qmetatype.h:1050
const QMetaObject *(*)(const QMetaTypeInterface *) MetaObjectFn
Definition qmetatype.h:1049
QIterable< QMetaAssociation > operator()(const From &f) const
Definition qmetatype.h:1814
QIterable< QMetaAssociation > operator()(From &f) const
Definition qmetatype.h:1823
static void dataStreamIn(const QMetaTypeInterface *, QDataStream &ds, void *a)
Definition qmetatype.h:2409
static void dataStreamOut(const QMetaTypeInterface *, QDataStream &ds, const void *a)
Definition qmetatype.h:2407
static void debugStream(const QMetaTypeInterface *, QDebug &dbg, const void *a)
Definition qmetatype.h:2391
static constexpr QMetaTypeInterface::DebugStreamFn debugStream
Definition qmetatype.h:2384
static constexpr QMetaTypeInterface::EqualsFn equals
Definition qmetatype.h:2365
static constexpr QMetaTypeInterface::LessThanFn lessThan
Definition qmetatype.h:2378
static bool lessThan(const QMetaTypeInterface *, const void *a, const void *b)
Definition qmetatype.h:2371
static constexpr int qt_metatype_id()
Definition qmetatype.h:1317
static constexpr int qt_metatype_id()
Definition qmetatype.h:1313
static constexpr bool IsConstMetaTypeInterface
Definition qmetatype.h:2559
QIterable< QMetaSequence > operator()(const From &f) const
Definition qmetatype.h:1774
QIterable< QMetaSequence > operator()(From &f) const
Definition qmetatype.h:1783
QObject * operator()(const QWeakPointer< T > &p) const
Definition qmetatype.h:1356
QObject * operator()(const SmartPointer &p) const
Definition qmetatype.h:1342
constexpr int normalizeType(const char *begin, const char *end, bool adjustConst=true)
Definition qmetatype.h:2112
constexpr int normalizeTypeFromSignature(const char *begin, const char *end)
Definition qmetatype.h:2108
static auto check(...) -> std::false_type
static auto check(U *) -> std::integral_constant< bool, sizeof(U) !=0 >
decltype(check(static_cast< T * >(nullptr))) type
Definition qmetatype.h:346