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 constexpr qsizetype sizeOf() const;
533 constexpr qsizetype alignOf() const;
534 constexpr TypeFlags flags() const;
535 constexpr const QMetaObject *metaObject() const;
536 constexpr const char *name() const;
537
538 void *create(const void *copy = nullptr) const;
539 void destroy(void *data) const;
540 void *construct(void *where, const void *copy = nullptr) const;
541 void destruct(void *data) const;
542 QPartialOrdering compare(const void *lhs, const void *rhs) const;
543 bool equals(const void *lhs, const void *rhs) const;
544
545 bool isDefaultConstructible() const noexcept { return d_ptr && isDefaultConstructible(d_ptr); }
546 bool isCopyConstructible() const noexcept { return d_ptr && isCopyConstructible(d_ptr); }
547 bool isMoveConstructible() const noexcept { return d_ptr && isMoveConstructible(d_ptr); }
548 bool isDestructible() const noexcept { return d_ptr && isDestructible(d_ptr); }
549 bool isEqualityComparable() const;
550 bool isOrdered() const;
551
552#ifndef QT_NO_DATASTREAM
553 bool save(QDataStream &stream, const void *data) const;
554 bool load(QDataStream &stream, void *data) const;
555 bool hasRegisteredDataStreamOperators() const;
556
557#if QT_DEPRECATED_SINCE(6, 0)
558 QT_DEPRECATED_VERSION_6_0
559 static bool save(QDataStream &stream, int type, const void *data)
560 { return QMetaType(type).save(stream, data); }
561 QT_DEPRECATED_VERSION_6_0
562 static bool load(QDataStream &stream, int type, void *data)
563 { return QMetaType(type).load(stream, data); }
564#endif
565#endif
566
567 QMetaType underlyingType() const;
568
569 template<typename T>
570 constexpr static QMetaType fromType();
571 static QMetaType fromName(QByteArrayView name);
572private:
573 friend bool comparesEqual(const QMetaType &lhs,
574 const QMetaType &rhs)
575 {
576 if (lhs.d_ptr == rhs.d_ptr)
577 return true;
578 if (!lhs.d_ptr || !rhs.d_ptr)
579 return false; // one type is undefined, the other is defined
580 // avoid id call if we already have the id
581 const int aId = lhs.id();
582 const int bId = rhs.id();
583 return aId == bId;
584 }
585 Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(QMetaType)
586#ifndef QT_NO_DEBUG_STREAM
587private:
588 friend Q_CORE_EXPORT QDebug operator<<(QDebug d, QMetaType m);
589public:
590 bool debugStream(QDebug& dbg, const void *rhs);
591 bool hasRegisteredDebugStreamOperator() const;
592
593#if QT_DEPRECATED_SINCE(6, 0)
594 QT_DEPRECATED_VERSION_6_0
595 static bool debugStream(QDebug& dbg, const void *rhs, int typeId)
596 { return QMetaType(typeId).debugStream(dbg, rhs); }
597 template<typename T>
598 QT_DEPRECATED_VERSION_6_0
599 static bool hasRegisteredDebugStreamOperator()
600 { return QMetaType::fromType<T>().hasRegisteredDebugStreamOperator(); }
601 QT_DEPRECATED_VERSION_6_0
602 static bool hasRegisteredDebugStreamOperator(int typeId)
603 { return QMetaType(typeId).hasRegisteredDebugStreamOperator(); }
604#endif
605#endif
606
607public:
608 // type erased converter function
609 using ConverterFunction = std::function<bool(const void *src, void *target)>;
610
611 // type erased mutable view, primarily for containers
612 using MutableViewFunction = std::function<bool(void *src, void *target)>;
613
614 // implicit conversion supported like double -> float
615 template<typename From, typename To>
616 static bool registerConverter()
617 {
618 return registerConverter<From, To>(QtPrivate::convertImplicit<From, To>);
619 }
620
621 // member function as in "QString QFont::toString() const"
622 template<typename From, typename To>
623 static bool registerConverter(To(From::*function)() const)
624 {
625 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
626 "QMetaType::registerConverter: At least one of the types must be a custom type.");
627
628 const QMetaType fromType = QMetaType::fromType<From>();
629 const QMetaType toType = QMetaType::fromType<To>();
630 auto converter = [function](const void *from, void *to) -> bool {
631 const From *f = static_cast<const From *>(from);
632 To *t = static_cast<To *>(to);
633 *t = (f->*function)();
634 return true;
635 };
636 return registerConverterImpl<From, To>(converter, fromType, toType);
637 }
638
639 // member function
640 template<typename From, typename To>
641 static bool registerMutableView(To(From::*function)())
642 {
643 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
644 "QMetaType::registerMutableView: At least one of the types must be a custom type.");
645
646 const QMetaType fromType = QMetaType::fromType<From>();
647 const QMetaType toType = QMetaType::fromType<To>();
648 auto view = [function](void *from, void *to) -> bool {
649 From *f = static_cast<From *>(from);
650 To *t = static_cast<To *>(to);
651 *t = (f->*function)();
652 return true;
653 };
654 return registerMutableViewImpl<From, To>(view, fromType, toType);
655 }
656
657 // member function as in "double QString::toDouble(bool *ok = nullptr) const"
658 template<typename From, typename To>
659 static bool registerConverter(To(From::*function)(bool*) const)
660 {
661 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
662 "QMetaType::registerConverter: At least one of the types must be a custom type.");
663
664 const QMetaType fromType = QMetaType::fromType<From>();
665 const QMetaType toType = QMetaType::fromType<To>();
666 auto converter = [function](const void *from, void *to) -> bool {
667 const From *f = static_cast<const From *>(from);
668 To *t = static_cast<To *>(to);
669 bool result = true;
670 *t = (f->*function)(&result);
671 if (!result)
672 *t = To();
673 return result;
674 };
675 return registerConverterImpl<From, To>(converter, fromType, toType);
676 }
677
678 // functor or function pointer
679 template<typename From, typename To, typename UnaryFunction>
680 static bool registerConverter(UnaryFunction function)
681 {
682 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
683 "QMetaType::registerConverter: At least one of the types must be a custom type.");
684
685 const QMetaType fromType = QMetaType::fromType<From>();
686 const QMetaType toType = QMetaType::fromType<To>();
687 auto converter = [function = std::move(function)](const void *from, void *to) -> bool {
688 const From *f = static_cast<const From *>(from);
689 To *t = static_cast<To *>(to);
690 auto &&r = function(*f);
691 if constexpr (std::is_same_v<q20::remove_cvref_t<decltype(r)>, std::optional<To>>) {
692 if (!r)
693 return false;
694 *t = *std::forward<decltype(r)>(r);
695 } else {
696 *t = std::forward<decltype(r)>(r);
697 }
698 return true;
699 };
700 return registerConverterImpl<From, To>(std::move(converter), fromType, toType);
701 }
702
703 // functor or function pointer
704 template<typename From, typename To, typename UnaryFunction>
705 static bool registerMutableView(UnaryFunction function)
706 {
707 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
708 "QMetaType::registerMutableView: At least one of the types must be a custom type.");
709
710 const QMetaType fromType = QMetaType::fromType<From>();
711 const QMetaType toType = QMetaType::fromType<To>();
712 auto view = [function = std::move(function)](void *from, void *to) -> bool {
713 From *f = static_cast<From *>(from);
714 To *t = static_cast<To *>(to);
715 *t = function(*f);
716 return true;
717 };
718 return registerMutableViewImpl<From, To>(std::move(view), fromType, toType);
719 }
720
721private:
722 template<typename From, typename To>
723 static bool registerConverterImpl(ConverterFunction converter, QMetaType fromType, QMetaType toType)
724 {
725 if (registerConverterFunction(std::move(converter), fromType, toType)) {
726 static const auto unregister = qScopeGuard([=] {
727 unregisterConverterFunction(fromType, toType);
728 });
729 return true;
730 } else {
731 return false;
732 }
733 }
734
735 template<typename From, typename To>
736 static bool registerMutableViewImpl(MutableViewFunction view, QMetaType fromType, QMetaType toType)
737 {
738 if (registerMutableViewFunction(std::move(view), fromType, toType)) {
739 static const auto unregister = qScopeGuard([=] {
740 unregisterMutableViewFunction(fromType, toType);
741 });
742 return true;
743 } else {
744 return false;
745 }
746 }
747public:
748
749 static bool convert(QMetaType fromType, const void *from, QMetaType toType, void *to);
750 static bool canConvert(QMetaType fromType, QMetaType toType);
751
752 static bool view(QMetaType fromType, void *from, QMetaType toType, void *to);
753 static bool canView(QMetaType fromType, QMetaType toType);
754#if QT_DEPRECATED_SINCE(6, 0)
755 QT_DEPRECATED_VERSION_6_0
756 static bool convert(const void *from, int fromTypeId, void *to, int toTypeId)
757 { return convert(QMetaType(fromTypeId), from, QMetaType(toTypeId), to); }
758 QT_DEPRECATED_VERSION_6_0
759 static bool compare(const void *lhs, const void *rhs, int typeId, int *result)
760 {
761 QMetaType t(typeId);
762 auto c = t.compare(lhs, rhs);
763 if (c == QPartialOrdering::Unordered) {
764 *result = 0;
765 return false;
766 } else if (c == QPartialOrdering::Less) {
767 *result = -1;
768 return true;
769 } else if (c == QPartialOrdering::Equivalent) {
770 *result = 0;
771 return true;
772 } else {
773 *result = 1;
774 return true;
775 }
776 }
777 QT_DEPRECATED_VERSION_6_0
778 static bool equals(const void *lhs, const void *rhs, int typeId, int *result)
779 {
780 QMetaType t(typeId);
781 if (!t.isEqualityComparable())
782 return false;
783 *result = t.equals(lhs, rhs) ? 0 : -1;
784 return true;
785 }
786#endif
787
788 template<typename From, typename To>
789 static bool hasRegisteredConverterFunction()
790 {
791 return hasRegisteredConverterFunction(
792 QMetaType::fromType<From>(), QMetaType::fromType<To>());
793 }
794
795 static bool hasRegisteredConverterFunction(QMetaType fromType, QMetaType toType);
796
797 template<typename From, typename To>
798 static bool hasRegisteredMutableViewFunction()
799 {
800 return hasRegisteredMutableViewFunction(
801 QMetaType::fromType<From>(), QMetaType::fromType<To>());
802 }
803
804 static bool hasRegisteredMutableViewFunction(QMetaType fromType, QMetaType toType);
805
806#ifndef Q_QDOC
807 template<typename, bool> friend struct QtPrivate::SequentialValueTypeIsMetaType;
808 template<typename, bool> friend struct QtPrivate::AssociativeValueTypeIsMetaType;
809 template<typename, bool> friend struct QtPrivate::IsMetaTypePair;
810 template<typename, typename> friend struct QtPrivate::MetaTypeSmartPointerHelper;
811#endif
812 static bool registerConverterFunction(const ConverterFunction &f, QMetaType from, QMetaType to);
813 static void unregisterConverterFunction(QMetaType from, QMetaType to);
814
815 static bool registerMutableViewFunction(const MutableViewFunction &f, QMetaType from, QMetaType to);
816 static void unregisterMutableViewFunction(QMetaType from, QMetaType to);
817
818 static void unregisterMetaType(QMetaType type);
819
820#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
821 constexpr const QtPrivate::QMetaTypeInterface *iface() { return d_ptr; }
822#endif
823 constexpr const QtPrivate::QMetaTypeInterface *iface() const { return d_ptr; }
824
825private:
826 Q_DECL_PURE_FUNCTION static bool isDefaultConstructible(const QtPrivate::QMetaTypeInterface *) noexcept;
827 Q_DECL_PURE_FUNCTION static bool isCopyConstructible(const QtPrivate::QMetaTypeInterface *) noexcept;
828 Q_DECL_PURE_FUNCTION static bool isMoveConstructible(const QtPrivate::QMetaTypeInterface *) noexcept;
829 Q_DECL_PURE_FUNCTION static bool isDestructible(const QtPrivate::QMetaTypeInterface *) noexcept;
830
831#if QT_CORE_REMOVED_SINCE(6, 5)
832 int idHelper() const;
833#endif
834 static int registerHelper(const QtPrivate::QMetaTypeInterface *iface);
835 int registerHelper() const
836 {
837 if (d_ptr) {
838 if (int id = d_ptr->typeId.loadRelaxed(); Q_LIKELY(id))
839 return id;
840 return registerHelper(d_ptr);
841 }
842 return 0;
843 }
844
845 friend int qRegisterMetaType(QMetaType meta);
846
847 friend class QVariant;
848 const QtPrivate::QMetaTypeInterface *d_ptr = nullptr;
849};
850
851#undef QT_DEFINE_METATYPE_ID
852
853Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags)
854
855#define QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(C, F)
856 }
857 Q_DECLARE_TYPEINFO(QtMetaTypePrivate:: C, (F));
858 namespace QtMetaTypePrivate {
859
860
862
864{
865public:
866 const void *_pair;
869
870 typedef void (*getFunc)(const void * const *p, void *);
871
874
875 template<class T>
876 static void getFirstImpl(const void * const *pair, void *dataPtr)
877 { *static_cast<typename T::first_type *>(dataPtr) = static_cast<const T*>(*pair)->first; }
878 template<class T>
879 static void getSecondImpl(const void * const *pair, void *dataPtr)
880 { *static_cast<typename T::second_type *>(dataPtr) = static_cast<const T*>(*pair)->second; }
881
882public:
883 template<class T> QPairVariantInterfaceImpl(const T*p)
884 : _pair(p)
887 , _getFirst(getFirstImpl<T>)
888 , _getSecond(getSecondImpl<T>)
889 {
890 }
891
893 : _pair(nullptr)
894 , _getFirst(nullptr)
895 , _getSecond(nullptr)
896 {
897 }
898
899 inline void first(void *dataPtr) const { _getFirst(&_pair, dataPtr); }
900 inline void second(void *dataPtr) const { _getSecond(&_pair, dataPtr); }
901};
903
904template<typename From>
906
907template<typename T, typename U>
909{
910 QPairVariantInterfaceImpl operator()(const std::pair<T, U>& f) const
911 {
912 return QPairVariantInterfaceImpl(&f);
913 }
914};
915
916}
917
918class QObject;
919
920#define QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER(Name)
921 template <class T> class Name;
922
923QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER)
924
925namespace QtPrivate
926{
927 // Note: this does not check that T = U* isn't pointing to a
928 // forward-declared type. You may want to combine with
929 // checkTypeIsSuitableForMetaType().
930 template<typename T>
932 {
933 enum { Value = false };
934 };
935
936 // Specialize to avoid sizeof(void) warning
937 template<>
939 {
940 enum { Value = false };
941 };
942 template<>
944 {
945 enum { Value = false };
946 };
947 template<>
949 {
950 enum { Value = true };
951 };
952
953 template<typename T>
955 {
958
959#ifndef QT_NO_QOBJECT
960 static yes_type checkType(QObject* );
961 static yes_type checkType(const QObject* );
962#endif
963 static no_type checkType(...);
964 enum { Value = sizeof(checkType(static_cast<T*>(nullptr))) == sizeof(yes_type) };
965 };
966
967 template<typename T, typename Enable = void>
968 struct IsGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; };
969
970 template<typename T>
971 struct IsGadgetHelper<T, typename T::QtGadgetHelper>
972 {
973 template <typename X>
974 static char checkType(void (X::*)());
975 static void *checkType(void (T::*)());
976 enum {
977 IsRealGadget = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *),
979 };
980 };
981
982 template <typename T>
984
985 template<typename T, typename Enable = void>
986 struct IsPointerToGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; };
987
988 template<typename T>
990 {
991 using BaseType = T;
992 template <typename X>
993 static char checkType(void (X::*)());
994 static void *checkType(void (T::*)());
995 enum {
996 IsRealGadget = !IsPointerToTypeDerivedFromQObject<T*>::Value && sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *),
998 };
999 };
1000
1001
1002 template<typename T> char qt_getEnumMetaObject(const T&);
1003
1004 template<typename T>
1006 static const T &declval();
1007 // If the type was declared with Q_ENUM, the friend qt_getEnumMetaObject() declared in the
1008 // Q_ENUM macro will be chosen by ADL, and the return type will be QMetaObject*.
1009 // Otherwise the chosen overload will be the catch all template function
1010 // qt_getEnumMetaObject(T) which returns 'char'
1011 enum { Value = sizeof(qt_getEnumMetaObject(declval())) == sizeof(QMetaObject*) };
1012 };
1013 template<> struct IsQEnumHelper<void> { enum { Value = false }; };
1014
1015 template<typename T, typename Enable = void>
1017 {
1018 static constexpr const QMetaObject *value() { return nullptr; }
1019 using MetaObjectFn = const QMetaObject *(*)(const QMetaTypeInterface *);
1020 static constexpr MetaObjectFn metaObjectFunction = nullptr;
1021 };
1022#ifndef QT_NO_QOBJECT
1023 template<typename T>
1025 {
1026 static constexpr const QMetaObject *value() { return &T::staticMetaObject; }
1027 static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return &T::staticMetaObject; }
1028 };
1029 template<typename T>
1034 >
1035 >>
1036 {
1037 static constexpr const QMetaObject *value() { return &T::staticMetaObject; }
1038 static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return &T::staticMetaObject; }
1039 };
1040 template<typename T>
1042 {
1043 static constexpr const QMetaObject *value()
1044 {
1046 }
1047 static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return value(); }
1048 };
1049 template<typename T>
1051 {
1052 static constexpr const QMetaObject *value() { return qt_getEnumMetaObject(T()); }
1053 static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return value(); }
1054 };
1055#endif
1056
1057 template<typename T>
1059 {
1060 enum { Value = false };
1061 };
1062
1063 template<typename T>
1067
1068 template<typename T>
1070 {
1071 enum { Value = false };
1072 };
1073
1074 template<typename T>
1078
1079 template<typename T>
1081 {
1082 enum { Value = false };
1083 };
1084
1085 template<typename T>
1087 {
1088 enum { Value = true };
1089 };
1090
1091 template<typename T>
1093 {
1094 enum { Value = false };
1095 };
1096
1097 template<typename T>
1099 {
1100 enum { Value = false };
1101 };
1102
1103 template<typename T, bool = QtPrivate::IsSequentialContainer<T>::Value>
1105 {
1106 static bool registerConverter()
1107 {
1108 return false;
1109 }
1110
1112 {
1113 return false;
1114 }
1115 };
1116
1117 template<typename T, bool = QMetaTypeId2<typename T::value_type>::Defined>
1119 {
1120 static bool registerConverter()
1121 {
1122 return false;
1123 }
1124
1126 {
1127 return false;
1128 }
1129 };
1130
1131 template<typename T>
1135
1136 template<typename T, bool = QtPrivate::IsAssociativeContainer<T>::Value>
1138 {
1139 static bool registerConverter()
1140 {
1141 return false;
1142 }
1143
1145 {
1146 return false;
1147 }
1148 };
1149
1150 template<typename T, bool = QMetaTypeId2<typename T::key_type>::Defined>
1152 {
1153 static bool registerConverter()
1154 {
1155 return false;
1156 }
1157
1159 {
1160 return false;
1161 }
1162 };
1163
1164 template<typename T, bool = QMetaTypeId2<typename T::mapped_type>::Defined>
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 = QMetaTypeId2<typename T::first_type>::Defined
1184 && QMetaTypeId2<typename T::second_type>::Defined>
1186 {
1187 static bool registerConverter()
1188 {
1189 return false;
1190 }
1191 };
1192
1193 template<typename T>
1194 struct IsMetaTypePair<T, true>
1195 {
1196 inline static bool registerConverter();
1197 };
1198
1199 template<typename T>
1200 struct IsPair
1201 {
1202 static bool registerConverter()
1203 {
1204 return false;
1205 }
1206 };
1207 template<typename T, typename U>
1208 struct IsPair<std::pair<T, U> > : IsMetaTypePair<std::pair<T, U> > {};
1209
1210 template<typename T>
1212
1213 template<typename T, typename = void>
1215 {
1216 static bool registerConverter() { return false; }
1217 };
1218
1219#if QT_CONFIG(future)
1220 template<typename T>
1222 {
1223 static bool registerConverter() { return false; }
1224 };
1225#endif
1226
1227} // namespace QtPrivate
1228
1229template <typename T, int =
1230 QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject :
1231 QtPrivate::IsRealGadget<T>::value ? QMetaType::IsGadget :
1232 QtPrivate::IsPointerToGadgetHelper<T>::IsRealGadget ? QMetaType::PointerToGadget :
1233 QtPrivate::IsQEnumHelper<T>::Value ? QMetaType::IsEnumeration : 0>
1234struct QMetaTypeIdQObject
1235{
1236 enum {
1237 Defined = 0
1238 };
1239};
1240
1241template <typename T>
1243{
1244};
1245
1246template <typename T>
1248{
1249 using NameAsArrayType = void;
1250 enum { Defined = QMetaTypeId<T>::Defined, IsBuiltIn=false };
1251 static inline constexpr int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }
1252};
1253
1254template <typename T>
1255struct QMetaTypeId2<const T&> : QMetaTypeId2<T> {};
1256
1257template <typename T>
1259{
1260 using NameAsArrayType = void;
1261 enum { Defined = false, IsBuiltIn = false };
1262 static inline constexpr int qt_metatype_id() { return 0; }
1263};
1264
1265namespace QtPrivate {
1266 template <typename T, bool Defined = QMetaTypeId2<T>::Defined>
1268 static inline constexpr int qt_metatype_id()
1269 { return QMetaTypeId2<T>::qt_metatype_id(); }
1270 };
1271 template <typename T> struct QMetaTypeIdHelper<T, false> {
1272 static inline constexpr int qt_metatype_id()
1273 { return -1; }
1274 };
1275
1276 // Function pointers don't derive from QObject
1277 template <typename Result, typename... Args>
1278 struct IsPointerToTypeDerivedFromQObject<Result(*)(Args...)> { enum { Value = false }; };
1279
1280 template<typename T>
1281 inline constexpr bool IsQmlListType = false;
1282
1283 template<typename T, bool = std::is_enum<T>::value>
1284 constexpr bool IsUnsignedEnum = false;
1285 template<typename T>
1286 constexpr bool IsUnsignedEnum<T, true> = !std::is_signed_v<std::underlying_type_t<T>>;
1287
1288 template<typename T, bool defined>
1290 {
1291 enum DefinedType { Defined = defined };
1292 };
1293
1294 template<typename SmartPointer>
1296 {
1297 QObject* operator()(const SmartPointer &p) const
1298 {
1299 return p.operator->();
1300 }
1301 };
1302
1303 // hack to delay name lookup to instantiation time by making
1304 // EnableInternalData a dependent name:
1305 template <typename T>
1307
1308 template<typename T>
1310 {
1311 QObject* operator()(const QWeakPointer<T> &p) const
1312 {
1313 return QtPrivate::EnableInternalDataWrap<T>::internalData(p);
1314 }
1315 };
1316}
1317
1318template <typename T>
1319int qRegisterNormalizedMetaTypeImplementation(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName)
1320{
1321#ifndef QT_NO_QOBJECT
1322 Q_ASSERT_X(normalizedTypeName == QMetaObject::normalizedType(normalizedTypeName.constData()),
1323 "qRegisterNormalizedMetaType",
1324 "qRegisterNormalizedMetaType was called with a not normalized type name, "
1325 "please call qRegisterMetaType instead.");
1326#endif
1327
1328 const QMetaType metaType = QMetaType::fromType<T>();
1329 const int id = metaType.id();
1330
1331 QtPrivate::SequentialContainerTransformationHelper<T>::registerConverter();
1332 QtPrivate::SequentialContainerTransformationHelper<T>::registerMutableView();
1333 QtPrivate::AssociativeContainerTransformationHelper<T>::registerConverter();
1334 QtPrivate::AssociativeContainerTransformationHelper<T>::registerMutableView();
1335 QtPrivate::MetaTypePairHelper<T>::registerConverter();
1336 QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter();
1337#if QT_CONFIG(future)
1338 QtPrivate::MetaTypeQFutureHelper<T>::registerConverter();
1339#endif
1340
1341 if (normalizedTypeName != metaType.name())
1342 QMetaType::registerNormalizedTypedef(normalizedTypeName, metaType);
1343
1344 return id;
1345}
1346
1347// This primary template calls the -Implementation, like all other specialisations should.
1348// But the split allows to
1349// - in a header:
1350// - define a specialization of this template calling an out-of-line function
1351// (QT_DECL_METATYPE_EXTERN{,_TAGGED})
1352// - in the .cpp file:
1353// - define the out-of-line wrapper to call the -Implementation
1354// (QT_IMPL_METATYPE_EXTERN{,_TAGGED})
1355// The _TAGGED variants let you choose a tag (must be a C identifier) to disambiguate
1356// the out-of-line function; the non-_TAGGED variants use the passed class name as tag.
1357template <typename T>
1358int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName)
1359{
1360 return qRegisterNormalizedMetaTypeImplementation<T>(normalizedTypeName);
1361}
1362
1363#if defined(QT_BOOTSTRAPPED)
1364#define QT_DECL_METATYPE_EXTERN_TAGGED(TYPE, TAG, EXPORT)
1365#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG)
1366#else
1367#define QT_DECL_METATYPE_EXTERN_TAGGED(TYPE, TAG, EXPORT)
1368 QT_BEGIN_NAMESPACE
1369 EXPORT int qRegisterNormalizedMetaType_ ## TAG (const QByteArray &);
1370 template <> inline int qRegisterNormalizedMetaType< TYPE >(const QByteArray &name)
1371 { return qRegisterNormalizedMetaType_ ## TAG (name); }
1372 QT_END_NAMESPACE
1373 Q_DECLARE_METATYPE(TYPE)
1374 /* end */
1375#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG)
1376 int qRegisterNormalizedMetaType_ ## TAG (const QByteArray &name)
1377 { return qRegisterNormalizedMetaTypeImplementation< TYPE >(name); }
1378 /* end */
1379#endif
1380#define QT_DECL_METATYPE_EXTERN(TYPE, EXPORT)
1381 QT_DECL_METATYPE_EXTERN_TAGGED(TYPE, TYPE, EXPORT)
1382#define QT_IMPL_METATYPE_EXTERN(TYPE)
1384
1385template <typename T>
1386int qRegisterMetaType(const char *typeName)
1387{
1388#ifdef QT_NO_QOBJECT
1389 QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = typeName;
1390#else
1391 QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
1392#endif
1393 return qRegisterNormalizedMetaType<T>(normalizedTypeName);
1394}
1395
1396template <typename T>
1397inline constexpr int qMetaTypeId()
1398{
1399 if constexpr (bool(QMetaTypeId2<T>::IsBuiltIn)) {
1400 // this has the same result as the below code, but avoids asking the
1401 // compiler to load a global variable whose value we know at compile
1402 // time
1403 return QMetaTypeId2<T>::MetaType;
1404 } else {
1405 return QMetaType::fromType<T>().id();
1406 }
1407}
1408
1409template <typename T>
1410inline constexpr int qRegisterMetaType()
1411{
1412 int id = qMetaTypeId<T>();
1413 return id;
1414}
1415
1416inline int qRegisterMetaType(QMetaType meta)
1417{
1418 return meta.registerHelper();
1419}
1420
1421#ifndef QT_NO_QOBJECT
1422template <typename T>
1424{
1425 enum {
1427 };
1428
1429 static int qt_metatype_id()
1430 {
1431 Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1432 if (const int id = metatype_id.loadAcquire())
1433 return id;
1434 const char *const cName = T::staticMetaObject.className();
1435 QByteArray typeName;
1436 typeName.reserve(strlen(cName) + 1);
1437 typeName.append(cName).append('*');
1438 const int newId = qRegisterNormalizedMetaType<T *>(typeName);
1439 metatype_id.storeRelease(newId);
1440 return newId;
1441 }
1442};
1443
1444template <typename T>
1445struct QMetaTypeIdQObject<T, QMetaType::IsGadget>
1446{
1447 enum {
1448 Defined = std::is_default_constructible<T>::value
1449 };
1450
1451 static int qt_metatype_id()
1452 {
1453 Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1454 if (const int id = metatype_id.loadAcquire())
1455 return id;
1456 const char *const cName = T::staticMetaObject.className();
1457 const int newId = qRegisterNormalizedMetaType<T>(cName);
1458 metatype_id.storeRelease(newId);
1459 return newId;
1460 }
1461};
1462
1463template <typename T>
1464struct QMetaTypeIdQObject<T*, QMetaType::PointerToGadget>
1465{
1466 enum {
1467 Defined = 1
1468 };
1469
1470 static int qt_metatype_id()
1471 {
1472 Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1473 if (const int id = metatype_id.loadAcquire())
1474 return id;
1475 const char *const cName = T::staticMetaObject.className();
1476 QByteArray typeName;
1477 typeName.reserve(strlen(cName) + 1);
1478 typeName.append(cName).append('*');
1479 const int newId = qRegisterNormalizedMetaType<T *>(typeName);
1480 metatype_id.storeRelease(newId);
1481 return newId;
1482 }
1483};
1484
1485template <typename T>
1486struct QMetaTypeIdQObject<T, QMetaType::IsEnumeration>
1487{
1488 enum {
1489 Defined = 1
1490 };
1491
1492 static int qt_metatype_id()
1493 {
1494 Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1495 if (const int id = metatype_id.loadAcquire())
1496 return id;
1497 const char *eName = qt_getEnumName(T());
1498 const char *cName = qt_getEnumMetaObject(T())->className();
1499 QByteArray typeName;
1500 typeName.reserve(strlen(cName) + 2 + strlen(eName));
1501 typeName.append(cName).append("::").append(eName);
1502 const int newId = qRegisterNormalizedMetaType<T>(typeName);
1503 metatype_id.storeRelease(newId);
1504 return newId;
1505 }
1506};
1507#endif
1508
1509#define Q_DECLARE_OPAQUE_POINTER(POINTER)
1510 QT_BEGIN_NAMESPACE namespace QtPrivate {
1511 template <> struct IsPointerDeclaredOpaque<POINTER>
1512 : std::true_type {};
1513 } QT_END_NAMESPACE
1514 /**/
1515
1516#ifndef Q_MOC_RUN
1517#define Q_DECLARE_METATYPE(TYPE) Q_DECLARE_METATYPE_IMPL(TYPE)
1518#define Q_DECLARE_METATYPE_IMPL(TYPE)
1519 QT_BEGIN_NAMESPACE
1520 template <>
1521 struct QMetaTypeId< TYPE >
1522 {
1523 enum { Defined = 1 };
1524 static_assert(QtPrivate::checkTypeIsSuitableForMetaType<TYPE>());
1525 static int qt_metatype_id()
1526 {
1527 Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1528 if (const int id = metatype_id.loadAcquire())
1529 return id;
1530 constexpr auto arr = QtPrivate::typenameHelper<TYPE>();
1531 auto name = arr.data();
1532 if (QByteArrayView(name) == (#TYPE)) {
1533 const int id = qRegisterNormalizedMetaType<TYPE>(name);
1534 metatype_id.storeRelease(id);
1535 return id;
1536 }
1537 const int newId = qRegisterMetaType< TYPE >(#TYPE);
1538 metatype_id.storeRelease(newId);
1539 return newId;
1540 }
1541 };
1542 QT_END_NAMESPACE
1543#endif // Q_MOC_RUN
1544
1545#define Q_DECLARE_BUILTIN_METATYPE(TYPE, METATYPEID, NAME)
1546 QT_BEGIN_NAMESPACE
1547 template<> struct QMetaTypeId2<NAME>
1548 {
1549 using NameAsArrayType = std::array<char, sizeof(#NAME)>;
1550 enum { Defined = 1, IsBuiltIn = true, MetaType = METATYPEID };
1551 static inline constexpr int qt_metatype_id() { return METATYPEID; }
1552 static constexpr NameAsArrayType nameAsArray = { #NAME };
1553 };
1554 QT_END_NAMESPACE
1555
1556#define QT_FORWARD_DECLARE_STATIC_TYPES_ITER(TypeName, TypeId, Name)
1557 class Name;
1558
1559QT_FOR_EACH_STATIC_CORE_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1560QT_FOR_EACH_STATIC_GUI_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1561QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1562
1563#undef QT_FORWARD_DECLARE_STATIC_TYPES_ITER
1564
1565#define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE) QT_BEGIN_NAMESPACE
1566 template
1567 <typename T> struct
1568 QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \
1569{
1570 enum {
1571 Defined = QMetaTypeId2<T>::Defined
1572 };
1573 static int qt_metatype_id()
1574 {
1575 Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1576 if (const int id = metatype_id.loadRelaxed())
1577 return id;
1578 const char *tName = QMetaType::fromType<T>().name();
1579 Q_ASSERT(tName);
1580 const size_t tNameLen = qstrlen(tName);
1581 QByteArray typeName;
1582 typeName.reserve(sizeof(#SINGLE_ARG_TEMPLATE) + 1 + tNameLen + 1 + 1);
1583 typeName.append(#SINGLE_ARG_TEMPLATE, int(sizeof(#SINGLE_ARG_TEMPLATE)) - 1)
1584 .append('<').append(tName, tNameLen);
1585 typeName.append('>');
1586 const int newId = qRegisterNormalizedMetaType< SINGLE_ARG_TEMPLATE<T> >(typeName);
1587 metatype_id.storeRelease(newId);
1588 return newId;
1589 } \
1590};QT_END_NAMESPACE
1591
1592
1593#define Q_DECLARE_METATYPE_TEMPLATE_2ARG(DOUBLE_ARG_TEMPLATE) QT_BEGIN_NAMESPACE
1594 template
1595 <typename T, typename U> struct
1596 QMetaTypeId< DOUBLE_ARG_TEMPLATE<T, U> > \
1597{
1598 enum {
1599 Defined = QMetaTypeId2<T>::Defined && QMetaTypeId2<U>::Defined
1600 };
1601 static int qt_metatype_id()
1602 {
1603 Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1604 if (const int id = metatype_id.loadAcquire())
1605 return id;
1606 const char *tName = QMetaType::fromType<T>().name();
1607 const char *uName = QMetaType::fromType<U>().name();
1608 Q_ASSERT(tName);
1609 Q_ASSERT(uName);
1610 const size_t tNameLen = qstrlen(tName);
1611 const size_t uNameLen = qstrlen(uName);
1612 QByteArray typeName;
1613 typeName.reserve(sizeof(#DOUBLE_ARG_TEMPLATE) + 1 + tNameLen + 1 + uNameLen + 1 + 1);
1614 typeName.append(#DOUBLE_ARG_TEMPLATE, int(sizeof(#DOUBLE_ARG_TEMPLATE)) - 1)
1615 .append('<').append(tName, tNameLen).append(',').append(uName, uNameLen);
1616 typeName.append('>');
1617 const int newId = qRegisterNormalizedMetaType< DOUBLE_ARG_TEMPLATE<T, U> >(typeName);
1618 metatype_id.storeRelease(newId);
1619 return newId;
1620 } \
1621};QT_END_NAMESPACE
1622
1623
1624namespace QtPrivate {
1625
1626template<typename T, bool /* isSharedPointerToQObjectDerived */ = false>
1628{
1629 enum {
1631 };
1632 static int qt_metatype_id()
1633 {
1634 return -1;
1635 }
1636};
1637
1638}
1639
1640#define Q_DECLARE_SMART_POINTER_METATYPE(SMART_POINTER) QT_BEGIN_NAMESPACE
1641 namespace
1642 QtPrivate { template
1643 <typename T> struct
1644 SharedPointerMetaTypeIdHelper<SMART_POINTER<T>, true> \
1645{
1646 enum {
1647 Defined = 1
1648 };
1649 static int qt_metatype_id()
1650 {
1651 Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1652 if (const int id = metatype_id.loadAcquire())
1653 return id;
1654 const char * const cName = T::staticMetaObject.className();
1655 QByteArray typeName;
1656 typeName.reserve(sizeof(#SMART_POINTER) + 1 + strlen(cName) + 1);
1657 typeName.append(#SMART_POINTER, int(sizeof(#SMART_POINTER)) - 1)
1658 .append('<').append(cName).append('>');
1659 const int newId = qRegisterNormalizedMetaType< SMART_POINTER<T> >(typeName);
1660 metatype_id.storeRelease(newId);
1661 return newId;
1662 } \
1663};template
1664 <typename T> struct
1665 MetaTypeSmartPointerHelper<SMART_POINTER<T> ,
1666 typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value && !std::is_const_v<T>>::type> \
1667{
1668 static bool registerConverter()
1669 {
1670 const QMetaType to = QMetaType(QMetaType::QObjectStar);
1671 if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<SMART_POINTER<T>>(), to)) {
1672 QtPrivate::QSmartPointerConvertFunctor<SMART_POINTER<T> > o;
1673 return QMetaType::registerConverter<SMART_POINTER<T>, QObject*>(o);
1674 }
1675 return true;
1676 } \
1677};\
1678}template
1679 <typename T> struct
1680 QMetaTypeId< SMART_POINTER<T> >
1681 : QtPrivate::SharedPointerMetaTypeIdHelper< SMART_POINTER<T>,
1682 QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value> \
1683{\
1684};QT_END_NAMESPACE
1685
1686
1687#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(SINGLE_ARG_TEMPLATE)
1688 QT_BEGIN_NAMESPACE
1689 namespace QtPrivate {
1690 template<typename T>
1691 struct IsSequentialContainer<SINGLE_ARG_TEMPLATE<T> >
1692 {
1693 enum { Value = true };
1694 };
1695 }
1696 QT_END_NAMESPACE
1697 Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE)
1698
1699#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER(TEMPLATENAME)
1701
1703
1705
1706#undef Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER
1707
1710
1711#define Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(TEMPLATENAME)
1712 QT_BEGIN_NAMESPACE
1713 namespace QtPrivate {
1714 template<typename T, typename U>
1715 struct IsAssociativeContainer<TEMPLATENAME<T, U> >
1716 {
1717 enum { Value = true };
1718 };
1719 }
1720 QT_END_NAMESPACE
1722
1726
1728
1729#define Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER(TEMPLATENAME)
1731
1733
1735
1736#undef Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER
1737
1738QT_END_NAMESPACE
1739
1741
1742
1744
1745namespace QtPrivate {
1746// out-of-line helpers to reduce template code bloat ("SCARY") and improve compile times:
1747Q_CORE_EXPORT bool hasRegisteredConverterFunctionToPairVariantInterface(QMetaType m);
1748Q_CORE_EXPORT bool hasRegisteredConverterFunctionToIterableMetaSequence(QMetaType m);
1749Q_CORE_EXPORT bool hasRegisteredMutableViewFunctionToIterableMetaSequence(QMetaType m);
1750Q_CORE_EXPORT bool hasRegisteredConverterFunctionToIterableMetaAssociation(QMetaType m);
1751Q_CORE_EXPORT bool hasRegisteredMutableViewFunctionToIterableMetaAssociation(QMetaType m);
1752}
1753
1754template <typename T>
1756{
1759 return QMetaType::registerConverter<T, QtMetaTypePrivate::QPairVariantInterfaceImpl>(o);
1760 }
1761 return true;
1762}
1763
1764namespace QtPrivate {
1765
1766template<typename From>
1768{
1769 QIterable<QMetaSequence> operator()(const From &f) const
1770 {
1771 return QIterable<QMetaSequence>(QMetaSequence::fromContainer<From>(), &f);
1772 }
1773};
1774
1775template<typename From>
1777{
1779 {
1780 return QIterable<QMetaSequence>(QMetaSequence::fromContainer<From>(), &f);
1781 }
1782};
1783
1784template<typename T>
1786{
1787 static bool registerConverter()
1788 {
1791 return QMetaType::registerConverter<T, QIterable<QMetaSequence>>(o);
1792 }
1793 return true;
1794 }
1795
1797 {
1800 return QMetaType::registerMutableView<T, QIterable<QMetaSequence>>(o);
1801 }
1802 return true;
1803 }
1804};
1805
1806template<typename From>
1808{
1809 QIterable<QMetaAssociation> operator()(const From &f) const
1810 {
1811 return QIterable<QMetaAssociation>(QMetaAssociation::fromContainer<From>(), &f);
1812 }
1813};
1814
1815template<typename From>
1817{
1819 {
1820 return QIterable<QMetaAssociation>(QMetaAssociation::fromContainer<From>(), &f);
1821 }
1822};
1823
1824// Mapped type can be omitted, for example in case of a set.
1825// However, if it is available, we want to instantiate the metatype here.
1826template<typename T>
1828{
1829 static bool registerConverter()
1830 {
1833 return QMetaType::registerConverter<T, QIterable<QMetaAssociation>>(o);
1834 }
1835 return true;
1836 }
1837
1839 {
1842 return QMetaType::registerMutableView<T, QIterable<QMetaAssociation>>(o);
1843 }
1844 return true;
1845 }
1846};
1847
1849{
1850 char *output;
1851 int len = 0;
1852 char last = 0;
1853
1854private:
1855 static constexpr bool is_ident_char(char s)
1856 {
1857 return ((s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z') || (s >= '0' && s <= '9')
1858 || s == '_');
1859 }
1860 static constexpr bool is_space(char s) { return (s == ' ' || s == '\t' || s == '\n'); }
1861 static constexpr bool is_number(char s) { return s >= '0' && s <= '9'; }
1862 static constexpr bool starts_with_token(const char *b, const char *e, const char *token,
1863 bool msvcKw = false)
1864 {
1865 while (b != e && *token && *b == *token) {
1866 b++;
1867 token++;
1868 }
1869 if (*token)
1870 return false;
1871#ifdef Q_CC_MSVC
1872 /// On MSVC, keywords like class or struct are not separated with spaces in constexpr
1873 /// context
1874 if (msvcKw && !is_ident_char(*b))
1875 return true;
1876#endif
1877 Q_UNUSED(msvcKw);
1878 return b == e || !is_ident_char(*b);
1879 }
1880 static constexpr bool skipToken(const char *&x, const char *e, const char *token,
1881 bool msvcKw = false)
1882 {
1883 if (!starts_with_token(x, e, token, msvcKw))
1884 return false;
1885 while (*token++)
1886 x++;
1887 while (x != e && is_space(*x))
1888 x++;
1889 return true;
1890 }
1891 static constexpr const char *skipString(const char *x, const char *e)
1892 {
1893 char delim = *x;
1894 x++;
1895 while (x != e && *x != delim) {
1896 if (*x == '\\') {
1897 x++;
1898 if (x == e)
1899 return e;
1900 }
1901 x++;
1902 }
1903 if (x != e)
1904 x++;
1905 return x;
1906 }
1907 static constexpr const char *skipTemplate(const char *x, const char *e, bool stopAtComa = false)
1908 {
1909 int scopeDepth = 0;
1910 int templateDepth = 0;
1911 while (x != e) {
1912 switch (*x) {
1913 case '<':
1914 if (!scopeDepth)
1915 templateDepth++;
1916 break;
1917 case ',':
1918 if (stopAtComa && !scopeDepth && !templateDepth)
1919 return x;
1920 break;
1921 case '>':
1922 if (!scopeDepth)
1923 if (--templateDepth < 0)
1924 return x;
1925 break;
1926 case '(':
1927 case '[':
1928 case '{':
1929 scopeDepth++;
1930 break;
1931 case '}':
1932 case ']':
1933 case ')':
1934 scopeDepth--;
1935 break;
1936 case '\'':
1937 if (is_number(x[-1]))
1938 break;
1939 Q_FALLTHROUGH();
1940 case '\"':
1941 x = skipString(x, e);
1942 continue;
1943 }
1944 x++;
1945 }
1946 return x;
1947 }
1948
1949 constexpr void append(char x)
1950 {
1951 last = x;
1952 len++;
1953 if (output)
1954 *output++ = x;
1955 }
1956
1957 constexpr void replaceLast(char x)
1958 {
1959 last = x;
1960 if (output)
1961 *(output - 1) = x;
1962 }
1963
1964 constexpr void appendStr(const char *x)
1965 {
1966 while (*x)
1967 append(*x++);
1968 }
1969
1970 constexpr void normalizeIntegerTypes(const char *&begin, const char *end)
1971 {
1972 int numLong = 0;
1973 int numSigned = 0;
1974 int numUnsigned = 0;
1975 int numInt = 0;
1976 int numShort = 0;
1977 int numChar = 0;
1978 while (begin < end) {
1979 if (skipToken(begin, end, "long")) {
1980 numLong++;
1981 continue;
1982 }
1983 if (skipToken(begin, end, "int")) {
1984 numInt++;
1985 continue;
1986 }
1987 if (skipToken(begin, end, "short")) {
1988 numShort++;
1989 continue;
1990 }
1991 if (skipToken(begin, end, "unsigned")) {
1992 numUnsigned++;
1993 continue;
1994 }
1995 if (skipToken(begin, end, "signed")) {
1996 numSigned++;
1997 continue;
1998 }
1999 if (skipToken(begin, end, "char")) {
2000 numChar++;
2001 continue;
2002 }
2003#ifdef Q_CC_MSVC
2004 if (skipToken(begin, end, "__int64")) {
2005 numLong = 2;
2006 continue;
2007 }
2008#endif
2009 break;
2010 }
2011 if (numLong == 2)
2012 append('q'); // q(u)longlong
2013 if (numSigned && numChar)
2014 appendStr("signed ");
2015 else if (numUnsigned)
2016 appendStr("u");
2017 if (numChar)
2018 appendStr("char");
2019 else if (numShort)
2020 appendStr("short");
2021 else if (numLong == 1)
2022 appendStr("long");
2023 else if (numLong == 2)
2024 appendStr("longlong");
2025 else if (numUnsigned || numSigned || numInt)
2026 appendStr("int");
2027 }
2028
2029 constexpr void skipStructClassOrEnum(const char *&begin, const char *end)
2030 {
2031 // discard 'struct', 'class', and 'enum'; they are optional
2032 // and we don't want them in the normalized signature
2033 skipToken(begin, end, "struct", true) || skipToken(begin, end, "class", true)
2034 || skipToken(begin, end, "enum", true);
2035 }
2036
2037 constexpr void skipQtNamespace(const char *&begin, const char *end)
2038 {
2039#ifdef QT_NAMESPACE
2040 const char *nsbeg = begin;
2041 if (skipToken(nsbeg, end, QT_STRINGIFY(QT_NAMESPACE)) && nsbeg + 2 < end && nsbeg[0] == ':'
2042 && nsbeg[1] == ':') {
2043 begin = nsbeg + 2;
2044 while (begin != end && is_space(*begin))
2045 begin++;
2046 }
2047#else
2048 Q_UNUSED(begin);
2049 Q_UNUSED(end);
2050#endif
2051 }
2052
2053public:
2054#if defined(Q_CC_CLANG) || defined (Q_CC_GNU)
2055 // this is much simpler than the full type normalization below
2056 // the reason is that the signature returned by Q_FUNC_INFO is already
2057 // normalized to the largest degree, and we need to do only small adjustments
2058 constexpr int normalizeTypeFromSignature(const char *begin, const char *end)
2059 {
2060 // bail out if there is an anonymous struct
2062#if defined (Q_CC_CLANG)
2063 if (name.find("anonymous ") != std::string_view::npos)
2064 return normalizeType(begin, end);
2065#endif
2066 if (name.find("unnamed ") != std::string_view::npos)
2067 return normalizeType(begin, end);
2068 while (begin < end) {
2069 if (*begin == ' ') {
2070 if (last == ',' || last == '>' || last == '<' || last == '*' || last == '&') {
2071 ++begin;
2072 continue;
2073 }
2074 }
2075 if (last == ' ') {
2076 if (*begin == '*' || *begin == '&' || *begin == '(') {
2078 ++begin;
2079 continue;
2080 }
2081 }
2082 if (!is_ident_char(last)) {
2084 if (begin == end)
2085 break;
2086
2088 if (begin == end)
2089 break;
2090
2092 if (begin == end)
2093 break;
2094 }
2095 append(*begin);
2096 ++begin;
2097 }
2098 return len;
2099 }
2100#else
2101 // MSVC needs the full normalization, as it puts the const in a different
2102 // place than we expect
2103 constexpr int normalizeTypeFromSignature(const char *begin, const char *end)
2104 { return normalizeType(begin, end); }
2105#endif
2106
2107 constexpr int normalizeType(const char *begin, const char *end, bool adjustConst = true)
2108 {
2109 // Trim spaces
2110 while (begin != end && is_space(*begin))
2111 begin++;
2112 while (begin != end && is_space(*(end - 1)))
2113 end--;
2114
2115 if (begin == end)
2116 return len;
2117
2118 // Convert 'char const *' into 'const char *'. Start at index 1,
2119 // not 0, because 'const char *' is already OK.
2120 const char *cst = begin + 1;
2121 if (*begin == '\'' || *begin == '"')
2122 cst = skipString(begin, end);
2123 bool seenStar = false;
2124 bool hasMiddleConst = false;
2125 while (cst < end) {
2126 if (*cst == '\"' || (*cst == '\'' && !is_number(cst[-1]))) {
2127 cst = skipString(cst, end);
2128 if (cst == end)
2129 break;
2130 }
2131
2132 // We mustn't convert 'char * const *' into 'const char **'
2133 // and we must beware of 'Bar<const Bla>'.
2134 if (*cst == '&' || *cst == '*' || *cst == '[') {
2135 seenStar = *cst != '&' || cst != (end - 1);
2136 break;
2137 }
2138 if (*cst == '<') {
2139 cst = skipTemplate(cst + 1, end);
2140 if (cst == end)
2141 break;
2142 }
2143 cst++;
2144 const char *skipedCst = cst;
2145 if (!is_ident_char(*(cst - 1)) && skipToken(skipedCst, end, "const")) {
2146 const char *testEnd = end;
2147 while (skipedCst < testEnd--) {
2148 if (*testEnd == '*' || *testEnd == '['
2149 || (*testEnd == '&' && testEnd != (end - 1))) {
2150 seenStar = true;
2151 break;
2152 }
2153 if (*testEnd == '>')
2154 break;
2155 }
2156 if (adjustConst && !seenStar) {
2157 if (*(end - 1) == '&')
2158 end--;
2159 } else {
2160 appendStr("const ");
2161 }
2162 normalizeType(begin, cst, false);
2163 begin = skipedCst;
2164 hasMiddleConst = true;
2165 break;
2166 }
2167 }
2168 if (skipToken(begin, end, "const")) {
2169 if (adjustConst && !seenStar) {
2170 if (*(end - 1) == '&')
2171 end--;
2172 } else {
2173 appendStr("const ");
2174 }
2175 }
2176 if (seenStar && adjustConst) {
2177 const char *e = end;
2178 if (*(end - 1) == '&' && *(end - 2) != '&')
2179 e--;
2180 while (begin != e && is_space(*(e - 1)))
2181 e--;
2182 const char *token = "tsnoc"; // 'const' reverse, to check if it ends with const
2183 while (*token && begin != e && *(--e) == *token++)
2184 ;
2185 if (!*token && begin != e && !is_ident_char(*(e - 1))) {
2186 while (begin != e && is_space(*(e - 1)))
2187 e--;
2188 end = e;
2189 }
2190 }
2191
2192 skipStructClassOrEnum(begin, end);
2193 skipQtNamespace(begin, end);
2194
2195 if (skipToken(begin, end, "QVector")) {
2196 // Replace QVector by QList
2197 appendStr("QList");
2198 }
2199
2200 if (skipToken(begin, end, "QPair")) {
2201 // replace QPair by std::pair
2202 appendStr("std::pair");
2203 }
2204
2205 if (!hasMiddleConst)
2206 // Normalize the integer types
2207 normalizeIntegerTypes(begin, end);
2208
2209 bool spaceSkiped = true;
2210 while (begin != end) {
2211 char c = *begin++;
2212 if (is_space(c)) {
2213 spaceSkiped = true;
2214 } else if ((c == '\'' && !is_number(last)) || c == '\"') {
2215 begin--;
2216 auto x = skipString(begin, end);
2217 while (begin < x)
2218 append(*begin++);
2219 } else {
2220 if (spaceSkiped && is_ident_char(last) && is_ident_char(c))
2221 append(' ');
2222 append(c);
2223 spaceSkiped = false;
2224 if (c == '<') {
2225 do {
2226 // template recursion
2227 const char *tpl = skipTemplate(begin, end, true);
2228 normalizeType(begin, tpl, false);
2229 if (tpl == end)
2230 return len;
2231 append(*tpl);
2232 begin = tpl;
2233 } while (*begin++ == ',');
2234 }
2235 }
2236 }
2237 return len;
2238 }
2239};
2240
2241// Normalize the type between begin and end, and store the data in the output. Returns the length.
2242// The idea is to first run this function with nullptr as output to allocate the output with the
2243// size
2244constexpr int qNormalizeType(const char *begin, const char *end, char *output)
2245{
2246 return QTypeNormalizer { output }.normalizeType(begin, end);
2247}
2248
2249template<typename T>
2251
2252template <typename T1_, typename T2_>
2253struct is_std_pair<std::pair<T1_, T2_>> : std::true_type {
2254 using T1 = T1_;
2255 using T2 = T2_;
2256};
2257
2259template<typename T>
2260constexpr auto typenameHelper()
2261{
2262 if constexpr (is_std_pair<T>::value) {
2263 using T1 = typename is_std_pair<T>::T1;
2264 using T2 = typename is_std_pair<T>::T2;
2265 std::remove_const_t<std::conditional_t<bool (QMetaTypeId2<T1>::IsBuiltIn), typename QMetaTypeId2<T1>::NameAsArrayType, decltype(typenameHelper<T1>())>> t1Name {};
2266 std::remove_const_t<std::conditional_t<bool (QMetaTypeId2<T2>::IsBuiltIn), typename QMetaTypeId2<T2>::NameAsArrayType, decltype(typenameHelper<T2>())>> t2Name {};
2267 if constexpr (bool (QMetaTypeId2<T1>::IsBuiltIn) ) {
2268 t1Name = QMetaTypeId2<T1>::nameAsArray;
2269 } else {
2270 t1Name = typenameHelper<T1>();
2271 }
2272 if constexpr (bool(QMetaTypeId2<T2>::IsBuiltIn)) {
2273 t2Name = QMetaTypeId2<T2>::nameAsArray;
2274 } else {
2275 t2Name = typenameHelper<T2>();
2276 }
2277 constexpr auto nonTypeDependentLen = sizeof("std::pair<,>");
2278 constexpr auto t1Len = t1Name.size() - 1;
2279 constexpr auto t2Len = t2Name.size() - 1;
2280 constexpr auto length = nonTypeDependentLen + t1Len + t2Len;
2281 std::array<char, length + 1> result {};
2282 constexpr auto prefix = "std::pair<";
2283 int currentLength = 0;
2284 for (; currentLength < int(sizeof("std::pair<") - 1); ++currentLength)
2285 result[currentLength] = prefix[currentLength];
2286 for (int i = 0; i < int(t1Len); ++currentLength, ++i)
2287 result[currentLength] = t1Name[i];
2288 result[currentLength++] = ',';
2289 for (int i = 0; i < int(t2Len); ++currentLength, ++i)
2290 result[currentLength] = t2Name[i];
2291 result[currentLength++] = '>';
2292 result[currentLength++] = '\0';
2293 return result;
2294 } else {
2295 constexpr auto prefix = sizeof(
2296#ifdef QT_NAMESPACE
2297 QT_STRINGIFY(QT_NAMESPACE) "::"
2298#endif
2299#if defined(Q_CC_MSVC) && defined(Q_CC_CLANG)
2300 "auto __cdecl QtPrivate::TypeNameHelper::typenameHelper(void) [T = "
2301#elif defined(Q_CC_MSVC)
2302 "auto __cdecl QtPrivate::TypeNameHelper::typenameHelper<"
2303#elif defined(Q_CC_CLANG)
2304 "auto QtPrivate::TypeNameHelper::typenameHelper() [T = "
2305#elif defined(Q_CC_GHS)
2306 "auto QtPrivate::TypeNameHelper::typenameHelper<T>()[with T="
2307#else
2308 "constexpr auto QtPrivate::TypeNameHelper::typenameHelper() [with T = "
2309#endif
2310 ) - 1;
2311#if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
2312 constexpr int suffix = sizeof(">(void)");
2313#else
2314 constexpr int suffix = sizeof("]");
2315#endif
2316
2317#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU_ONLY < 804
2318 auto func = Q_FUNC_INFO;
2319 const char *begin = func + prefix;
2320 const char *end = func + sizeof(Q_FUNC_INFO) - suffix;
2321 // This is an upper bound of the size since the normalized signature should always be smaller
2322 constexpr int len = sizeof(Q_FUNC_INFO) - suffix - prefix;
2323#else
2324 constexpr auto func = Q_FUNC_INFO;
2325 constexpr const char *begin = func + prefix;
2326 constexpr const char *end = func + sizeof(Q_FUNC_INFO) - suffix;
2327 constexpr int len = QTypeNormalizer{ nullptr }.normalizeTypeFromSignature(begin, end);
2328#endif
2329 std::array<char, len + 1> result {};
2330 QTypeNormalizer{ result.data() }.normalizeTypeFromSignature(begin, end);
2331 return result;
2332 }
2333}
2334} // namespace TypeNameHelper
2335using TypeNameHelper::typenameHelper;
2336
2337template<typename T, typename = void>
2339{
2340};
2341template<typename T>
2346
2347template<typename T, bool = (QTypeTraits::has_operator_equal_v<T> && !std::is_pointer_v<T>)>
2349{
2350QT_WARNING_PUSH
2351QT_WARNING_DISABLE_FLOAT_COMPARE
2352 static bool equals(const QMetaTypeInterface *, const void *a, const void *b)
2353 { return *reinterpret_cast<const T *>(a) == *reinterpret_cast<const T *>(b); }
2355};
2356
2357template<typename T>
2359{
2360 static constexpr QMetaTypeInterface::EqualsFn equals = nullptr;
2361};
2362
2363template<typename T, bool = (QTypeTraits::has_operator_less_than_v<T> && !std::is_pointer_v<T>)>
2365{
2366 static bool lessThan(const QMetaTypeInterface *, const void *a, const void *b)
2367 { return *reinterpret_cast<const T *>(a) < *reinterpret_cast<const T *>(b); }
2368};
2369
2370template<typename T>
2372{
2373 static constexpr QMetaTypeInterface::LessThanFn lessThan = nullptr;
2374};
2375
2376template<typename T, bool = (QTypeTraits::has_ostream_operator_v<QDebug, T> && !std::is_pointer_v<T>)>
2378{
2379 static constexpr QMetaTypeInterface::DebugStreamFn debugStream = nullptr;
2380};
2381
2382#ifndef QT_NO_DEBUG_STREAM
2383template<typename T>
2385{
2386 static void debugStream(const QMetaTypeInterface *, QDebug &dbg, const void *a)
2387 { dbg << *reinterpret_cast<const T *>(a); }
2388};
2389#endif
2390
2391template<typename T, bool = QTypeTraits::has_stream_operator_v<QDataStream, T>>
2397
2398#ifndef QT_NO_DATASTREAM
2399template<typename T>
2401{
2402 static void dataStreamOut(const QMetaTypeInterface *, QDataStream &ds, const void *a)
2403 { ds << *reinterpret_cast<const T *>(a); }
2404 static void dataStreamIn(const QMetaTypeInterface *, QDataStream &ds, void *a)
2405 { ds >> *reinterpret_cast<T *>(a); }
2406};
2407#endif
2408
2409// Performance optimization:
2410//
2411// Don't add all these symbols to the dynamic symbol tables on ELF systems and
2412// on Darwin. Each library is going to have a copy anyway and QMetaType already
2413// copes with some of these being "hidden" (see QMetaType::idHelper()). We may
2414// as well let the linker know it can always use the local copy.
2415//
2416// This is currently not enabled for GCC due to
2417// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106023
2418
2419#if !defined(Q_OS_WIN) && defined(Q_CC_CLANG)
2420# pragma GCC visibility push(hidden)
2421#endif
2422
2423// ### Qt 7: consider removing this infrastructure if nothing uses it
2424// (see also getCopyCtr())
2426{
2427 // Hack to suppress deprecation warnings from types
2428 // with deprecated copy operations, cf. QTBUG-132752
2429 template <typename T>
2431
2432#if !defined(QT_BOOTSTRAPPED)
2433 Q_CORE_EXPORT void warnAboutDeprecatedCopy(const char *name);
2434#endif
2435} // namespace QMetaTypeCopyTraits
2436
2437template<typename S>
2439{
2440public:
2441 static constexpr decltype(typenameHelper<S>()) name = typenameHelper<S>();
2442
2443 static constexpr unsigned flags()
2444 {
2445 uint flags = 0;
2446 if constexpr (QTypeInfo<S>::isRelocatable)
2447 flags |= QMetaType::RelocatableType;
2448 if constexpr (!std::is_default_constructible_v<S> || !QTypeInfo<S>::isValueInitializationBitwiseZero)
2449 flags |= QMetaType::NeedsConstruction;
2450 if constexpr (!std::is_trivially_destructible_v<S>)
2451 flags |= QMetaType::NeedsDestruction;
2452 if constexpr (!std::is_trivially_copy_constructible_v<S>)
2453 flags |= QMetaType::NeedsCopyConstruction;
2454 if constexpr (!std::is_trivially_move_constructible_v<S>)
2455 flags |= QMetaType::NeedsMoveConstruction;
2456 if constexpr (IsPointerToTypeDerivedFromQObject<S>::Value)
2457 flags |= QMetaType::PointerToQObject;
2458 if constexpr (IsSharedPointerToTypeDerivedFromQObject<S>::Value)
2459 flags |= QMetaType::SharedPointerToQObject;
2460 if constexpr (IsWeakPointerToTypeDerivedFromQObject<S>::Value)
2461 flags |= QMetaType::WeakPointerToQObject;
2462 if constexpr (IsTrackingPointerToTypeDerivedFromQObject<S>::Value)
2463 flags |= QMetaType::TrackingPointerToQObject;
2464 if constexpr (IsEnumOrFlags<S>::value)
2465 flags |= QMetaType::IsEnumeration;
2466 if constexpr (IsGadgetHelper<S>::IsGadgetOrDerivedFrom)
2467 flags |= QMetaType::IsGadget;
2468 if constexpr (IsPointerToGadgetHelper<S>::IsGadgetOrDerivedFrom)
2469 flags |= QMetaType::PointerToGadget;
2470 if constexpr (std::is_pointer_v<S>)
2471 flags |= QMetaType::IsPointer;
2472 if constexpr (IsUnsignedEnum<S>)
2473 flags |= QMetaType::IsUnsignedEnumeration;
2474 if constexpr (IsQmlListType<S>)
2475 flags |= QMetaType::IsQmlList;
2476 if constexpr (std::is_const_v<std::remove_pointer_t<S>>)
2477 flags |= QMetaType::IsConst;
2478 return flags;
2479 }
2480
2482 {
2483 if constexpr (std::is_default_constructible_v<S> && !QTypeInfo<S>::isValueInitializationBitwiseZero) {
2484 return [](const QMetaTypeInterface *, void *addr) { new (addr) S(); };
2485 } else {
2486 return nullptr;
2487 }
2488 }
2489
2491 {
2492 if constexpr (std::is_copy_constructible_v<S> && !std::is_trivially_copy_constructible_v<S>) {
2493 return [](const QMetaTypeInterface *, void *addr, const void *other) {
2494 if constexpr (qxp::is_detected_v<QMetaTypeCopyTraits::HasDeprecatedCopyConstructorTest, S>) {
2495#if !defined(QT_BOOTSTRAPPED)
2497#endif
2498 QT_IGNORE_DEPRECATIONS(new (addr) S(*reinterpret_cast<const S *>(other));)
2499 } else {
2500 new (addr) S(*reinterpret_cast<const S *>(other));
2501 }
2502 };
2503 } else {
2504 return nullptr;
2505 }
2506 }
2507
2509 {
2510 if constexpr (std::is_move_constructible_v<S> && !std::is_trivially_move_constructible_v<S>) {
2511 return [](const QMetaTypeInterface *, void *addr, void *other) {
2512 new (addr) S(std::move(*reinterpret_cast<S *>(other)));
2513 };
2514 } else {
2515 return nullptr;
2516 }
2517 }
2518
2520 {
2521 if constexpr (std::is_destructible_v<S> && !std::is_trivially_destructible_v<S>)
2522 return [](const QMetaTypeInterface *, void *addr) {
2523 reinterpret_cast<S *>(addr)->~S();
2524 };
2525 else
2526 return nullptr;
2527 }
2528
2530 {
2531 if constexpr (QMetaTypeId2<S>::Defined && !QMetaTypeId2<S>::IsBuiltIn) {
2532 return []() { QMetaTypeId2<S>::qt_metatype_id(); };
2533 } else {
2534 return nullptr;
2535 }
2536 }
2537
2538 static constexpr const char *getName()
2539 {
2540 if constexpr (bool(QMetaTypeId2<S>::IsBuiltIn)) {
2541 return QMetaTypeId2<S>::nameAsArray.data();
2542 } else {
2543 return name.data();
2544 }
2545 }
2546};
2547
2548template<typename T>
2550{
2551 // if the type ID for T is known at compile-time, then we can declare
2552 // the QMetaTypeInterface object const; otherwise, we declare it as
2553 // non-const and the .typeId is updated by QMetaType::idHelper().
2556
2557 static inline InterfaceType metaType = {
2558 /*.revision=*/ QMetaTypeInterface::CurrentRevision,
2559 /*.alignment=*/ alignof(T),
2560 /*.size=*/ sizeof(T),
2561 /*.flags=*/ QMetaTypeForType<T>::flags(),
2562 /*.typeId=*/ BuiltinMetaType<T>::value,
2563 /*.metaObjectFn=*/ MetaObjectForType<T>::metaObjectFunction,
2564 /*.name=*/ QMetaTypeForType<T>::getName(),
2565 /*.defaultCtr=*/ QMetaTypeForType<T>::getDefaultCtr(),
2566 /*.copyCtr=*/ QMetaTypeForType<T>::getCopyCtr(),
2567 /*.moveCtr=*/ QMetaTypeForType<T>::getMoveCtr(),
2568 /*.dtor=*/ QMetaTypeForType<T>::getDtor(),
2569 /*.equals=*/ QEqualityOperatorForType<T>::equals,
2570 /*.lessThan=*/ QLessThanOperatorForType<T>::lessThan,
2571 /*.debugStream=*/ QDebugStreamOperatorForType<T>::debugStream,
2572 /*.dataStreamOut=*/ QDataStreamOperatorForType<T>::dataStreamOut,
2573 /*.dataStreamIn=*/ QDataStreamOperatorForType<T>::dataStreamIn,
2574 /*.legacyRegisterOp=*/ QMetaTypeForType<T>::getLegacyRegister()
2575 };
2576};
2577template<typename T> struct QMetaTypeInterfaceWrapper<T &> {};
2578
2579
2580#if !defined(Q_OS_WIN) && defined(Q_CC_CLANG)
2581# pragma GCC visibility pop
2582#endif
2583
2584template<>
2586{
2587public:
2588 static constexpr QMetaTypeInterface metaType =
2589 {
2590 /*.revision=*/ 0,
2591 /*.alignment=*/ 0,
2592 /*.size=*/ 0,
2593 /*.flags=*/ 0,
2594 /*.typeId=*/ BuiltinMetaType<void>::value,
2595 /*.metaObjectFn=*/ nullptr,
2596 /*.name=*/ "void",
2597 /*.defaultCtr=*/ nullptr,
2598 /*.copyCtr=*/ nullptr,
2599 /*.moveCtr=*/ nullptr,
2600 /*.dtor=*/ nullptr,
2601 /*.equals=*/ nullptr,
2602 /*.lessThan=*/ nullptr,
2603 /*.debugStream=*/ nullptr,
2604 /*.dataStreamOut=*/ nullptr,
2605 /*.dataStreamIn=*/ nullptr,
2606 /*.legacyRegisterOp=*/ nullptr
2607 };
2608};
2609
2610/*
2611 MSVC instantiates extern templates
2612(https://developercommunity.visualstudio.com/t/c11-extern-templates-doesnt-work-for-class-templat/157868)
2613
2614 The INTEGRITY compiler apparently does too.
2615
2616 On Windows (with other compilers or whenever MSVC is fixed), we can't declare
2617 QMetaTypeInterfaceWrapper with __declspec(dllimport) because taking its
2618 address is not a core constant expression.
2619 */
2620#if !defined(QT_BOOTSTRAPPED) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY)
2621
2622#ifdef QT_NO_DATA_RELOCATION
2623# define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name)
2624 extern template class Q_CORE_EXPORT QMetaTypeForType<Name>;
2625#else
2626# define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name)
2627 extern template class Q_CORE_EXPORT QMetaTypeForType<Name>;
2628 extern template struct Q_CORE_EXPORT QMetaTypeInterfaceWrapper<Name>;
2629#endif
2630
2636#undef QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER
2637#endif
2638
2639template<typename T>
2641{
2643};
2644
2645#define Q_REMOVE_POINTER_LIKE_IMPL(Pointer) template
2646 <typename T> struct
2647 QRemovePointerLike<Pointer<T>> \
2648{
2649 using type = T; \
2650};
2651
2653#undef Q_REMOVE_POINTER_LIKE_IMPL
2654
2655template<typename T>
2657{
2658 // don't check the type is suitable here
2659 using Ty = typename MetatypeDecay<T>::type;
2660 return &QMetaTypeInterfaceWrapper<Ty>::metaType;
2661}
2662
2663// Relaxed vesion of the above, used by moc-generated code to create the
2664// metatype array without requiring types to be complete and allowing
2665// references. Unique is passed to is_complete and must be a different unique
2666// type; if it is void, this function is equal to qMetaTypeInterfaceForType()
2667// above.
2668template<typename Unique, typename T>
2670{
2671 using Ty = typename MetatypeDecay<T>::type;
2672 using Tz = typename QRemovePointerLike<Ty>::type;
2673
2674 if constexpr (std::is_void_v<Tz>) {
2675 // early out to avoid expanding the rest of the templates
2676 return &QMetaTypeInterfaceWrapper<Ty>::metaType;
2677 } else if constexpr (std::is_void_v<Unique>) {
2678 checkTypeIsSuitableForMetaType<Ty>();
2679 return &QMetaTypeInterfaceWrapper<Ty>::metaType;
2680 } else if constexpr (std::is_reference_v<Tz>) {
2681 return nullptr;
2682 } else if constexpr (!is_complete<Tz, Unique>::value) {
2683 return nullptr;
2684 } else {
2685 // don't check the type is suitable here
2686 return &QMetaTypeInterfaceWrapper<Ty>::metaType;
2687 }
2688}
2689
2690} // namespace QtPrivate
2691
2692template<typename T>
2693constexpr QMetaType QMetaType::fromType()
2694{
2695 QtPrivate::checkTypeIsSuitableForMetaType<T>();
2696 return QMetaType(QtPrivate::qMetaTypeInterfaceForType<T>());
2697}
2698
2699constexpr bool QMetaType::isValid(QT6_IMPL_NEW_OVERLOAD) const noexcept
2700{
2701 return d_ptr;
2702}
2703
2704bool QMetaType::isRegistered(QT6_IMPL_NEW_OVERLOAD) const noexcept
2705{
2706 return d_ptr && Q_LIKELY(d_ptr->typeId.loadRelaxed());
2707}
2708
2709constexpr qsizetype QMetaType::sizeOf() const
2710{
2711 return d_ptr ? d_ptr->size : 0;
2712}
2713
2714constexpr qsizetype QMetaType::alignOf() const
2715{
2716 return d_ptr ? d_ptr->alignment : 0;
2717}
2718
2719constexpr QMetaType::TypeFlags QMetaType::flags() const
2720{
2721 return d_ptr ? TypeFlags(d_ptr->flags) : TypeFlags{};
2722}
2723
2724constexpr const QMetaObject *QMetaType::metaObject() const
2725{
2726 return d_ptr && d_ptr->metaObjectFn ? d_ptr->metaObjectFn(d_ptr) : nullptr;
2727}
2728
2729constexpr const char *QMetaType::name() const
2730{
2731 return d_ptr ? d_ptr->name : nullptr;
2732}
2733
2734inline size_t qHash(QMetaType type, size_t seed = 0)
2735{
2736 // We cannot use d_ptr here since the same type in different DLLs
2737 // might result in different pointers!
2738 return qHash(type.id(), seed);
2739}
2740
2742
2743QT_DECL_METATYPE_EXTERN_TAGGED(QtMetaTypePrivate::QPairVariantInterfaceImpl,
2744 QPairVariantInterfaceImpl, Q_CORE_EXPORT)
2745
2746#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:879
void(* getFunc)(const void *const *p, void *)
Definition qmetatype.h:870
static void getFirstImpl(const void *const *pair, void *dataPtr)
Definition qmetatype.h:876
static constexpr QMetaTypeInterface::DtorFn getDtor()
Definition qmetatype.h:2519
static constexpr QMetaTypeInterface::CopyCtrFn getCopyCtr()
Definition qmetatype.h:2490
static constexpr QMetaTypeInterface::LegacyRegisterOp getLegacyRegister()
Definition qmetatype.h:2529
static constexpr unsigned flags()
Definition qmetatype.h:2443
static constexpr const char * getName()
Definition qmetatype.h:2538
static constexpr QMetaTypeInterface::DefaultCtrFn getDefaultCtr()
Definition qmetatype.h:2481
static constexpr decltype(typenameHelper< S >()) name
Definition qmetatype.h:2441
static constexpr QMetaTypeInterface::MoveCtrFn getMoveCtr()
Definition qmetatype.h:2508
static constexpr QMetaTypeInterface metaType
Definition qmetatype.h:2588
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:2430
Q_CORE_EXPORT void warnAboutDeprecatedCopy(const char *name)
constexpr auto typenameHelper()
Definition qmetatype.h:2260
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:1281
constexpr int qNormalizeType(const char *begin, const char *end, char *output)
Definition qmetatype.h:2244
constexpr bool IsUnsignedEnum
Definition qmetatype.h:1284
Q_CORE_EXPORT bool hasRegisteredConverterFunctionToPairVariantInterface(QMetaType m)
constexpr const QMetaTypeInterface * qTryMetaTypeInterfaceForType()
Definition qmetatype.h:2669
constexpr bool IsUnsignedEnum< T, true >
Definition qmetatype.h:1286
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:2656
char qt_getEnumMetaObject(const T &)
constexpr int qMetaTypeId()
Definition qmetatype.h:1397
#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(SINGLE_ARG_TEMPLATE)
Definition qmetatype.h:1687
#define QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F)
Definition qmetatype.h:97
int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName)
Definition qmetatype.h:1358
#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:1565
#define QT_FOR_EACH_STATIC_WIDGETS_CLASS(F)
Definition qmetatype.h:190
#define QT_DECL_METATYPE_EXTERN_TAGGED(TYPE, TAG, EXPORT)
Definition qmetatype.h:1367
#define QT_FOR_EACH_STATIC_CORE_POINTER(F)
Definition qmetatype.h:138
#define Q_DECLARE_METATYPE_IMPL(TYPE)
Definition qmetatype.h:1518
int qRegisterMetaType(const char *typeName)
Definition qmetatype.h:1386
#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:1593
#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:1375
#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)
Definition qmetatype.h:161
int qRegisterMetaType(QMetaType meta)
Definition qmetatype.h:1416
#define QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(C, F)
Definition qmetatype.h:855
constexpr int qRegisterMetaType()
Definition qmetatype.h:1410
#define QT_FOR_EACH_STATIC_CORE_CLASS(F)
Definition qmetatype.h:106
#define Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(TEMPLATENAME)
Definition qmetatype.h:1711
size_t qHash(QMetaType type, size_t seed=0)
\qhashold{QMetaType}
Definition qmetatype.h:2734
int qRegisterNormalizedMetaTypeImplementation(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName)
Definition qmetatype.h:1319
#define QMTI_MUTABLE
Definition qmetatype.h:265
#define Q_DECLARE_METATYPE(TYPE)
Definition qmetatype.h:1517
#define Q_DECLARE_SMART_POINTER_METATYPE(SMART_POINTER)
Definition qmetatype.h:1640
#define QT_FOR_EACH_STATIC_TYPE(F)
Definition qmetatype.h:224
static constexpr int qt_metatype_id()
Definition qmetatype.h:1262
void NameAsArrayType
Definition qmetatype.h:1249
static constexpr int qt_metatype_id()
Definition qmetatype.h:1251
QPairVariantInterfaceImpl operator()(const std::pair< T, U > &f) const
Definition qmetatype.h:910
static bool registerConverter()
Definition qmetatype.h:1187
static bool registerConverter()
Definition qmetatype.h:1202
static yes_type checkType(const QObject *)
static const T & declval()
static constexpr const QMetaObject * value()
Definition qmetatype.h:1018
static constexpr MetaObjectFn metaObjectFunction
Definition qmetatype.h:1020
const QMetaObject *(*)(const QMetaTypeInterface *) MetaObjectFn
Definition qmetatype.h:1019
QIterable< QMetaAssociation > operator()(const From &f) const
Definition qmetatype.h:1809
QIterable< QMetaAssociation > operator()(From &f) const
Definition qmetatype.h:1818
static void dataStreamIn(const QMetaTypeInterface *, QDataStream &ds, void *a)
Definition qmetatype.h:2404
static void dataStreamOut(const QMetaTypeInterface *, QDataStream &ds, const void *a)
Definition qmetatype.h:2402
static void debugStream(const QMetaTypeInterface *, QDebug &dbg, const void *a)
Definition qmetatype.h:2386
static constexpr QMetaTypeInterface::DebugStreamFn debugStream
Definition qmetatype.h:2379
static constexpr QMetaTypeInterface::EqualsFn equals
Definition qmetatype.h:2360
static constexpr QMetaTypeInterface::LessThanFn lessThan
Definition qmetatype.h:2373
static bool lessThan(const QMetaTypeInterface *, const void *a, const void *b)
Definition qmetatype.h:2366
static constexpr int qt_metatype_id()
Definition qmetatype.h:1272
static constexpr int qt_metatype_id()
Definition qmetatype.h:1268
static constexpr bool IsConstMetaTypeInterface
Definition qmetatype.h:2554
QIterable< QMetaSequence > operator()(const From &f) const
Definition qmetatype.h:1769
QIterable< QMetaSequence > operator()(From &f) const
Definition qmetatype.h:1778
QObject * operator()(const QWeakPointer< T > &p) const
Definition qmetatype.h:1311
QObject * operator()(const SmartPointer &p) const
Definition qmetatype.h:1297
constexpr int normalizeType(const char *begin, const char *end, bool adjustConst=true)
Definition qmetatype.h:2107
constexpr int normalizeTypeFromSignature(const char *begin, const char *end)
Definition qmetatype.h:2103
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