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