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