1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Copyright (C) 2018 Intel Corporation.
5** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
6** Contact: https://www.qt.io/licensing/
7**
8** This file is part of the QtCore module of the Qt Toolkit.
9**
10** $QT_BEGIN_LICENSE:LGPL$
11** Commercial License Usage
12** Licensees holding valid commercial Qt licenses may use this file in
13** accordance with the commercial license agreement provided with the
14** Software or, alternatively, in accordance with the terms contained in
15** a written agreement between you and The Qt Company. For licensing terms
16** and conditions see https://www.qt.io/terms-conditions. For further
17** information use the contact form at https://www.qt.io/contact-us.
18**
19** GNU Lesser General Public License Usage
20** Alternatively, this file may be used under the terms of the GNU Lesser
21** General Public License version 3 as published by the Free Software
22** Foundation and appearing in the file LICENSE.LGPL3 included in the
23** packaging of this file. Please review the following information to
24** ensure the GNU Lesser General Public License version 3 requirements
25** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
26**
27** GNU General Public License Usage
28** Alternatively, this file may be used under the terms of the GNU
29** General Public License version 2.0 or (at your option) the GNU General
30** Public license version 3 or any later version approved by the KDE Free
31** Qt Foundation. The licenses are as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
33** included in the packaging of this file. Please review the following
34** information to ensure the GNU General Public License requirements will
35** be met: https://www.gnu.org/licenses/gpl-2.0.html and
36** https://www.gnu.org/licenses/gpl-3.0.html.
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifndef QMETATYPE_H
43#define QMETATYPE_H
44
45#include <QtCore/qglobal.h>
46#include <QtCore/qatomic.h>
47#include <QtCore/qbytearray.h>
48#include <QtCore/qvarlengtharray.h>
49#include <QtCore/qrefcount.h>
50#include <QtCore/qdatastream.h>
51#include <QtCore/qiterable.h>
52#ifndef QT_NO_QOBJECT
53#include <QtCore/qobjectdefs.h>
54#endif
55
56#include <array>
57#include <new>
58#include <vector>
59#include <list>
60#include <map>
61#include <optional>
62#include <functional>
63
64#ifdef Bool
65#error qmetatype.h must be included before any header file that defines Bool
66#endif
67
68QT_BEGIN_NAMESPACE
69
70// from qcborcommon.h
71enum class QCborSimpleType : quint8;
72
73template <typename T>
74struct QMetaTypeId2;
75
76template <typename T>
77inline constexpr int qMetaTypeId();
78
79// F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, RealType)
80#define QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
81 F(Void, 43, void) \
82 F(Bool, 1, bool) \
83 F(Int, 2, int) \
84 F(UInt, 3, uint) \
85 F(LongLong, 4, qlonglong) \
86 F(ULongLong, 5, qulonglong) \
87 F(Double, 6, double) \
88 F(Long, 32, long) \
89 F(Short, 33, short) \
90 F(Char, 34, char) \
91 F(Char16, 56, char16_t) \
92 F(Char32, 57, char32_t) \
93 F(ULong, 35, ulong) \
94 F(UShort, 36, ushort) \
95 F(UChar, 37, uchar) \
96 F(Float, 38, float) \
97 F(SChar, 40, signed char) \
98 F(Nullptr, 51, std::nullptr_t) \
99 F(QCborSimpleType, 52, QCborSimpleType) \
100
101#define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\
102 F(VoidStar, 31, void*) \
103
104#if QT_CONFIG(easingcurve)
105#define QT_FOR_EACH_STATIC_EASINGCURVE(F)\
106 F(QEasingCurve, 29, QEasingCurve)
107#else
108#define QT_FOR_EACH_STATIC_EASINGCURVE(F)
109#endif
110
111#if QT_CONFIG(itemmodel)
112#define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)\
113 F(QModelIndex, 42, QModelIndex) \
114 F(QPersistentModelIndex, 50, QPersistentModelIndex)
115#else
116#define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
117#endif
118
119#if QT_CONFIG(regularexpression)
120# define QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F) \
121 F(QRegularExpression, 44, QRegularExpression)
122#else
123# define QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F)
124#endif
125
126#define QT_FOR_EACH_STATIC_CORE_CLASS(F)\
127 F(QChar, 7, QChar) \
128 F(QString, 10, QString) \
129 F(QByteArray, 12, QByteArray) \
130 F(QBitArray, 13, QBitArray) \
131 F(QDate, 14, QDate) \
132 F(QTime, 15, QTime) \
133 F(QDateTime, 16, QDateTime) \
134 F(QUrl, 17, QUrl) \
135 F(QLocale, 18, QLocale) \
136 F(QRect, 19, QRect) \
137 F(QRectF, 20, QRectF) \
138 F(QSize, 21, QSize) \
139 F(QSizeF, 22, QSizeF) \
140 F(QLine, 23, QLine) \
141 F(QLineF, 24, QLineF) \
142 F(QPoint, 25, QPoint) \
143 F(QPointF, 26, QPointF) \
144 QT_FOR_EACH_STATIC_EASINGCURVE(F) \
145 F(QUuid, 30, QUuid) \
146 F(QVariant, 41, QVariant) \
147 QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F) \
148 F(QJsonValue, 45, QJsonValue) \
149 F(QJsonObject, 46, QJsonObject) \
150 F(QJsonArray, 47, QJsonArray) \
151 F(QJsonDocument, 48, QJsonDocument) \
152 F(QCborValue, 53, QCborValue) \
153 F(QCborArray, 54, QCborArray) \
154 F(QCborMap, 55, QCborMap) \
155 QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
156
157#define QT_FOR_EACH_STATIC_CORE_POINTER(F)\
158 F(QObjectStar, 39, QObject*)
159
160#define QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)\
161 F(QVariantMap, 8, QVariantMap) \
162 F(QVariantList, 9, QVariantList) \
163 F(QVariantHash, 28, QVariantHash) \
164 F(QVariantPair, 58, QVariantPair) \
165 F(QByteArrayList, 49, QByteArrayList) \
166 F(QStringList, 11, QStringList) \
167
168#if QT_CONFIG(shortcut)
169#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)\
170 F(QKeySequence, 0x100b, QKeySequence)
171#else
172#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)
173#endif
174
175#define QT_FOR_EACH_STATIC_GUI_CLASS(F)\
176 F(QFont, 0x1000, QFont) \
177 F(QPixmap, 0x1001, QPixmap) \
178 F(QBrush, 0x1002, QBrush) \
179 F(QColor, 0x1003, QColor) \
180 F(QPalette, 0x1004, QPalette) \
181 F(QIcon, 0x1005, QIcon) \
182 F(QImage, 0x1006, QImage) \
183 F(QPolygon, 0x1007, QPolygon) \
184 F(QRegion, 0x1008, QRegion) \
185 F(QBitmap, 0x1009, QBitmap) \
186 F(QCursor, 0x100a, QCursor) \
187 QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F) \
188 F(QPen, 0x100c, QPen) \
189 F(QTextLength, 0x100d, QTextLength) \
190 F(QTextFormat, 0x100e, QTextFormat) \
191 F(QTransform, 0x1010, QTransform) \
192 F(QMatrix4x4, 0x1011, QMatrix4x4) \
193 F(QVector2D, 0x1012, QVector2D) \
194 F(QVector3D, 0x1013, QVector3D) \
195 F(QVector4D, 0x1014, QVector4D) \
196 F(QQuaternion, 0x1015, QQuaternion) \
197 F(QPolygonF, 0x1016, QPolygonF) \
198 F(QColorSpace, 0x1017, QColorSpace) \
199
200
201#define QT_FOR_EACH_STATIC_WIDGETS_CLASS(F)\
202 F(QSizePolicy, 0x2000, QSizePolicy) \
203
204// F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, AliasingType, "RealType")
205#define QT_FOR_EACH_STATIC_ALIAS_TYPE(F)\
206 F(ULong, -1, ulong, "unsigned long") \
207 F(UInt, -1, uint, "unsigned int") \
208 F(UShort, -1, ushort, "unsigned short") \
209 F(UChar, -1, uchar, "unsigned char") \
210 F(LongLong, -1, qlonglong, "long long") \
211 F(ULongLong, -1, qulonglong, "unsigned long long") \
212 F(SChar, -1, signed char, "qint8") \
213 F(UChar, -1, uchar, "quint8") \
214 F(Short, -1, short, "qint16") \
215 F(UShort, -1, ushort, "quint16") \
216 F(Int, -1, int, "qint32") \
217 F(UInt, -1, uint, "quint32") \
218 F(LongLong, -1, qlonglong, "qint64") \
219 F(ULongLong, -1, qulonglong, "quint64") \
220 F(QVariantList, -1, QVariantList, "QList<QVariant>") \
221 F(QVariantMap, -1, QVariantMap, "QMap<QString,QVariant>") \
222 F(QVariantHash, -1, QVariantHash, "QHash<QString,QVariant>") \
223 F(QVariantPair, -1, QVariantPair, "QPair<QVariant,QVariant>") \
224 F(QByteArrayList, -1, QByteArrayList, "QList<QByteArray>") \
225 F(QStringList, -1, QStringList, "QList<QString>") \
226
227#define QT_FOR_EACH_STATIC_TYPE(F)\
228 QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
229 QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\
230 QT_FOR_EACH_STATIC_CORE_CLASS(F)\
231 QT_FOR_EACH_STATIC_CORE_POINTER(F)\
232 QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)\
233 QT_FOR_EACH_STATIC_GUI_CLASS(F)\
234 QT_FOR_EACH_STATIC_WIDGETS_CLASS(F)\
235
236#define QT_DEFINE_METATYPE_ID(TypeName, Id, Name) \
237 TypeName = Id,
238
239#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(F) \
240 F(QList) \
241 F(QQueue) \
242 F(QStack) \
243 F(QSet) \
244 /*end*/
245
246#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(F) \
247 F(QHash, class) \
248 F(QMap, class)
249
250#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(F) \
251 F(QSharedPointer) \
252 F(QWeakPointer) \
253 F(QPointer)
254
255class QDataStream;
256struct QMetaObject;
257
258namespace QtPrivate
259{
260
261class QMetaTypeInterface;
262
263/*!
264 This template is used for implicit conversion from type From to type To.
265 \internal
266*/
267template<typename From, typename To>
268To convertImplicit(const From& from)
269{
270 return from;
271}
272
273 template<typename T, bool>
274 struct SequentialValueTypeIsMetaType;
275 template<typename T, bool>
276 struct AssociativeValueTypeIsMetaType;
277 template<typename T, bool>
278 struct IsMetaTypePair;
279 template<typename, typename>
280 struct MetaTypeSmartPointerHelper;
281
282 template<typename T>
283 struct IsQFlags : std::false_type {};
284
285 template<typename Enum>
286 struct IsQFlags<QFlags<Enum>> : std::true_type {};
287
288 template<typename T>
289 struct IsEnumOrFlags : std::disjunction<std::is_enum<T>, IsQFlags<T>> {};
290} // namespace QtPrivate
291
292class Q_CORE_EXPORT QMetaType {
293public:
294#ifndef Q_CLANG_QDOC
295 // The code that actually gets compiled.
296 enum Type {
297 // these are merged with QVariant
298 QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID)
299
300 FirstCoreType = Bool,
301 LastCoreType = QVariantPair,
302 FirstGuiType = QFont,
303 LastGuiType = QColorSpace,
304 FirstWidgetsType = QSizePolicy,
305 LastWidgetsType = QSizePolicy,
306 HighestInternalId = LastWidgetsType,
307
308 QReal = sizeof(qreal) == sizeof(double) ? Double : Float,
309
310 UnknownType = 0,
311 User = 65536
312 };
313#else
314 // If we are using QDoc it fakes the Type enum looks like this.
315 enum Type {
316 UnknownType = 0, Bool = 1, Int = 2, UInt = 3, LongLong = 4, ULongLong = 5,
317 Double = 6, Long = 32, Short = 33, Char = 34, ULong = 35, UShort = 36,
318 UChar = 37, Float = 38,
319 VoidStar = 31,
320 QChar = 7, QString = 10, QStringList = 11, QByteArray = 12,
321 QBitArray = 13, QDate = 14, QTime = 15, QDateTime = 16, QUrl = 17,
322 QLocale = 18, QRect = 19, QRectF = 20, QSize = 21, QSizeF = 22,
323 QLine = 23, QLineF = 24, QPoint = 25, QPointF = 26,
324 QEasingCurve = 29, QUuid = 30, QVariant = 41, QModelIndex = 42,
325 QPersistentModelIndex = 50, QRegularExpression = 44,
326 QJsonValue = 45, QJsonObject = 46, QJsonArray = 47, QJsonDocument = 48,
327 QByteArrayList = 49, QObjectStar = 39, SChar = 40,
328 Void = 43,
329 Nullptr = 51,
330 QVariantMap = 8, QVariantList = 9, QVariantHash = 28,
331 QCborSimpleType = 52, QCborValue = 53, QCborArray = 54, QCborMap = 55,
332 Char16 = 56, Char32 = 57,
333
334 // Gui types
335 QFont = 0x1000, QPixmap = 0x1001, QBrush = 0x1002, QColor = 0x1003, QPalette = 0x1004,
336 QIcon = 0x1005, QImage = 0x1006, QPolygon = 0x1007, QRegion = 0x1008, QBitmap = 0x1009,
337 QCursor = 0x100a, QKeySequence = 0x100b, QPen = 0x100c, QTextLength = 0x100d, QTextFormat = 0x100e,
338 QTransform = 0x1010, QMatrix4x4 = 0x1011, QVector2D = 0x1012,
339 QVector3D = 0x1013, QVector4D = 0x1014, QQuaternion = 0x1015, QPolygonF = 0x1016, QColorSpace = 0x1017,
340
341 // Widget types
342 QSizePolicy = 0x2000,
343 LastCoreType = Char32,
344 LastGuiType = QColorSpace,
345 User = 65536
346 };
347#endif
348
349 enum TypeFlag {
350 NeedsConstruction = 0x1,
351 NeedsDestruction = 0x2,
352 RelocatableType = 0x4,
353#if QT_DEPRECATED_SINCE(6, 0)
354 MovableType Q_DECL_ENUMERATOR_DEPRECATED_X("Use RelocatableType instead.") = RelocatableType,
355#endif
356 PointerToQObject = 0x8,
357 IsEnumeration = 0x10,
358 SharedPointerToQObject = 0x20,
359 WeakPointerToQObject = 0x40,
360 TrackingPointerToQObject = 0x80,
361 IsUnsignedEnumeration = 0x100,
362 IsGadget = 0x200,
363 PointerToGadget = 0x400,
364 IsPointer = 0x800,
365 };
366 Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
367
368 static void registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, QMetaType type);
369
370#if QT_DEPRECATED_SINCE(6, 0)
371 QT_DEPRECATED_VERSION_6_0
372 static int type(const char *typeName)
373 { return QMetaType::fromName(typeName).id(); }
374 QT_DEPRECATED_VERSION_6_0
375 static int type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName)
376 { return QMetaType::fromName(typeName).id(); }
377 QT_DEPRECATED_VERSION_6_0
378 static const char *typeName(int type)
379 { return QMetaType(type).name(); }
380 QT_DEPRECATED_VERSION_6_0
381 static int sizeOf(int type)
382 { return QMetaType(type).sizeOf(); }
383 QT_DEPRECATED_VERSION_6_0
384 static TypeFlags typeFlags(int type)
385 { return QMetaType(type).flags(); }
386 QT_DEPRECATED_VERSION_6_0
387 static const QMetaObject *metaObjectForType(int type)
388 { return QMetaType(type).metaObject(); }
389 QT_DEPRECATED_VERSION_6_0
390 static void *create(int type, const void *copy = nullptr)
391 { return QMetaType(type).create(copy); }
392 QT_DEPRECATED_VERSION_6_0
393 static void destroy(int type, void *data)
394 { return QMetaType(type).destroy(data); }
395 QT_DEPRECATED_VERSION_6_0
396 static void *construct(int type, void *where, const void *copy)
397 { return QMetaType(type).construct(where, copy); }
398 QT_DEPRECATED_VERSION_6_0
399 static void destruct(int type, void *where)
400 { return QMetaType(type).destruct(where); }
401#endif
402 static bool isRegistered(int type);
403
404 explicit QMetaType(int type);
405 explicit constexpr QMetaType(const QtPrivate::QMetaTypeInterface *d) : d_ptr(d) {}
406 constexpr QMetaType() = default;
407
408 bool isValid() const;
409 bool isRegistered() const;
410 int id() const;
411 constexpr qsizetype sizeOf() const;
412 constexpr qsizetype alignOf() const;
413 constexpr TypeFlags flags() const;
414 constexpr const QMetaObject *metaObject() const;
415 constexpr const char *name() const;
416
417 void *create(const void *copy = nullptr) const;
418 void destroy(void *data) const;
419 void *construct(void *where, const void *copy = nullptr) const;
420 void destruct(void *data) const;
421 std::optional<int> compare(const void *lhs, const void *rhs) const;
422 bool equals(const void *lhs, const void *rhs) const;
423
424 bool isEqualityComparable() const;
425 bool isOrdered() const;
426
427#ifndef QT_NO_DATASTREAM
428 bool save(QDataStream &stream, const void *data) const;
429 bool load(QDataStream &stream, void *data) const;
430
431#if QT_DEPRECATED_SINCE(6, 0)
432 QT_DEPRECATED_VERSION_6_0
433 static bool save(QDataStream &stream, int type, const void *data)
434 { return QMetaType(type).save(stream, data); }
435 QT_DEPRECATED_VERSION_6_0
436 static bool load(QDataStream &stream, int type, void *data)
437 { return QMetaType(type).load(stream, data); }
438#endif
439#endif
440
441 template<typename T>
442 constexpr static QMetaType fromType();
443 static QMetaType fromName(QByteArrayView name);
444
445 friend bool operator==(QMetaType a, QMetaType b) { return a.d_ptr == b.d_ptr || a.id() == b.id(); }
446 friend bool operator!=(QMetaType a, QMetaType b) { return !(a == b); }
447
448public:
449
450#ifndef QT_NO_DEBUG_STREAM
451 bool debugStream(QDebug& dbg, const void *rhs);
452 bool hasRegisteredDebugStreamOperator() const;
453
454#if QT_DEPRECATED_SINCE(6, 0)
455 QT_DEPRECATED_VERSION_6_0
456 static bool debugStream(QDebug& dbg, const void *rhs, int typeId)
457 { return QMetaType(typeId).debugStream(dbg, rhs); }
458 template<typename T>
459 QT_DEPRECATED_VERSION_6_0
460 static bool hasRegisteredDebugStreamOperator()
461 { return QMetaType::fromType<T>().hasRegisteredDebugStreamOperator(); }
462 QT_DEPRECATED_VERSION_6_0
463 static bool hasRegisteredDebugStreamOperator(int typeId)
464 { return QMetaType(typeId).hasRegisteredDebugStreamOperator(); }
465#endif
466#endif
467
468 // type erased converter function
469 using ConverterFunction = std::function<bool(const void *src, void *target)>;
470
471 // type erased mutable view, primarily for containers
472 using MutableViewFunction = std::function<bool(void *src, void *target)>;
473
474 // implicit conversion supported like double -> float
475 template<typename From, typename To>
476 static bool registerConverter()
477 {
478 return registerConverter<From, To>(QtPrivate::convertImplicit<From, To>);
479 }
480
481#ifdef Q_CLANG_QDOC
482 template<typename MemberFunction, int>
483 static bool registerConverter(MemberFunction function);
484 template<typename MemberFunctionOk, char>
485 static bool registerConverter(MemberFunctionOk function);
486 template<typename UnaryFunction>
487 static bool registerConverter(UnaryFunction function);
488
489 template<typename MemberFunction, int>
490 static bool registerMutableView(MemberFunction function);
491 template<typename MemberFunctionOk, char>
492 static bool registerMutableView(MemberFunctionOk function);
493 template<typename UnaryFunction>
494 static bool registerMutableView(UnaryFunction function);
495#else
496 // member function as in "QString QFont::toString() const"
497 template<typename From, typename To>
498 static bool registerConverter(To(From::*function)() const)
499 {
500 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
501 "QMetaType::registerConverter: At least one of the types must be a custom type.");
502
503 const QMetaType fromType = QMetaType::fromType<From>();
504 const QMetaType toType = QMetaType::fromType<To>();
505 auto converter = [function](const void *from, void *to) -> bool {
506 const From *f = static_cast<const From *>(from);
507 To *t = static_cast<To *>(to);
508 *t = (f->*function)();
509 return true;
510 };
511 return registerConverterFunction(converter, fromType, toType);
512 }
513
514 // member function
515 template<typename From, typename To>
516 static bool registerMutableView(To(From::*function)())
517 {
518 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
519 "QMetaType::registerMutableView: At least one of the types must be a custom type.");
520
521 const QMetaType fromType = QMetaType::fromType<From>();
522 const QMetaType toType = QMetaType::fromType<To>();
523 auto view = [function](void *from, void *to) -> bool {
524 From *f = static_cast<From *>(from);
525 To *t = static_cast<To *>(to);
526 *t = (f->*function)();
527 return true;
528 };
529 return registerMutableViewFunction(view, fromType, toType);
530 }
531
532 // member function as in "double QString::toDouble(bool *ok = nullptr) const"
533 template<typename From, typename To>
534 static bool registerConverter(To(From::*function)(bool*) const)
535 {
536 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
537 "QMetaType::registerConverter: At least one of the types must be a custom type.");
538
539 const QMetaType fromType = QMetaType::fromType<From>();
540 const QMetaType toType = QMetaType::fromType<To>();
541 auto converter = [function](const void *from, void *to) -> bool {
542 const From *f = static_cast<const From *>(from);
543 To *t = static_cast<To *>(to);
544 bool result = true;
545 *t = (f->*function)(&result);
546 if (!result)
547 *t = To();
548 return result;
549 };
550 return registerConverterFunction(converter, fromType, toType);
551 }
552
553 // functor or function pointer
554 template<typename From, typename To, typename UnaryFunction>
555 static bool registerConverter(UnaryFunction function)
556 {
557 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
558 "QMetaType::registerConverter: At least one of the types must be a custom type.");
559
560 const QMetaType fromType = QMetaType::fromType<From>();
561 const QMetaType toType = QMetaType::fromType<To>();
562 auto converter = [function](const void *from, void *to) -> bool {
563 const From *f = static_cast<const From *>(from);
564 To *t = static_cast<To *>(to);
565 *t = function(*f);
566 return true;
567 };
568 return registerConverterFunction(converter, fromType, toType);
569 }
570
571 // functor or function pointer
572 template<typename From, typename To, typename UnaryFunction>
573 static bool registerMutableView(UnaryFunction function)
574 {
575 static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
576 "QMetaType::registerMutableView: 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 view = [function](void *from, void *to) -> bool {
581 From *f = static_cast<From *>(from);
582 To *t = static_cast<To *>(to);
583 *t = function(*f);
584 return true;
585 };
586 return registerMutableViewFunction(view, fromType, toType);
587 }
588#endif
589
590 static bool convert(QMetaType fromType, const void *from, QMetaType toType, void *to);
591 static bool canConvert(QMetaType fromType, QMetaType toType);
592
593 static bool view(QMetaType fromType, void *from, QMetaType toType, void *to);
594 static bool canView(QMetaType fromType, QMetaType toType);
595#if QT_DEPRECATED_SINCE(6, 0)
596 QT_DEPRECATED_VERSION_6_0
597 static bool convert(const void *from, int fromTypeId, void *to, int toTypeId)
598 { return convert(QMetaType(fromTypeId), from, QMetaType(toTypeId), to); }
599 QT_DEPRECATED_VERSION_6_0
600 static bool compare(const void *lhs, const void *rhs, int typeId, int *result)
601 {
602 QMetaType t(typeId);
603 auto c = t.compare(lhs, rhs);
604 if (!c) {
605 *result = 0;
606 return false;
607 }
608 *result = *c;
609 return true;
610 }
611 QT_DEPRECATED_VERSION_6_0
612 static bool equals(const void *lhs, const void *rhs, int typeId, int *result)
613 {
614 QMetaType t(typeId);
615 if (!t.isEqualityComparable())
616 return false;
617 *result = t.equals(lhs, rhs) ? 0 : -1;
618 return true;
619 }
620#endif
621
622 template<typename From, typename To>
623 static bool hasRegisteredConverterFunction()
624 {
625 return hasRegisteredConverterFunction(
626 QMetaType::fromType<From>(), QMetaType::fromType<To>());
627 }
628
629 static bool hasRegisteredConverterFunction(QMetaType fromType, QMetaType toType);
630
631 template<typename From, typename To>
632 static bool hasRegisteredMutableViewFunction()
633 {
634 return hasRegisteredMutableViewFunction(
635 QMetaType::fromType<From>(), QMetaType::fromType<To>());
636 }
637
638 static bool hasRegisteredMutableViewFunction(QMetaType fromType, QMetaType toType);
639
640#ifndef Q_CLANG_QDOC
641 template<typename, bool> friend struct QtPrivate::SequentialValueTypeIsMetaType;
642 template<typename, bool> friend struct QtPrivate::AssociativeValueTypeIsMetaType;
643 template<typename, bool> friend struct QtPrivate::IsMetaTypePair;
644 template<typename, typename> friend struct QtPrivate::MetaTypeSmartPointerHelper;
645#endif
646 static bool registerConverterFunction(const ConverterFunction &f, QMetaType from, QMetaType to);
647 static void unregisterConverterFunction(QMetaType from, QMetaType to);
648
649 static bool registerMutableViewFunction(const MutableViewFunction &f, QMetaType from, QMetaType to);
650 static void unregisterMutableViewFunction(QMetaType from, QMetaType to);
651
652 static void unregisterMetaType(QMetaType type);
653 const QtPrivate::QMetaTypeInterface *iface() { return d_ptr; }
654
655private:
656 friend class QVariant;
657 const QtPrivate::QMetaTypeInterface *d_ptr = nullptr;
658};
659
660#undef QT_DEFINE_METATYPE_ID
661
662Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags)
663
664#define QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(C, F) \
665 } \
666 Q_DECLARE_TYPEINFO(QtMetaTypePrivate:: C, (F)); \
667 namespace QtMetaTypePrivate {
668
669
670namespace QtMetaTypePrivate {
671
672class QPairVariantInterfaceImpl
673{
674public:
675 const void *_pair;
676 QMetaType _metaType_first;
677 QMetaType _metaType_second;
678
679 typedef void (*getFunc)(const void * const *p, void *);
680
681 getFunc _getFirst;
682 getFunc _getSecond;
683
684 template<class T>
685 static void getFirstImpl(const void * const *pair, void *dataPtr)
686 { *static_cast<typename T::first_type *>(dataPtr) = static_cast<const T*>(*pair)->first; }
687 template<class T>
688 static void getSecondImpl(const void * const *pair, void *dataPtr)
689 { *static_cast<typename T::second_type *>(dataPtr) = static_cast<const T*>(*pair)->second; }
690
691public:
692 template<class T> QPairVariantInterfaceImpl(const T*p)
693 : _pair(p)
694 , _metaType_first(QMetaType::fromType<typename T::first_type>())
695 , _metaType_second(QMetaType::fromType<typename T::second_type>())
696 , _getFirst(getFirstImpl<T>)
697 , _getSecond(getSecondImpl<T>)
698 {
699 }
700
701 QPairVariantInterfaceImpl()
702 : _pair(nullptr)
703 , _getFirst(nullptr)
704 , _getSecond(nullptr)
705 {
706 }
707
708 inline void first(void *dataPtr) const { _getFirst(&_pair, dataPtr); }
709 inline void second(void *dataPtr) const { _getSecond(&_pair, dataPtr); }
710};
711QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QPairVariantInterfaceImpl, Q_MOVABLE_TYPE)
712
713template<typename From>
714struct QPairVariantInterfaceConvertFunctor;
715
716template<typename T, typename U>
717struct QPairVariantInterfaceConvertFunctor<std::pair<T, U> >
718{
719 QPairVariantInterfaceImpl operator()(const std::pair<T, U>& f) const
720 {
721 return QPairVariantInterfaceImpl(&f);
722 }
723};
724
725}
726
727class QObject;
728
729#define QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER(Name) \
730 template <class T> class Name; \
731
732QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER)
733
734namespace QtPrivate
735{
736 template<typename T>
737 struct IsPointerToTypeDerivedFromQObject
738 {
739 enum { Value = false };
740 };
741
742 // Specialize to avoid sizeof(void) warning
743 template<>
744 struct IsPointerToTypeDerivedFromQObject<void*>
745 {
746 enum { Value = false };
747 };
748 template<>
749 struct IsPointerToTypeDerivedFromQObject<const void*>
750 {
751 enum { Value = false };
752 };
753 template<>
754 struct IsPointerToTypeDerivedFromQObject<QObject*>
755 {
756 enum { Value = true };
757 };
758
759 template<typename T>
760 struct IsPointerToTypeDerivedFromQObject<T*>
761 {
762 typedef qint8 yes_type;
763 typedef qint64 no_type;
764
765#ifndef QT_NO_QOBJECT
766 static yes_type checkType(QObject* );
767#endif
768 static no_type checkType(...);
769 static_assert(sizeof(T), "Type argument of Q_PROPERTY or Q_DECLARE_METATYPE(T*) must be fully defined");
770 enum { Value = sizeof(checkType(static_cast<T*>(nullptr))) == sizeof(yes_type) };
771 };
772
773 template<typename T, typename Enable = void>
774 struct IsGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; };
775
776 template<typename T>
777 struct IsGadgetHelper<T, typename T::QtGadgetHelper>
778 {
779 template <typename X>
780 static char checkType(void (X::*)());
781 static void *checkType(void (T::*)());
782 enum {
783 IsRealGadget = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *),
784 IsGadgetOrDerivedFrom = true
785 };
786 };
787
788 template<typename T, typename Enable = void>
789 struct IsPointerToGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; };
790
791 template<typename T>
792 struct IsPointerToGadgetHelper<T*, typename T::QtGadgetHelper>
793 {
794 using BaseType = T;
795 template <typename X>
796 static char checkType(void (X::*)());
797 static void *checkType(void (T::*)());
798 enum {
799 IsRealGadget = !IsPointerToTypeDerivedFromQObject<T*>::Value && sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *),
800 IsGadgetOrDerivedFrom = !IsPointerToTypeDerivedFromQObject<T*>::Value
801 };
802 };
803
804
805 template<typename T> char qt_getEnumMetaObject(const T&);
806
807 template<typename T>
808 struct IsQEnumHelper {
809 static const T &declval();
810 // If the type was declared with Q_ENUM, the friend qt_getEnumMetaObject() declared in the
811 // Q_ENUM macro will be chosen by ADL, and the return type will be QMetaObject*.
812 // Otherwise the chosen overload will be the catch all template function
813 // qt_getEnumMetaObject(T) which returns 'char'
814 enum { Value = sizeof(qt_getEnumMetaObject(declval())) == sizeof(QMetaObject*) };
815 };
816 template<> struct IsQEnumHelper<void> { enum { Value = false }; };
817
818 template<typename T, typename Enable = void>
819 struct MetaObjectForType
820 {
821 static constexpr inline const QMetaObject *value() { return nullptr; }
822 };
823#ifndef QT_NO_QOBJECT
824 template<>
825 struct MetaObjectForType<void>
826 {
827 static constexpr inline const QMetaObject *value() { return nullptr; }
828 };
829 template<typename T>
830 struct MetaObjectForType<T*, typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value>::type>
831 {
832 static constexpr inline const QMetaObject *value() { return &T::staticMetaObject; }
833 };
834 template<typename T>
835 struct MetaObjectForType<T, typename std::enable_if<IsGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
836 {
837 static constexpr inline const QMetaObject *value() { return &T::staticMetaObject; }
838 };
839 template<typename T>
840 struct MetaObjectForType<T, typename std::enable_if<IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
841 {
842 static constexpr inline const QMetaObject *value()
843 {
844 return &IsPointerToGadgetHelper<T>::BaseType::staticMetaObject;
845 }
846 };
847 template<typename T>
848 struct MetaObjectForType<T, typename std::enable_if<IsQEnumHelper<T>::Value>::type >
849 {
850 static constexpr inline const QMetaObject *value() { return qt_getEnumMetaObject(T()); }
851 };
852#endif
853
854 template<typename T>
855 struct IsSharedPointerToTypeDerivedFromQObject
856 {
857 enum { Value = false };
858 };
859
860 template<typename T>
861 struct IsSharedPointerToTypeDerivedFromQObject<QSharedPointer<T> > : IsPointerToTypeDerivedFromQObject<T*>
862 {
863 };
864
865 template<typename T>
866 struct IsWeakPointerToTypeDerivedFromQObject
867 {
868 enum { Value = false };
869 };
870
871 template<typename T>
872 struct IsWeakPointerToTypeDerivedFromQObject<QWeakPointer<T> > : IsPointerToTypeDerivedFromQObject<T*>
873 {
874 };
875
876 template<typename T>
877 struct IsTrackingPointerToTypeDerivedFromQObject
878 {
879 enum { Value = false };
880 };
881
882 template<typename T>
883 struct IsTrackingPointerToTypeDerivedFromQObject<QPointer<T> >
884 {
885 enum { Value = true };
886 };
887
888 template<typename T>
889 struct IsSequentialContainer
890 {
891 enum { Value = false };
892 };
893
894 template<typename T>
895 struct IsAssociativeContainer
896 {
897 enum { Value = false };
898 };
899
900 template<typename T, bool = QtPrivate::IsSequentialContainer<T>::Value>
901 struct SequentialContainerTransformationHelper
902 {
903 static bool registerConverter()
904 {
905 return false;
906 }
907
908 static bool registerMutableView()
909 {
910 return false;
911 }
912 };
913
914 template<typename T, bool = QMetaTypeId2<typename T::value_type>::Defined>
915 struct SequentialValueTypeIsMetaType
916 {
917 static bool registerConverter()
918 {
919 return false;
920 }
921
922 static bool registerMutableView()
923 {
924 return false;
925 }
926 };
927
928 template<typename T>
929 struct SequentialContainerTransformationHelper<T, true> : SequentialValueTypeIsMetaType<T>
930 {
931 };
932
933 template<typename T, bool = QtPrivate::IsAssociativeContainer<T>::Value>
934 struct AssociativeContainerTransformationHelper
935 {
936 static bool registerConverter()
937 {
938 return false;
939 }
940
941 static bool registerMutableView()
942 {
943 return false;
944 }
945 };
946
947 template<typename T, bool = QMetaTypeId2<typename T::key_type>::Defined>
948 struct AssociativeKeyTypeIsMetaType
949 {
950 static bool registerConverter()
951 {
952 return false;
953 }
954
955 static bool registerMutableView()
956 {
957 return false;
958 }
959 };
960
961 template<typename T, bool = QMetaTypeId2<typename T::mapped_type>::Defined>
962 struct AssociativeMappedTypeIsMetaType
963 {
964 static bool registerConverter()
965 {
966 return false;
967 }
968
969 static bool registerMutableView()
970 {
971 return false;
972 }
973 };
974
975 template<typename T>
976 struct AssociativeContainerTransformationHelper<T, true> : AssociativeKeyTypeIsMetaType<T>
977 {
978 };
979
980 template<typename T, bool = QMetaTypeId2<typename T::first_type>::Defined
981 && QMetaTypeId2<typename T::second_type>::Defined>
982 struct IsMetaTypePair
983 {
984 static bool registerConverter()
985 {
986 return false;
987 }
988 };
989
990 template<typename T>
991 struct IsMetaTypePair<T, true>
992 {
993 inline static bool registerConverter();
994 };
995
996 template<typename T>
997 struct IsPair
998 {
999 static bool registerConverter()
1000 {
1001 return false;
1002 }
1003 };
1004 template<typename T, typename U>
1005 struct IsPair<std::pair<T, U> > : IsMetaTypePair<std::pair<T, U> > {};
1006
1007 template<typename T>
1008 struct MetaTypePairHelper : IsPair<T> {};
1009
1010 template<typename T, typename = void>
1011 struct MetaTypeSmartPointerHelper
1012 {
1013 static bool registerConverter() { return false; }
1014 };
1015
1016 Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type);
1017} // namespace QtPrivate
1018
1019template <typename T, int =
1020 QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject :
1021 QtPrivate::IsGadgetHelper<T>::IsRealGadget ? QMetaType::IsGadget :
1022 QtPrivate::IsPointerToGadgetHelper<T>::IsRealGadget ? QMetaType::PointerToGadget :
1023 QtPrivate::IsQEnumHelper<T>::Value ? QMetaType::IsEnumeration : 0>
1024struct QMetaTypeIdQObject
1025{
1026 enum {
1027 Defined = 0
1028 };
1029};
1030
1031template <typename T>
1032struct QMetaTypeId : public QMetaTypeIdQObject<T>
1033{
1034};
1035
1036template <typename T>
1037struct QMetaTypeId2
1038{
1039 using NameAsArrayType = void;
1040 enum { Defined = QMetaTypeId<T>::Defined, IsBuiltIn=false };
1041 static inline constexpr int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }
1042};
1043
1044template <typename T>
1045struct QMetaTypeId2<const T&> : QMetaTypeId2<T> {};
1046
1047template <typename T>
1048struct QMetaTypeId2<T&> { enum {Defined = false }; };
1049
1050namespace QtPrivate {
1051 template <typename T, bool Defined = QMetaTypeId2<T>::Defined>
1052 struct QMetaTypeIdHelper {
1053 static inline constexpr int qt_metatype_id()
1054 { return QMetaTypeId2<T>::qt_metatype_id(); }
1055 };
1056 template <typename T> struct QMetaTypeIdHelper<T, false> {
1057 static inline constexpr int qt_metatype_id()
1058 { return -1; }
1059 };
1060
1061 // Function pointers don't derive from QObject
1062 template <typename Result, typename... Args>
1063 struct IsPointerToTypeDerivedFromQObject<Result(*)(Args...)> { enum { Value = false }; };
1064
1065 template<typename T, bool = std::is_enum<T>::value>
1066 constexpr bool IsUnsignedEnum = false;
1067 template<typename T>
1068 constexpr bool IsUnsignedEnum<T, true> = !std::is_signed_v<std::underlying_type_t<T>>;
1069
1070 template<typename T>
1071 struct QMetaTypeTypeFlags
1072 {
1073 enum { Flags = (QTypeInfo<T>::isRelocatable ? QMetaType::RelocatableType : 0)
1074 | (QTypeInfo<T>::isComplex ? QMetaType::NeedsConstruction : 0)
1075 | (QTypeInfo<T>::isComplex ? QMetaType::NeedsDestruction : 0)
1076 | (IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject : 0)
1077 | (IsSharedPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::SharedPointerToQObject : 0)
1078 | (IsWeakPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::WeakPointerToQObject : 0)
1079 | (IsTrackingPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::TrackingPointerToQObject : 0)
1080 | (IsEnumOrFlags<T>::value ? QMetaType::IsEnumeration : 0)
1081 | (IsGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::IsGadget : 0)
1082 | (IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::PointerToGadget : 0)
1083 | (QTypeInfo<T>::isPointer ? QMetaType::IsPointer : 0)
1084 | (IsUnsignedEnum<T> ? QMetaType::IsUnsignedEnumeration : 0)
1085 };
1086 };
1087
1088 template<typename T, bool defined>
1089 struct MetaTypeDefinedHelper
1090 {
1091 enum DefinedType { Defined = defined };
1092 };
1093
1094 template<typename SmartPointer>
1095 struct QSmartPointerConvertFunctor
1096 {
1097 QObject* operator()(const SmartPointer &p) const
1098 {
1099 return p.operator->();
1100 }
1101 };
1102
1103 // hack to delay name lookup to instantiation time by making
1104 // EnableInternalData a dependent name:
1105 template <typename T>
1106 struct EnableInternalDataWrap;
1107
1108 template<typename T>
1109 struct QSmartPointerConvertFunctor<QWeakPointer<T> >
1110 {
1111 QObject* operator()(const QWeakPointer<T> &p) const
1112 {
1113 return QtPrivate::EnableInternalDataWrap<T>::internalData(p);
1114 }
1115 };
1116}
1117
1118template <typename T>
1119int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName)
1120{
1121#ifndef QT_NO_QOBJECT
1122 Q_ASSERT_X(normalizedTypeName == QMetaObject::normalizedType(normalizedTypeName.constData()), "qRegisterNormalizedMetaType", "qRegisterNormalizedMetaType was called with a not normalized type name, please call qRegisterMetaType instead.");
1123#endif
1124
1125 const QMetaType metaType = QMetaType::fromType<T>();
1126 const int id = metaType.id();
1127
1128 if (id > 0) {
1129 QMetaType::registerNormalizedTypedef(normalizedTypeName, metaType);
1130 QtPrivate::SequentialContainerTransformationHelper<T>::registerConverter();
1131 QtPrivate::SequentialContainerTransformationHelper<T>::registerMutableView();
1132 QtPrivate::AssociativeContainerTransformationHelper<T>::registerConverter();
1133 QtPrivate::AssociativeContainerTransformationHelper<T>::registerMutableView();
1134 QtPrivate::MetaTypePairHelper<T>::registerConverter();
1135 QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter();
1136 }
1137
1138 return id;
1139}
1140
1141template <typename T>
1142int qRegisterMetaType(const char *typeName)
1143{
1144#ifdef QT_NO_QOBJECT
1145 QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = typeName;
1146#else
1147 QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
1148#endif
1149 return qRegisterNormalizedMetaType<T>(normalizedTypeName);
1150}
1151
1152template <typename T>
1153inline constexpr int qMetaTypeId()
1154{
1155 if constexpr (bool(QMetaTypeId2<T>::IsBuiltIn)) {
1156 return QMetaTypeId2<T>::MetaType;
1157 } else {
1158 return QMetaType::fromType<T>().id();
1159 }
1160}
1161
1162template <typename T>
1163inline constexpr int qRegisterMetaType()
1164{
1165 int id = qMetaTypeId<T>();
1166 return id;
1167}
1168
1169#ifndef QT_NO_QOBJECT
1170template <typename T>
1171struct QMetaTypeIdQObject<T*, QMetaType::PointerToQObject>
1172{
1173 enum {
1174 Defined = 1
1175 };
1176
1177 static int qt_metatype_id()
1178 {
1179 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1180 if (const int id = metatype_id.loadAcquire())
1181 return id;
1182 const char *const cName = T::staticMetaObject.className();
1183 QByteArray typeName;
1184 typeName.reserve(int(strlen(cName)) + 1);
1185 typeName.append(cName).append('*');
1186 const int newId = qRegisterNormalizedMetaType<T *>(typeName);
1187 metatype_id.storeRelease(newId);
1188 return newId;
1189 }
1190};
1191
1192template <typename T>
1193struct QMetaTypeIdQObject<T, QMetaType::IsGadget>
1194{
1195 enum {
1196 Defined = std::is_default_constructible<T>::value
1197 };
1198
1199 static int qt_metatype_id()
1200 {
1201 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1202 if (const int id = metatype_id.loadAcquire())
1203 return id;
1204 const char *const cName = T::staticMetaObject.className();
1205 const int newId = qRegisterNormalizedMetaType<T>(cName);
1206 metatype_id.storeRelease(newId);
1207 return newId;
1208 }
1209};
1210
1211template <typename T>
1212struct QMetaTypeIdQObject<T*, QMetaType::PointerToGadget>
1213{
1214 enum {
1215 Defined = 1
1216 };
1217
1218 static int qt_metatype_id()
1219 {
1220 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1221 if (const int id = metatype_id.loadAcquire())
1222 return id;
1223 const char *const cName = T::staticMetaObject.className();
1224 QByteArray typeName;
1225 typeName.reserve(int(strlen(cName)) + 1);
1226 typeName.append(cName).append('*');
1227 const int newId = qRegisterNormalizedMetaType<T *>(typeName);
1228 metatype_id.storeRelease(newId);
1229 return newId;
1230 }
1231};
1232
1233template <typename T>
1234struct QMetaTypeIdQObject<T, QMetaType::IsEnumeration>
1235{
1236 enum {
1237 Defined = 1
1238 };
1239
1240 static int qt_metatype_id()
1241 {
1242 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1243 if (const int id = metatype_id.loadAcquire())
1244 return id;
1245 const char *eName = qt_getEnumName(T());
1246 const char *cName = qt_getEnumMetaObject(T())->className();
1247 QByteArray typeName;
1248 typeName.reserve(int(strlen(cName) + 2 + strlen(eName)));
1249 typeName.append(cName).append("::").append(eName);
1250 const int newId = qRegisterNormalizedMetaType<T>(typeName);
1251 metatype_id.storeRelease(newId);
1252 return newId;
1253 }
1254};
1255#endif
1256
1257#define Q_DECLARE_OPAQUE_POINTER(POINTER) \
1258 QT_BEGIN_NAMESPACE namespace QtPrivate { \
1259 template <> \
1260 struct IsPointerToTypeDerivedFromQObject<POINTER > \
1261 { \
1262 enum { Value = false }; \
1263 }; \
1264 } QT_END_NAMESPACE \
1265 /**/
1266
1267#ifndef Q_MOC_RUN
1268#define Q_DECLARE_METATYPE(TYPE) Q_DECLARE_METATYPE_IMPL(TYPE)
1269#define Q_DECLARE_METATYPE_IMPL(TYPE) \
1270 QT_BEGIN_NAMESPACE \
1271 template <> \
1272 struct QMetaTypeId< TYPE > \
1273 { \
1274 enum { Defined = 1 }; \
1275 static int qt_metatype_id() \
1276 { \
1277 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
1278 if (const int id = metatype_id.loadAcquire()) \
1279 return id; \
1280 const int newId = qRegisterMetaType< TYPE >(#TYPE); \
1281 metatype_id.storeRelease(newId); \
1282 return newId; \
1283 } \
1284 }; \
1285 QT_END_NAMESPACE
1286#endif // Q_MOC_RUN
1287
1288#define Q_DECLARE_BUILTIN_METATYPE(TYPE, METATYPEID, NAME) \
1289 QT_BEGIN_NAMESPACE \
1290 template<> struct QMetaTypeId2<NAME> \
1291 { \
1292 using NameAsArrayType = std::array<char, sizeof(#NAME)>; \
1293 enum { Defined = 1, IsBuiltIn = true, MetaType = METATYPEID }; \
1294 static inline constexpr int qt_metatype_id() { return METATYPEID; } \
1295 static constexpr NameAsArrayType nameAsArray = { #NAME }; \
1296 }; \
1297 QT_END_NAMESPACE
1298
1299#define QT_FORWARD_DECLARE_STATIC_TYPES_ITER(TypeName, TypeId, Name) \
1300 class Name;
1301
1302QT_FOR_EACH_STATIC_CORE_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1303QT_FOR_EACH_STATIC_GUI_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1304QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1305
1306#undef QT_FORWARD_DECLARE_STATIC_TYPES_ITER
1307
1308typedef QList<QVariant> QVariantList;
1309typedef QMap<QString, QVariant> QVariantMap;
1310typedef QHash<QString, QVariant> QVariantHash;
1311typedef QPair<QVariant, QVariant> QVariantPair;
1312#ifdef Q_CLANG_QDOC
1313class QByteArrayList;
1314#else
1315using QByteArrayList = QList<QByteArray>;
1316#endif
1317
1318#define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE) \
1319QT_BEGIN_NAMESPACE \
1320template <typename T> \
1321struct QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \
1322{ \
1323 enum { \
1324 Defined = QMetaTypeId2<T>::Defined \
1325 }; \
1326 static int qt_metatype_id() \
1327 { \
1328 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
1329 if (const int id = metatype_id.loadRelaxed()) \
1330 return id; \
1331 const char *tName = QMetaType::fromType<T>().name(); \
1332 Q_ASSERT(tName); \
1333 const int tNameLen = int(qstrlen(tName)); \
1334 QByteArray typeName; \
1335 typeName.reserve(int(sizeof(#SINGLE_ARG_TEMPLATE)) + 1 + tNameLen + 1 + 1); \
1336 typeName.append(#SINGLE_ARG_TEMPLATE, int(sizeof(#SINGLE_ARG_TEMPLATE)) - 1) \
1337 .append('<').append(tName, tNameLen); \
1338 typeName.append('>'); \
1339 const int newId = qRegisterNormalizedMetaType< SINGLE_ARG_TEMPLATE<T> >(typeName); \
1340 metatype_id.storeRelease(newId); \
1341 return newId; \
1342 } \
1343}; \
1344namespace QtPrivate { \
1345template<typename T> \
1346struct IsSequentialContainer<SINGLE_ARG_TEMPLATE<T> > \
1347{ \
1348 enum { Value = true }; \
1349}; \
1350} \
1351QT_END_NAMESPACE
1352
1353#define Q_DECLARE_METATYPE_TEMPLATE_2ARG(DOUBLE_ARG_TEMPLATE) \
1354QT_BEGIN_NAMESPACE \
1355template<typename T, typename U> \
1356struct QMetaTypeId< DOUBLE_ARG_TEMPLATE<T, U> > \
1357{ \
1358 enum { \
1359 Defined = QMetaTypeId2<T>::Defined && QMetaTypeId2<U>::Defined \
1360 }; \
1361 static int qt_metatype_id() \
1362 { \
1363 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
1364 if (const int id = metatype_id.loadAcquire()) \
1365 return id; \
1366 const char *tName = QMetaType::fromType<T>().name(); \
1367 const char *uName = QMetaType::fromType<U>().name(); \
1368 Q_ASSERT(tName); \
1369 Q_ASSERT(uName); \
1370 const int tNameLen = int(qstrlen(tName)); \
1371 const int uNameLen = int(qstrlen(uName)); \
1372 QByteArray typeName; \
1373 typeName.reserve(int(sizeof(#DOUBLE_ARG_TEMPLATE)) + 1 + tNameLen + 1 + uNameLen + 1 + 1); \
1374 typeName.append(#DOUBLE_ARG_TEMPLATE, int(sizeof(#DOUBLE_ARG_TEMPLATE)) - 1) \
1375 .append('<').append(tName, tNameLen).append(',').append(uName, uNameLen); \
1376 typeName.append('>'); \
1377 const int newId = qRegisterNormalizedMetaType< DOUBLE_ARG_TEMPLATE<T, U> >(typeName); \
1378 metatype_id.storeRelease(newId); \
1379 return newId; \
1380 } \
1381}; \
1382QT_END_NAMESPACE
1383
1384namespace QtPrivate {
1385
1386template<typename T, bool /* isSharedPointerToQObjectDerived */ = false>
1387struct SharedPointerMetaTypeIdHelper
1388{
1389 enum {
1390 Defined = 0
1391 };
1392 static int qt_metatype_id()
1393 {
1394 return -1;
1395 }
1396};
1397
1398}
1399
1400#define Q_DECLARE_SMART_POINTER_METATYPE(SMART_POINTER) \
1401QT_BEGIN_NAMESPACE \
1402namespace QtPrivate { \
1403template<typename T> \
1404struct SharedPointerMetaTypeIdHelper<SMART_POINTER<T>, true> \
1405{ \
1406 enum { \
1407 Defined = 1 \
1408 }; \
1409 static int qt_metatype_id() \
1410 { \
1411 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
1412 if (const int id = metatype_id.loadAcquire()) \
1413 return id; \
1414 const char * const cName = T::staticMetaObject.className(); \
1415 QByteArray typeName; \
1416 typeName.reserve(int(sizeof(#SMART_POINTER) + 1 + strlen(cName) + 1)); \
1417 typeName.append(#SMART_POINTER, int(sizeof(#SMART_POINTER)) - 1) \
1418 .append('<').append(cName).append('>'); \
1419 const int newId = qRegisterNormalizedMetaType< SMART_POINTER<T> >(typeName); \
1420 metatype_id.storeRelease(newId); \
1421 return newId; \
1422 } \
1423}; \
1424template<typename T> \
1425struct MetaTypeSmartPointerHelper<SMART_POINTER<T> , \
1426 typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value>::type> \
1427{ \
1428 static bool registerConverter() \
1429 { \
1430 const QMetaType to = QMetaType(QMetaType::QObjectStar); \
1431 if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<SMART_POINTER<T>>(), to)) { \
1432 QtPrivate::QSmartPointerConvertFunctor<SMART_POINTER<T> > o; \
1433 return QMetaType::registerConverter<SMART_POINTER<T>, QObject*>(o); \
1434 } \
1435 return true; \
1436 } \
1437}; \
1438} \
1439template <typename T> \
1440struct QMetaTypeId< SMART_POINTER<T> > \
1441 : QtPrivate::SharedPointerMetaTypeIdHelper< SMART_POINTER<T>, \
1442 QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value> \
1443{ \
1444};\
1445QT_END_NAMESPACE
1446
1447#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER(TEMPLATENAME) \
1448 QT_BEGIN_NAMESPACE \
1449 template <class T> class TEMPLATENAME; \
1450 QT_END_NAMESPACE \
1451 Q_DECLARE_METATYPE_TEMPLATE_1ARG(TEMPLATENAME)
1452
1453QT_END_NAMESPACE
1454
1455QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER)
1456
1457#undef Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER
1458
1459#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE Q_DECLARE_METATYPE_TEMPLATE_1ARG
1460
1461Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::vector)
1462Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::list)
1463
1464#define Q_FORWARD_DECLARE_METATYPE_TEMPLATE_2ARG_ITER(TEMPLATENAME, CPPTYPE) \
1465 QT_BEGIN_NAMESPACE \
1466 template <class T1, class T2> CPPTYPE TEMPLATENAME; \
1467 QT_END_NAMESPACE \
1468
1469QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(Q_FORWARD_DECLARE_METATYPE_TEMPLATE_2ARG_ITER)
1470
1471#undef Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER
1472
1473#define Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(TEMPLATENAME) \
1474 QT_BEGIN_NAMESPACE \
1475 namespace QtPrivate { \
1476 template<typename T, typename U> \
1477 struct IsAssociativeContainer<TEMPLATENAME<T, U> > \
1478 { \
1479 enum { Value = true }; \
1480 }; \
1481 } \
1482 QT_END_NAMESPACE \
1483 Q_DECLARE_METATYPE_TEMPLATE_2ARG(TEMPLATENAME)
1484
1485Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QHash)
1486Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QMap)
1487Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(std::map)
1488
1489Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::pair)
1490
1491#define Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER(TEMPLATENAME) \
1492 Q_DECLARE_SMART_POINTER_METATYPE(TEMPLATENAME)
1493
1494QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER)
1495
1496QT_BEGIN_NAMESPACE
1497
1498#undef Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER
1499
1500QT_END_NAMESPACE
1501
1502QT_FOR_EACH_STATIC_TYPE(Q_DECLARE_BUILTIN_METATYPE)
1503
1504Q_DECLARE_METATYPE(QtMetaTypePrivate::QPairVariantInterfaceImpl)
1505
1506QT_BEGIN_NAMESPACE
1507
1508template <typename T>
1509inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter()
1510{
1511 const QMetaType to = QMetaType::fromType<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
1512 if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<T>(), to)) {
1513 QtMetaTypePrivate::QPairVariantInterfaceConvertFunctor<T> o;
1514 return QMetaType::registerConverter<T, QtMetaTypePrivate::QPairVariantInterfaceImpl>(o);
1515 }
1516 return true;
1517}
1518
1519namespace QtPrivate {
1520
1521template<typename From>
1522struct QSequentialIterableConvertFunctor
1523{
1524 QIterable<QMetaSequence> operator()(const From &f) const
1525 {
1526 return QIterable<QMetaSequence>(QMetaSequence::fromContainer<From>(), &f);
1527 }
1528};
1529
1530template<typename From>
1531struct QSequentialIterableMutableViewFunctor
1532{
1533 QIterable<QMetaSequence> operator()(From &f) const
1534 {
1535 return QIterable<QMetaSequence>(QMetaSequence::fromContainer<From>(), &f);
1536 }
1537};
1538
1539template<typename T>
1540struct SequentialValueTypeIsMetaType<T, true>
1541{
1542 static bool registerConverter()
1543 {
1544 const QMetaType to = QMetaType::fromType<QIterable<QMetaSequence>>();
1545 if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<T>(), to)) {
1546 QSequentialIterableConvertFunctor<T> o;
1547 return QMetaType::registerConverter<T, QIterable<QMetaSequence>>(o);
1548 }
1549 return true;
1550 }
1551
1552 static bool registerMutableView()
1553 {
1554 const QMetaType to = QMetaType::fromType<QIterable<QMetaSequence>>();
1555 if (!QMetaType::hasRegisteredMutableViewFunction(QMetaType::fromType<T>(), to)) {
1556 QSequentialIterableMutableViewFunctor<T> o;
1557 return QMetaType::registerMutableView<T, QIterable<QMetaSequence>>(o);
1558 }
1559 return true;
1560 }
1561};
1562
1563template<typename From>
1564struct QAssociativeIterableConvertFunctor
1565{
1566 QIterable<QMetaAssociation> operator()(const From &f) const
1567 {
1568 return QIterable<QMetaAssociation>(QMetaAssociation::fromContainer<From>(), &f);
1569 }
1570};
1571
1572template<typename From>
1573struct QAssociativeIterableMutableViewFunctor
1574{
1575 QIterable<QMetaAssociation> operator()(From &f) const
1576 {
1577 return QIterable<QMetaAssociation>(QMetaAssociation::fromContainer<From>(), &f);
1578 }
1579};
1580
1581// Mapped type can be omitted, for example in case of a set.
1582// However, if it is available, we want to instantiate the metatype here.
1583template<typename T>
1584struct AssociativeKeyTypeIsMetaType<T, true> : AssociativeMappedTypeIsMetaType<T>
1585{
1586 static bool registerConverter()
1587 {
1588 const QMetaType to = QMetaType::fromType<QIterable<QMetaAssociation>>();
1589 if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<T>(), to)) {
1590 QAssociativeIterableConvertFunctor<T> o;
1591 return QMetaType::registerConverter<T, QIterable<QMetaAssociation>>(o);
1592 }
1593 return true;
1594 }
1595
1596 static bool registerMutableView()
1597 {
1598 const QMetaType to = QMetaType::fromType<QIterable<QMetaAssociation>>();
1599 if (!QMetaType::hasRegisteredMutableViewFunction(QMetaType::fromType<T>(), to)) {
1600 QAssociativeIterableMutableViewFunctor<T> o;
1601 return QMetaType::registerMutableView<T, QIterable<QMetaAssociation>>(o);
1602 }
1603 return true;
1604 }
1605};
1606
1607class QMetaTypeInterface
1608{
1609public:
1610 ushort revision; // 0 in Qt 6.0. Can increase if new field are added
1611 ushort alignment;
1612 uint size;
1613 uint flags;
1614 mutable QBasicAtomicInt typeId;
1615 const QMetaObject *metaObject;
1616 const char *name;
1617
1618 using DefaultCtrFn = void (*)(const QMetaTypeInterface *, void *);
1619 DefaultCtrFn defaultCtr;
1620 using CopyCtrFn = void (*)(const QMetaTypeInterface *, void *, const void *);
1621 CopyCtrFn copyCtr;
1622 using MoveCtrFn = void (*)(const QMetaTypeInterface *, void *, void *);
1623 MoveCtrFn moveCtr;
1624 using DtorFn = void (*)(const QMetaTypeInterface *, void *);
1625 DtorFn dtor;
1626 using EqualsFn = bool (*)(const QMetaTypeInterface *, const void *, const void *);
1627 EqualsFn equals;
1628 using LessThanFn = bool (*)(const QMetaTypeInterface *, const void *, const void *);
1629 LessThanFn lessThan;
1630 using DebugStreamFn = void (*)(const QMetaTypeInterface *, QDebug &, const void *);
1631 DebugStreamFn debugStream;
1632 using DataStreamOutFn = void (*)(const QMetaTypeInterface *, QDataStream &, const void *);
1633 DataStreamOutFn dataStreamOut;
1634 using DataStreamInFn = void (*)(const QMetaTypeInterface *, QDataStream &, void *);
1635 DataStreamInFn dataStreamIn;
1636
1637 using LegacyRegisterOp = void (*)();
1638 LegacyRegisterOp legacyRegisterOp;
1639};
1640
1641struct QTypeNormalizer
1642{
1643 char *output;
1644 int len = 0;
1645 char last = 0;
1646
1647private:
1648 static constexpr bool is_ident_char(char s)
1649 {
1650 return ((s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z') || (s >= '0' && s <= '9')
1651 || s == '_');
1652 }
1653 static constexpr bool is_space(char s) { return (s == ' ' || s == '\t' || s == '\n'); }
1654 static constexpr bool is_number(char s) { return s >= '0' && s <= '9'; }
1655 static constexpr bool starts_with_token(const char *b, const char *e, const char *token,
1656 bool msvcKw = false)
1657 {
1658 while (b != e && *token && *b == *token) {
1659 b++;
1660 token++;
1661 }
1662 if (*token)
1663 return false;
1664#ifdef Q_CC_MSVC
1665 /// On MSVC, keywords like class or struct are not separated with spaces in constexpr
1666 /// context
1667 if (msvcKw)
1668 return true;
1669#endif
1670 Q_UNUSED(msvcKw);
1671 return b == e || !is_ident_char(*b);
1672 }
1673 static constexpr bool skipToken(const char *&x, const char *e, const char *token,
1674 bool msvcKw = false)
1675 {
1676 if (!starts_with_token(x, e, token, msvcKw))
1677 return false;
1678 while (*token++)
1679 x++;
1680 while (x != e && is_space(*x))
1681 x++;
1682 return true;
1683 }
1684 static constexpr const char *skipString(const char *x, const char *e)
1685 {
1686 char delim = *x;
1687 x++;
1688 while (x != e && *x != delim) {
1689 if (*x == '\\') {
1690 x++;
1691 if (x == e)
1692 return e;
1693 }
1694 x++;
1695 }
1696 if (x != e)
1697 x++;
1698 return x;
1699 };
1700 static constexpr const char *skipTemplate(const char *x, const char *e, bool stopAtComa = false)
1701 {
1702 int scopeDepth = 0;
1703 int templateDepth = 0;
1704 while (x != e) {
1705 switch (*x) {
1706 case '<':
1707 if (!scopeDepth)
1708 templateDepth++;
1709 break;
1710 case ',':
1711 if (stopAtComa && !scopeDepth && !templateDepth)
1712 return x;
1713 break;
1714 case '>':
1715 if (!scopeDepth)
1716 if (--templateDepth < 0)
1717 return x;
1718 break;
1719 case '(':
1720 case '[':
1721 case '{':
1722 scopeDepth++;
1723 break;
1724 case '}':
1725 case ']':
1726 case ')':
1727 scopeDepth--;
1728 break;
1729 case '\'':
1730 if (is_number(x[-1]))
1731 break;
1732 Q_FALLTHROUGH();
1733 case '\"':
1734 x = skipString(x, e);
1735 continue;
1736 }
1737 x++;
1738 }
1739 return x;
1740 };
1741
1742 constexpr void append(char x)
1743 {
1744 last = x;
1745 len++;
1746 if (output)
1747 *output++ = x;
1748 }
1749
1750 constexpr void replaceLast(char x)
1751 {
1752 last = x;
1753 if (output)
1754 *(output - 1) = x;
1755 }
1756
1757 constexpr void appendStr(const char *x)
1758 {
1759 while (*x)
1760 append(*x++);
1761 };
1762
1763 constexpr void normalizeIntegerTypes(const char *&begin, const char *end)
1764 {
1765 int numLong = 0;
1766 int numSigned = 0;
1767 int numUnsigned = 0;
1768 int numInt = 0;
1769 int numShort = 0;
1770 int numChar = 0;
1771 while (begin < end) {
1772 if (skipToken(begin, end, "long")) {
1773 numLong++;
1774 continue;
1775 }
1776 if (skipToken(begin, end, "int")) {
1777 numInt++;
1778 continue;
1779 }
1780 if (skipToken(begin, end, "short")) {
1781 numShort++;
1782 continue;
1783 }
1784 if (skipToken(begin, end, "unsigned")) {
1785 numUnsigned++;
1786 continue;
1787 }
1788 if (skipToken(begin, end, "signed")) {
1789 numSigned++;
1790 continue;
1791 }
1792 if (skipToken(begin, end, "char")) {
1793 numChar++;
1794 continue;
1795 }
1796#ifdef Q_CC_MSVC
1797 if (skipToken(begin, end, "__int64")) {
1798 numLong = 2;
1799 continue;
1800 }
1801#endif
1802 break;
1803 }
1804 if (numLong == 2)
1805 append('q'); // q(u)longlong
1806 if (numSigned && numChar)
1807 appendStr("signed ");
1808 else if (numUnsigned)
1809 appendStr("u");
1810 if (numChar)
1811 appendStr("char");
1812 else if (numShort)
1813 appendStr("short");
1814 else if (numLong == 1)
1815 appendStr("long");
1816 else if (numLong == 2)
1817 appendStr("longlong");
1818 else if (numUnsigned || numSigned || numInt)
1819 appendStr("int");
1820 }
1821
1822 constexpr void skipStructClassOrEnum(const char *&begin, const char *end)
1823 {
1824 // discard 'struct', 'class', and 'enum'; they are optional
1825 // and we don't want them in the normalized signature
1826 skipToken(begin, end, "struct", true) || skipToken(begin, end, "class", true)
1827 || skipToken(begin, end, "enum", true);
1828 }
1829
1830 constexpr void skipQtNamespace(const char *&begin, const char *end)
1831 {
1832#ifdef QT_NAMESPACE
1833 const char *nsbeg = begin;
1834 if (skipToken(nsbeg, end, QT_STRINGIFY(QT_NAMESPACE)) && nsbeg + 2 < end && nsbeg[0] == ':'
1835 && nsbeg[1] == ':') {
1836 begin = nsbeg + 2;
1837 while (begin != end && is_space(*begin))
1838 begin++;
1839 }
1840#else
1841 Q_UNUSED(begin);
1842 Q_UNUSED(end);
1843#endif
1844 }
1845
1846public:
1847#ifndef Q_CC_MSVC
1848 // this is much simpler than the full type normalization below
1849 // the reason is that the signature returned by Q_FUNC_INFO is already
1850 // normalized to the largest degree, and we need to do only small adjustments
1851 constexpr int normalizeTypeFromSignature(const char *begin, const char *end)
1852 {
1853 while (begin < end) {
1854 if (*begin == ' ') {
1855 if (last == ',' || last == '>' || last == '<' || last == '*' || last == '&') {
1856 ++begin;
1857 continue;
1858 }
1859 }
1860 if (last == ' ') {
1861 if (*begin == '*' || *begin == '&') {
1862 replaceLast(*begin);
1863 ++begin;
1864 continue;
1865 }
1866 }
1867 if (!is_ident_char(last)) {
1868 skipStructClassOrEnum(begin, end);
1869 if (begin == end)
1870 break;
1871
1872 skipQtNamespace(begin, end);
1873 if (begin == end)
1874 break;
1875
1876 normalizeIntegerTypes(begin, end);
1877 if (begin == end)
1878 break;
1879 }
1880 append(*begin);
1881 ++begin;
1882 }
1883 return len;
1884 }
1885#else
1886 // MSVC needs the full normalization, as it puts the const in a different
1887 // place than we expect
1888 constexpr int normalizeTypeFromSignature(const char *begin, const char *end)
1889 { return normalizeType(begin, end); }
1890#endif
1891
1892 constexpr int normalizeType(const char *begin, const char *end, bool adjustConst = true)
1893 {
1894 // Trim spaces
1895 while (begin != end && is_space(*begin))
1896 begin++;
1897 while (begin != end && is_space(*(end - 1)))
1898 end--;
1899
1900 // Convert 'char const *' into 'const char *'. Start at index 1,
1901 // not 0, because 'const char *' is already OK.
1902 const char *cst = begin + 1;
1903 if (*begin == '\'' || *begin == '"')
1904 cst = skipString(begin, end);
1905 bool seenStar = false;
1906 bool hasMiddleConst = false;
1907 while (cst < end) {
1908 if (*cst == '\"' || (*cst == '\'' && !is_number(cst[-1]))) {
1909 cst = skipString(cst, end);
1910 if (cst == end)
1911 break;
1912 }
1913
1914 // We mustn't convert 'char * const *' into 'const char **'
1915 // and we must beware of 'Bar<const Bla>'.
1916 if (*cst == '&' || *cst == '*' || *cst == '[') {
1917 seenStar = *cst != '&' || cst != (end - 1);
1918 break;
1919 }
1920 if (*cst == '<') {
1921 cst = skipTemplate(cst + 1, end);
1922 if (cst == end)
1923 break;
1924 }
1925 cst++;
1926 const char *skipedCst = cst;
1927 if (!is_ident_char(*(cst - 1)) && skipToken(skipedCst, end, "const")) {
1928 const char *testEnd = end;
1929 while (skipedCst < testEnd--) {
1930 if (*testEnd == '*' || *testEnd == '['
1931 || (*testEnd == '&' && testEnd != (end - 1))) {
1932 seenStar = true;
1933 break;
1934 }
1935 if (*testEnd == '>')
1936 break;
1937 }
1938 if (adjustConst && !seenStar) {
1939 if (*(end - 1) == '&')
1940 end--;
1941 } else {
1942 appendStr("const ");
1943 }
1944 normalizeType(begin, cst, false);
1945 begin = skipedCst;
1946 hasMiddleConst = true;
1947 break;
1948 }
1949 }
1950 if (skipToken(begin, end, "const")) {
1951 if (adjustConst && !seenStar) {
1952 if (*(end - 1) == '&')
1953 end--;
1954 } else {
1955 appendStr("const ");
1956 }
1957 }
1958 if (seenStar && adjustConst) {
1959 const char *e = end;
1960 if (*(end - 1) == '&' && *(end - 2) != '&')
1961 e--;
1962 while (begin != e && is_space(*(e - 1)))
1963 e--;
1964 const char *token = "tsnoc"; // 'const' reverse, to check if it ends with const
1965 while (*token && begin != e && *(--e) == *token++)
1966 ;
1967 if (!*token && begin != e && !is_ident_char(*(e - 1))) {
1968 while (begin != e && is_space(*(e - 1)))
1969 e--;
1970 end = e;
1971 }
1972 }
1973
1974 skipStructClassOrEnum(begin, end);
1975 skipQtNamespace(begin, end);
1976
1977 if (skipToken(begin, end, "QVector")) {
1978 // Replace QVector by QList
1979 appendStr("QList");
1980 }
1981
1982 if (skipToken(begin, end, "QPair")) {
1983 // replace QPair by std::pair
1984 appendStr("std::pair");
1985 }
1986
1987 if (!hasMiddleConst)
1988 // Normalize the integer types
1989 normalizeIntegerTypes(begin, end);
1990
1991 bool spaceSkiped = true;
1992 while (begin != end) {
1993 char c = *begin++;
1994 if (is_space(c)) {
1995 spaceSkiped = true;
1996 } else if ((c == '\'' && !is_number(last)) || c == '\"') {
1997 begin--;
1998 auto x = skipString(begin, end);
1999 while (begin < x)
2000 append(*begin++);
2001 } else {
2002 if (spaceSkiped && is_ident_char(last) && is_ident_char(c))
2003 append(' ');
2004 append(c);
2005 spaceSkiped = false;
2006 if (c == '<') {
2007 do {
2008 // template recursion
2009 const char *tpl = skipTemplate(begin, end, true);
2010 normalizeType(begin, tpl, false);
2011 if (tpl == end)
2012 return len;
2013 append(*tpl);
2014 begin = tpl;
2015 } while (*begin++ == ',');
2016 }
2017 }
2018 }
2019 return len;
2020 }
2021};
2022
2023// Normalize the type between begin and end, and store the data in the output. Returns the length.
2024// The idea is to first run this function with nullptr as output to allocate the output with the
2025// size
2026constexpr int qNormalizeType(const char *begin, const char *end, char *output)
2027{
2028 return QTypeNormalizer { output }.normalizeType(begin, end);
2029}
2030
2031template<typename T>
2032struct is_std_pair : std::false_type {};
2033
2034template <typename T1_, typename T2_>
2035struct is_std_pair<std::pair<T1_, T2_>> : std::true_type {
2036 using T1 = T1_;
2037 using T2 = T2_;
2038};
2039
2040template<typename T>
2041constexpr auto typenameHelper()
2042{
2043 if constexpr (is_std_pair<T>::value) {
2044 using T1 = typename is_std_pair<T>::T1;
2045 using T2 = typename is_std_pair<T>::T2;
2046 std::remove_const_t<std::conditional_t<bool (QMetaTypeId2<T1>::IsBuiltIn), typename QMetaTypeId2<T1>::NameAsArrayType, decltype(typenameHelper<T1>())>> t1Name {};
2047 std::remove_const_t<std::conditional_t<bool (QMetaTypeId2<T2>::IsBuiltIn), typename QMetaTypeId2<T2>::NameAsArrayType, decltype(typenameHelper<T2>())>> t2Name {};
2048 if constexpr (bool (QMetaTypeId2<T1>::IsBuiltIn) ) {
2049 t1Name = QMetaTypeId2<T1>::nameAsArray;
2050 } else {
2051 t1Name = typenameHelper<T1>();
2052 }
2053 if constexpr (bool(QMetaTypeId2<T2>::IsBuiltIn)) {
2054 t2Name = QMetaTypeId2<T2>::nameAsArray;
2055 } else {
2056 t2Name = typenameHelper<T2>();
2057 }
2058 constexpr auto nonTypeDependentLen = sizeof("std::pair<,>");
2059 constexpr auto t1Len = t1Name.size() - 1;
2060 constexpr auto t2Len = t2Name.size() - 1;
2061 constexpr auto length = nonTypeDependentLen + t1Len + t2Len;
2062 std::array<char, length + 1> result {};
2063 constexpr auto prefix = "std::pair<";
2064 int currentLength = 0;
2065 for (; currentLength < int(sizeof("std::pair<") - 1); ++currentLength)
2066 result[currentLength] = prefix[currentLength];
2067 for (int i = 0; i < int(t1Len); ++currentLength, ++i)
2068 result[currentLength] = t1Name[i];
2069 result[currentLength++] = ',';
2070 for (int i = 0; i < int(t2Len); ++currentLength, ++i)
2071 result[currentLength] = t2Name[i];
2072 result[currentLength++] = '>';
2073 result[currentLength++] = '\0';
2074 return result;
2075 } else {
2076 constexpr auto prefix = sizeof(
2077#ifdef QT_NAMESPACE
2078 QT_STRINGIFY(QT_NAMESPACE) "::"
2079#endif
2080#ifdef Q_CC_MSVC
2081 "auto __cdecl QtPrivate::typenameHelper<"
2082#elif defined(Q_CC_CLANG)
2083 "auto QtPrivate::typenameHelper() [T = "
2084#else
2085 "constexpr auto QtPrivate::typenameHelper() [with T = "
2086#endif
2087 ) - 1;
2088#ifdef Q_CC_MSVC
2089 constexpr int suffix = sizeof(">(void)");
2090#else
2091 constexpr int suffix = sizeof("]");
2092#endif
2093
2094#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG) && Q_CC_GNU < 804)
2095 auto func = Q_FUNC_INFO;
2096 const char *begin = func + prefix;
2097 const char *end = func + sizeof(Q_FUNC_INFO) - suffix;
2098 // This is an upper bound of the size since the normalized signature should always be smaller
2099 constexpr int len = sizeof(Q_FUNC_INFO) - suffix - prefix;
2100#else
2101 constexpr auto func = Q_FUNC_INFO;
2102 constexpr const char *begin = func + prefix;
2103 constexpr const char *end = func + sizeof(Q_FUNC_INFO) - suffix;
2104 constexpr int len = QTypeNormalizer{ nullptr }.normalizeTypeFromSignature(begin, end);
2105#endif
2106 std::array<char, len + 1> result {};
2107 QTypeNormalizer{ result.data() }.normalizeTypeFromSignature(begin, end);
2108 return result;
2109 }
2110}
2111
2112template<typename T, typename = void>
2113struct BuiltinMetaType : std::integral_constant<int, 0>
2114{
2115};
2116template<typename T>
2117struct BuiltinMetaType<T, std::enable_if_t<QMetaTypeId2<T>::IsBuiltIn>>
2118 : std::integral_constant<int, QMetaTypeId2<T>::MetaType>
2119{
2120};
2121
2122template<typename T, bool = (QTypeTraits::has_operator_equal_v<T> && !std::is_pointer_v<T>)>
2123struct QEqualityOperatorForType
2124{
2125QT_WARNING_PUSH
2126QT_WARNING_DISABLE_FLOAT_COMPARE
2127 static bool equals(const QMetaTypeInterface *, const void *a, const void *b)
2128 { return *reinterpret_cast<const T *>(a) == *reinterpret_cast<const T *>(b); }
2129QT_WARNING_POP
2130};
2131
2132template<typename T>
2133struct QEqualityOperatorForType <T, false>
2134{
2135 static constexpr QMetaTypeInterface::EqualsFn equals = nullptr;
2136};
2137
2138template<typename T, bool = (QTypeTraits::has_operator_less_than_v<T> && !std::is_pointer_v<T>)>
2139struct QLessThanOperatorForType
2140{
2141 static bool lessThan(const QMetaTypeInterface *, const void *a, const void *b)
2142 { return *reinterpret_cast<const T *>(a) < *reinterpret_cast<const T *>(b); }
2143};
2144
2145template<typename T>
2146struct QLessThanOperatorForType <T, false>
2147{
2148 static constexpr QMetaTypeInterface::LessThanFn lessThan = nullptr;
2149};
2150
2151template<typename T, bool = (QTypeTraits::has_ostream_operator_v<QDebug, T> && !std::is_pointer_v<T>)>
2152struct QDebugStreamOperatorForType
2153{
2154 static void debugStream(const QMetaTypeInterface *, QDebug &dbg, const void *a)
2155 { dbg << *reinterpret_cast<const T *>(a); }
2156};
2157
2158template<typename T>
2159struct QDebugStreamOperatorForType <T, false>
2160{
2161 static constexpr QMetaTypeInterface::DebugStreamFn debugStream = nullptr;
2162};
2163
2164template<typename T, bool = QTypeTraits::has_stream_operator_v<QDataStream, T>>
2165struct QDataStreamOperatorForType
2166{
2167 static void dataStreamOut(const QMetaTypeInterface *, QDataStream &ds, const void *a)
2168 { ds << *reinterpret_cast<const T *>(a); }
2169 static void dataStreamIn(const QMetaTypeInterface *, QDataStream &ds, void *a)
2170 { ds >> *reinterpret_cast<T *>(a); }
2171};
2172
2173template<typename T>
2174struct QDataStreamOperatorForType <T, false>
2175{
2176 static constexpr QMetaTypeInterface::DataStreamOutFn dataStreamOut = nullptr;
2177 static constexpr QMetaTypeInterface::DataStreamInFn dataStreamIn = nullptr;
2178};
2179
2180template<typename S>
2181class QMetaTypeForType
2182{
2183public:
2184 static constexpr decltype(typenameHelper<S>()) name = typenameHelper<S>();
2185
2186 static constexpr QMetaTypeInterface::DefaultCtrFn getDefaultCtr()
2187 {
2188 if constexpr (std::is_default_constructible_v<S>) {
2189 return [](const QMetaTypeInterface *, void *addr) { new (addr) S(); };
2190 } else {
2191 return nullptr;
2192 }
2193 }
2194
2195 static constexpr QMetaTypeInterface::CopyCtrFn getCopyCtr()
2196 {
2197 if constexpr (std::is_copy_constructible_v<S>) {
2198 return [](const QMetaTypeInterface *, void *addr, const void *other) {
2199 new (addr) S(*reinterpret_cast<const S *>(other));
2200 };
2201 } else {
2202 return nullptr;
2203 }
2204 }
2205
2206 static constexpr QMetaTypeInterface::MoveCtrFn getMoveCtr()
2207 {
2208 if constexpr (std::is_move_constructible_v<S>) {
2209 return [](const QMetaTypeInterface *, void *addr, void *other) {
2210 new (addr) S(std::move(*reinterpret_cast<S *>(other)));
2211 };
2212 } else {
2213 return nullptr;
2214 }
2215 }
2216
2217 static constexpr QMetaTypeInterface::DtorFn getDtor()
2218 {
2219 if constexpr (std::is_destructible_v<S>)
2220 return [](const QMetaTypeInterface *, void *addr) {
2221 reinterpret_cast<S *>(addr)->~S();
2222 };
2223 else
2224 return nullptr;
2225 }
2226
2227 static constexpr QMetaTypeInterface::LegacyRegisterOp getLegacyRegister()
2228 {
2229 if constexpr (QMetaTypeId2<S>::Defined && !QMetaTypeId2<S>::IsBuiltIn) {
2230 return []() { QMetaTypeId2<S>::qt_metatype_id(); };
2231 } else {
2232 return nullptr;
2233 }
2234 }
2235
2236 static constexpr const char *getName()
2237 {
2238 if constexpr (bool(QMetaTypeId2<S>::IsBuiltIn)) {
2239 return QMetaTypeId2<S>::nameAsArray.data();
2240 } else {
2241 return name.data();
2242 }
2243 }
2244};
2245
2246template<typename T>
2247struct QMetaTypeInterfaceWrapper
2248{
2249 static inline constexpr QMetaTypeInterface create()
2250 {
2251 return {
2252 /*.revision=*/ 0,
2253 /*.alignment=*/ alignof(T),
2254 /*.size=*/ sizeof(T),
2255 /*.flags=*/ QMetaTypeTypeFlags<T>::Flags,
2256 /*.typeId=*/ BuiltinMetaType<T>::value,
2257 /*.metaObject=*/ MetaObjectForType<T>::value(),
2258 /*.name=*/ QMetaTypeForType<T>::getName(),
2259 /*.defaultCtr=*/ QMetaTypeForType<T>::getDefaultCtr(),
2260 /*.copyCtr=*/ QMetaTypeForType<T>::getCopyCtr(),
2261 /*.moveCtr=*/ QMetaTypeForType<T>::getMoveCtr(),
2262 /*.dtor=*/ QMetaTypeForType<T>::getDtor(),
2263 /*.equals=*/ QEqualityOperatorForType<T>::equals,
2264 /*.lessThan=*/ QLessThanOperatorForType<T>::lessThan,
2265 /*.debugStream=*/ QDebugStreamOperatorForType<T>::debugStream,
2266 /*.dataStreamOut=*/ QDataStreamOperatorForType<T>::dataStreamOut,
2267 /*.dataStreamIn=*/ QDataStreamOperatorForType<T>::dataStreamIn,
2268 /*.legacyRegisterOp=*/ QMetaTypeForType<T>::getLegacyRegister()
2269 };
2270 }
2271
2272#ifdef Q_OS_WIN
2273 // MSVC produces link errors when the metaType is constexpr
2274 static const QMetaTypeInterface metaType;
2275#else
2276 static constexpr const QMetaTypeInterface metaType = create();
2277#endif
2278};
2279
2280#ifdef Q_OS_WIN
2281template<typename T>
2282const QMetaTypeInterface QMetaTypeInterfaceWrapper<T>::metaType
2283 = QMetaTypeInterfaceWrapper<T>::create();
2284#endif
2285
2286template<>
2287class QMetaTypeInterfaceWrapper<void>
2288{
2289public:
2290 static constexpr QMetaTypeInterface metaType =
2291 {
2292 /*.revision=*/ 0,
2293 /*.alignment=*/ 0,
2294 /*.size=*/ 0,
2295 /*.flags=*/ 0,
2296 /*.typeId=*/ BuiltinMetaType<void>::value,
2297 /*.metaObject=*/ nullptr,
2298 /*.name=*/ "void",
2299 /*.defaultCtr=*/ nullptr,
2300 /*.copyCtr=*/ nullptr,
2301 /*.moveCtr=*/ nullptr,
2302 /*.dtor=*/ nullptr,
2303 /*.equals=*/ nullptr,
2304 /*.lessThan=*/ nullptr,
2305 /*.debugStream=*/ nullptr,
2306 /*.dataStreamOut=*/ nullptr,
2307 /*.dataStreamIn=*/ nullptr,
2308 /*.legacyRegisterOp=*/ nullptr
2309 };
2310};
2311#undef QT_METATYPE_CONSTEXPRLAMDA
2312
2313#ifndef QT_BOOTSTRAPPED
2314
2315#if !defined(Q_CC_MSVC) || !defined(QT_BUILD_CORE_LIB)
2316#define QT_METATYPE_TEMPLATE_EXPORT Q_CORE_EXPORT
2317#else
2318#define QT_METATYPE_TEMPLATE_EXPORT
2319#endif
2320
2321#define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name) \
2322 extern template class QT_METATYPE_TEMPLATE_EXPORT QMetaTypeForType<Name>;
2323QT_WARNING_PUSH
2324QT_WARNING_DISABLE_GCC("-Wattributes") // false positive because of QMetaTypeForType<void>
2325QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
2326QT_WARNING_POP
2327QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
2328QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
2329QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
2330QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
2331#undef QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER
2332#undef QT_METATYPE_TEMPLATE_EXPORT
2333#endif
2334
2335template<typename T>
2336constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType()
2337{
2338 using Ty = std::remove_cv_t<std::remove_reference_t<T>>;
2339 return &QMetaTypeInterfaceWrapper<Ty>::metaType;
2340}
2341
2342namespace detail {
2343template<typename T, typename ODR_VIOLATION_PREVENTER>
2344struct is_complete_helper
2345{
2346 template<typename U>
2347 static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
2348 static auto check(...) -> std::false_type;
2349 using type = decltype(check(static_cast<T *>(nullptr)));
2350};
2351} // namespace detail
2352
2353template <typename T, typename ODR_VIOLATION_PREVENTER>
2354struct is_complete : detail::is_complete_helper<T, ODR_VIOLATION_PREVENTER>::type {};
2355
2356template<typename T>
2357struct qRemovePointerLike
2358{
2359 using type = std::remove_pointer_t<T>;
2360};
2361
2362#define Q_REMOVE_POINTER_LIKE_IMPL(Pointer) \
2363template <typename T> \
2364struct qRemovePointerLike<Pointer<T>> \
2365{ \
2366 using type = T; \
2367};
2368
2369QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(Q_REMOVE_POINTER_LIKE_IMPL)
2370template<typename T>
2371using qRemovePointerLike_t = typename qRemovePointerLike<T>::type;
2372#undef Q_REMOVE_POINTER_LIKE_IMPL
2373
2374template<typename T, typename ForceComplete_>
2375struct TypeAndForceComplete
2376{
2377 using type = T;
2378 using ForceComplete = ForceComplete_;
2379};
2380
2381template<typename Unique, typename TypeCompletePair>
2382constexpr const QMetaTypeInterface *qTryMetaTypeInterfaceForType()
2383{
2384 using T = typename TypeCompletePair::type;
2385 using ForceComplete = typename TypeCompletePair::ForceComplete;
2386 using Ty = std::remove_cv_t<std::remove_reference_t<T>>;
2387 using Tz = qRemovePointerLike_t<Ty>;
2388 if constexpr (!is_complete<Tz, Unique>::value && !ForceComplete::value) {
2389 return nullptr;
2390 } else {
2391 return &QMetaTypeInterfaceWrapper<Ty>::metaType;
2392 }
2393}
2394
2395} // namespace QtPrivate
2396
2397template<typename T>
2398constexpr QMetaType QMetaType::fromType()
2399{
2400 return QMetaType(QtPrivate::qMetaTypeInterfaceForType<T>());
2401}
2402
2403constexpr qsizetype QMetaType::sizeOf() const
2404{
2405 return d_ptr ? d_ptr->size : 0;
2406}
2407
2408constexpr qsizetype QMetaType::alignOf() const
2409{
2410 return d_ptr ? d_ptr->alignment : 0;
2411}
2412
2413constexpr QMetaType::TypeFlags QMetaType::flags() const
2414{
2415 return d_ptr ? TypeFlags(d_ptr->flags) : TypeFlags{};
2416}
2417
2418constexpr const QMetaObject *QMetaType::metaObject() const
2419{
2420 return d_ptr ? d_ptr->metaObject : nullptr;
2421}
2422
2423template<typename... T>
2424constexpr const QtPrivate::QMetaTypeInterface *const qt_metaTypeArray[] = {
2425 QtPrivate::qMetaTypeInterfaceForType<T>()...
2426};
2427
2428constexpr const char *QMetaType::name() const
2429{
2430 return d_ptr ? d_ptr->name : nullptr;
2431}
2432
2433template<typename Unique,typename... T>
2434constexpr const QtPrivate::QMetaTypeInterface *const qt_incomplete_metaTypeArray[] = {
2435 QtPrivate::qTryMetaTypeInterfaceForType<Unique, T>()...
2436};
2437
2438QT_END_NAMESPACE
2439
2440#endif // QMETATYPE_H
2441