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#ifndef QT_NO_QOBJECT
50#include <QtCore/qobjectdefs.h>
51#endif
52#include <new>
53
54#include <vector>
55#include <list>
56#include <map>
57
58#ifdef Bool
59#error qmetatype.h must be included before any header file that defines Bool
60#endif
61
62QT_BEGIN_NAMESPACE
63
64// from qcborcommon.h
65enum class QCborSimpleType : quint8;
66
67template <typename T>
68struct QMetaTypeId2;
69
70template <typename T>
71inline Q_DECL_CONSTEXPR int qMetaTypeId();
72
73// F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, RealType)
74// ### Qt6: reorder the types to match the C++ integral type ranking
75#define QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
76 F(Void, 43, void) \
77 F(Bool, 1, bool) \
78 F(Int, 2, int) \
79 F(UInt, 3, uint) \
80 F(LongLong, 4, qlonglong) \
81 F(ULongLong, 5, qulonglong) \
82 F(Double, 6, double) \
83 F(Long, 32, long) \
84 F(Short, 33, short) \
85 F(Char, 34, char) \
86 F(ULong, 35, ulong) \
87 F(UShort, 36, ushort) \
88 F(UChar, 37, uchar) \
89 F(Float, 38, float) \
90 F(SChar, 40, signed char) \
91 F(Nullptr, 51, std::nullptr_t) \
92 F(QCborSimpleType, 52, QCborSimpleType) \
93
94#define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\
95 F(VoidStar, 31, void*) \
96
97#if QT_CONFIG(itemmodel)
98#define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)\
99 F(QModelIndex, 42, QModelIndex) \
100 F(QPersistentModelIndex, 50, QPersistentModelIndex)
101#else
102#define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(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(QStringList, 11, QStringList) \
109 F(QByteArray, 12, QByteArray) \
110 F(QBitArray, 13, QBitArray) \
111 F(QDate, 14, QDate) \
112 F(QTime, 15, QTime) \
113 F(QDateTime, 16, QDateTime) \
114 F(QUrl, 17, QUrl) \
115 F(QLocale, 18, QLocale) \
116 F(QRect, 19, QRect) \
117 F(QRectF, 20, QRectF) \
118 F(QSize, 21, QSize) \
119 F(QSizeF, 22, QSizeF) \
120 F(QLine, 23, QLine) \
121 F(QLineF, 24, QLineF) \
122 F(QPoint, 25, QPoint) \
123 F(QPointF, 26, QPointF) \
124 F(QRegExp, 27, QRegExp) \
125 F(QEasingCurve, 29, QEasingCurve) \
126 F(QUuid, 30, QUuid) \
127 F(QVariant, 41, QVariant) \
128 F(QRegularExpression, 44, QRegularExpression) \
129 F(QJsonValue, 45, QJsonValue) \
130 F(QJsonObject, 46, QJsonObject) \
131 F(QJsonArray, 47, QJsonArray) \
132 F(QJsonDocument, 48, QJsonDocument) \
133 F(QCborValue, 53, QCborValue) \
134 F(QCborArray, 54, QCborArray) \
135 F(QCborMap, 55, QCborMap) \
136 QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
137
138#define QT_FOR_EACH_STATIC_CORE_POINTER(F)\
139 F(QObjectStar, 39, QObject*)
140
141#define QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)\
142 F(QVariantMap, 8, QVariantMap) \
143 F(QVariantList, 9, QVariantList) \
144 F(QVariantHash, 28, QVariantHash) \
145 F(QByteArrayList, 49, QByteArrayList) \
146
147#define QT_FOR_EACH_STATIC_GUI_CLASS(F)\
148 F(QFont, 64, QFont) \
149 F(QPixmap, 65, QPixmap) \
150 F(QBrush, 66, QBrush) \
151 F(QColor, 67, QColor) \
152 F(QPalette, 68, QPalette) \
153 F(QIcon, 69, QIcon) \
154 F(QImage, 70, QImage) \
155 F(QPolygon, 71, QPolygon) \
156 F(QRegion, 72, QRegion) \
157 F(QBitmap, 73, QBitmap) \
158 F(QCursor, 74, QCursor) \
159 F(QKeySequence, 75, QKeySequence) \
160 F(QPen, 76, QPen) \
161 F(QTextLength, 77, QTextLength) \
162 F(QTextFormat, 78, QTextFormat) \
163 F(QMatrix, 79, QMatrix) \
164 F(QTransform, 80, QTransform) \
165 F(QMatrix4x4, 81, QMatrix4x4) \
166 F(QVector2D, 82, QVector2D) \
167 F(QVector3D, 83, QVector3D) \
168 F(QVector4D, 84, QVector4D) \
169 F(QQuaternion, 85, QQuaternion) \
170 F(QPolygonF, 86, QPolygonF) \
171
172
173#define QT_FOR_EACH_STATIC_WIDGETS_CLASS(F)\
174 F(QSizePolicy, 121, QSizePolicy) \
175
176// ### FIXME kill that set
177#define QT_FOR_EACH_STATIC_HACKS_TYPE(F)\
178 F(QMetaTypeId2<qreal>::MetaType, -1, qreal)
179
180// F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, AliasingType, "RealType")
181#define QT_FOR_EACH_STATIC_ALIAS_TYPE(F)\
182 F(ULong, -1, ulong, "unsigned long") \
183 F(UInt, -1, uint, "unsigned int") \
184 F(UShort, -1, ushort, "unsigned short") \
185 F(UChar, -1, uchar, "unsigned char") \
186 F(LongLong, -1, qlonglong, "long long") \
187 F(ULongLong, -1, qulonglong, "unsigned long long") \
188 F(SChar, -1, signed char, "qint8") \
189 F(UChar, -1, uchar, "quint8") \
190 F(Short, -1, short, "qint16") \
191 F(UShort, -1, ushort, "quint16") \
192 F(Int, -1, int, "qint32") \
193 F(UInt, -1, uint, "quint32") \
194 F(LongLong, -1, qlonglong, "qint64") \
195 F(ULongLong, -1, qulonglong, "quint64") \
196 F(QVariantList, -1, QVariantList, "QList<QVariant>") \
197 F(QVariantMap, -1, QVariantMap, "QMap<QString,QVariant>") \
198 F(QVariantHash, -1, QVariantHash, "QHash<QString,QVariant>") \
199 F(QByteArrayList, -1, QByteArrayList, "QList<QByteArray>") \
200
201#define QT_FOR_EACH_STATIC_TYPE(F)\
202 QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
203 QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\
204 QT_FOR_EACH_STATIC_CORE_CLASS(F)\
205 QT_FOR_EACH_STATIC_CORE_POINTER(F)\
206 QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)\
207 QT_FOR_EACH_STATIC_GUI_CLASS(F)\
208 QT_FOR_EACH_STATIC_WIDGETS_CLASS(F)\
209
210#define QT_DEFINE_METATYPE_ID(TypeName, Id, Name) \
211 TypeName = Id,
212
213#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(F) \
214 F(QList) \
215 F(QVector) \
216 F(QQueue) \
217 F(QStack) \
218 F(QSet) \
219 F(QLinkedList)
220
221#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(F) \
222 F(QHash, class) \
223 F(QMap, class) \
224 F(QPair, struct)
225
226#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(F) \
227 F(QSharedPointer) \
228 F(QWeakPointer) \
229 F(QPointer)
230
231class QDataStream;
232class QMetaTypeInterface;
233struct QMetaObject;
234
235namespace QtPrivate
236{
237/*!
238 This template is used for implicit conversion from type From to type To.
239 \internal
240*/
241template<typename From, typename To>
242To convertImplicit(const From& from)
243{
244 return from;
245}
246
247#ifndef QT_NO_DEBUG_STREAM
248struct AbstractDebugStreamFunction
249{
250 typedef void (*Stream)(const AbstractDebugStreamFunction *, QDebug&, const void *);
251 typedef void (*Destroy)(AbstractDebugStreamFunction *);
252 explicit AbstractDebugStreamFunction(Stream s = nullptr, Destroy d = nullptr)
253 : stream(s), destroy(d) {}
254 Q_DISABLE_COPY(AbstractDebugStreamFunction)
255 Stream stream;
256 Destroy destroy;
257};
258
259template<typename T>
260struct BuiltInDebugStreamFunction : public AbstractDebugStreamFunction
261{
262 BuiltInDebugStreamFunction()
263 : AbstractDebugStreamFunction(stream, destroy) {}
264 static void stream(const AbstractDebugStreamFunction *, QDebug& dbg, const void *r)
265 {
266 const T *rhs = static_cast<const T *>(r);
267 operator<<(dbg, *rhs);
268 }
269
270 static void destroy(AbstractDebugStreamFunction *_this)
271 {
272 delete static_cast<BuiltInDebugStreamFunction *>(_this);
273 }
274};
275#endif
276
277struct AbstractComparatorFunction
278{
279 typedef bool (*LessThan)(const AbstractComparatorFunction *, const void *, const void *);
280 typedef bool (*Equals)(const AbstractComparatorFunction *, const void *, const void *);
281 typedef void (*Destroy)(AbstractComparatorFunction *);
282 explicit AbstractComparatorFunction(LessThan lt = nullptr, Equals e = nullptr, Destroy d = nullptr)
283 : lessThan(lt), equals(e), destroy(d) {}
284 Q_DISABLE_COPY(AbstractComparatorFunction)
285 LessThan lessThan;
286 Equals equals;
287 Destroy destroy;
288};
289
290template<typename T>
291struct BuiltInComparatorFunction : public AbstractComparatorFunction
292{
293 BuiltInComparatorFunction()
294 : AbstractComparatorFunction(lessThan, equals, destroy) {}
295 static bool lessThan(const AbstractComparatorFunction *, const void *l, const void *r)
296 {
297 const T *lhs = static_cast<const T *>(l);
298 const T *rhs = static_cast<const T *>(r);
299 return *lhs < *rhs;
300 }
301
302 static bool equals(const AbstractComparatorFunction *, const void *l, const void *r)
303 {
304 const T *lhs = static_cast<const T *>(l);
305 const T *rhs = static_cast<const T *>(r);
306 return *lhs == *rhs;
307 }
308
309 static void destroy(AbstractComparatorFunction *_this)
310 {
311 delete static_cast<BuiltInComparatorFunction *>(_this);
312 }
313};
314
315template<typename T>
316struct BuiltInEqualsComparatorFunction : public AbstractComparatorFunction
317{
318 BuiltInEqualsComparatorFunction()
319 : AbstractComparatorFunction(nullptr, equals, destroy) {}
320 static bool equals(const AbstractComparatorFunction *, const void *l, const void *r)
321 {
322 const T *lhs = static_cast<const T *>(l);
323 const T *rhs = static_cast<const T *>(r);
324 return *lhs == *rhs;
325 }
326
327 static void destroy(AbstractComparatorFunction *_this)
328 {
329 delete static_cast<BuiltInEqualsComparatorFunction *>(_this);
330 }
331};
332
333struct AbstractConverterFunction
334{
335 typedef bool (*Converter)(const AbstractConverterFunction *, const void *, void*);
336 explicit AbstractConverterFunction(Converter c = nullptr)
337 : convert(c) {}
338 Q_DISABLE_COPY(AbstractConverterFunction)
339 Converter convert;
340};
341
342template<typename From, typename To>
343struct ConverterMemberFunction : public AbstractConverterFunction
344{
345 explicit ConverterMemberFunction(To(From::*function)() const)
346 : AbstractConverterFunction(convert),
347 m_function(function) {}
348 ~ConverterMemberFunction();
349 static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
350 {
351 const From *f = static_cast<const From *>(in);
352 To *t = static_cast<To *>(out);
353 const ConverterMemberFunction *_typedThis =
354 static_cast<const ConverterMemberFunction *>(_this);
355 *t = (f->*_typedThis->m_function)();
356 return true;
357 }
358
359 To(From::* const m_function)() const;
360};
361
362template<typename From, typename To>
363struct ConverterMemberFunctionOk : public AbstractConverterFunction
364{
365 explicit ConverterMemberFunctionOk(To(From::*function)(bool *) const)
366 : AbstractConverterFunction(convert),
367 m_function(function) {}
368 ~ConverterMemberFunctionOk();
369 static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
370 {
371 const From *f = static_cast<const From *>(in);
372 To *t = static_cast<To *>(out);
373 bool ok = false;
374 const ConverterMemberFunctionOk *_typedThis =
375 static_cast<const ConverterMemberFunctionOk *>(_this);
376 *t = (f->*_typedThis->m_function)(&ok);
377 if (!ok)
378 *t = To();
379 return ok;
380 }
381
382 To(From::* const m_function)(bool*) const;
383};
384
385template<typename From, typename To, typename UnaryFunction>
386struct ConverterFunctor : public AbstractConverterFunction
387{
388 explicit ConverterFunctor(UnaryFunction function)
389 : AbstractConverterFunction(convert),
390 m_function(function) {}
391 ~ConverterFunctor();
392 static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
393 {
394 const From *f = static_cast<const From *>(in);
395 To *t = static_cast<To *>(out);
396 const ConverterFunctor *_typedThis =
397 static_cast<const ConverterFunctor *>(_this);
398 *t = _typedThis->m_function(*f);
399 return true;
400 }
401
402 UnaryFunction m_function;
403};
404
405 template<typename T, bool>
406 struct ValueTypeIsMetaType;
407 template<typename T, bool>
408 struct AssociativeValueTypeIsMetaType;
409 template<typename T, bool>
410 struct IsMetaTypePair;
411 template<typename, typename>
412 struct MetaTypeSmartPointerHelper;
413}
414
415class Q_CORE_EXPORT QMetaType {
416 enum ExtensionFlag { NoExtensionFlags,
417 CreateEx = 0x1, DestroyEx = 0x2,
418 ConstructEx = 0x4, DestructEx = 0x8,
419 NameEx = 0x10, SizeEx = 0x20,
420 CtorEx = 0x40, DtorEx = 0x80,
421 FlagsEx = 0x100, MetaObjectEx = 0x200
422 };
423public:
424#ifndef Q_CLANG_QDOC
425 // The code that actually gets compiled.
426 enum Type {
427 // these are merged with QVariant
428 QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID)
429
430 FirstCoreType = Bool,
431 LastCoreType = QCborMap,
432 FirstGuiType = QFont,
433 LastGuiType = QPolygonF,
434 FirstWidgetsType = QSizePolicy,
435 LastWidgetsType = QSizePolicy,
436 HighestInternalId = LastWidgetsType,
437
438 QReal = sizeof(qreal) == sizeof(double) ? Double : Float,
439
440 UnknownType = 0,
441 User = 1024
442 };
443#else
444 // If we are using QDoc it fakes the Type enum looks like this.
445 enum Type {
446 UnknownType = 0, Bool = 1, Int = 2, UInt = 3, LongLong = 4, ULongLong = 5,
447 Double = 6, Long = 32, Short = 33, Char = 34, ULong = 35, UShort = 36,
448 UChar = 37, Float = 38,
449 VoidStar = 31,
450 QChar = 7, QString = 10, QStringList = 11, QByteArray = 12,
451 QBitArray = 13, QDate = 14, QTime = 15, QDateTime = 16, QUrl = 17,
452 QLocale = 18, QRect = 19, QRectF = 20, QSize = 21, QSizeF = 22,
453 QLine = 23, QLineF = 24, QPoint = 25, QPointF = 26, QRegExp = 27,
454 QEasingCurve = 29, QUuid = 30, QVariant = 41, QModelIndex = 42,
455 QPersistentModelIndex = 50, QRegularExpression = 44,
456 QJsonValue = 45, QJsonObject = 46, QJsonArray = 47, QJsonDocument = 48,
457 QByteArrayList = 49, QObjectStar = 39, SChar = 40,
458 Void = 43,
459 Nullptr = 51,
460 QVariantMap = 8, QVariantList = 9, QVariantHash = 28,
461 QCborSimpleType = 52, QCborValue = 53, QCborArray = 54, QCborMap = 55,
462
463 // Gui types
464 QFont = 64, QPixmap = 65, QBrush = 66, QColor = 67, QPalette = 68,
465 QIcon = 69, QImage = 70, QPolygon = 71, QRegion = 72, QBitmap = 73,
466 QCursor = 74, QKeySequence = 75, QPen = 76, QTextLength = 77, QTextFormat = 78,
467 QMatrix = 79, QTransform = 80, QMatrix4x4 = 81, QVector2D = 82,
468 QVector3D = 83, QVector4D = 84, QQuaternion = 85, QPolygonF = 86,
469
470 // Widget types
471 QSizePolicy = 121,
472 LastCoreType = QCborMap,
473 LastGuiType = QPolygonF,
474 User = 1024
475 };
476#endif
477
478 enum TypeFlag {
479 NeedsConstruction = 0x1,
480 NeedsDestruction = 0x2,
481 MovableType = 0x4,
482 PointerToQObject = 0x8,
483 IsEnumeration = 0x10,
484 SharedPointerToQObject = 0x20,
485 WeakPointerToQObject = 0x40,
486 TrackingPointerToQObject = 0x80,
487 WasDeclaredAsMetaType = 0x100,
488 IsGadget = 0x200,
489 PointerToGadget = 0x400
490 };
491 Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
492
493 typedef void (*Deleter)(void *);
494 typedef void *(*Creator)(const void *);
495
496#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
497 typedef void (*Destructor)(void *);
498 typedef void *(*Constructor)(void *, const void *); // TODO Qt6: remove me
499#endif
500 typedef void (*TypedDestructor)(int, void *);
501 typedef void *(*TypedConstructor)(int, void *, const void *);
502
503 typedef void (*SaveOperator)(QDataStream &, const void *);
504 typedef void (*LoadOperator)(QDataStream &, void *);
505#ifndef QT_NO_DATASTREAM
506 static void registerStreamOperators(const char *typeName, SaveOperator saveOp,
507 LoadOperator loadOp);
508 static void registerStreamOperators(int type, SaveOperator saveOp,
509 LoadOperator loadOp);
510#endif
511 static int registerType(const char *typeName, Deleter deleter,
512 Creator creator);
513 static int registerType(const char *typeName, Deleter deleter,
514 Creator creator,
515 Destructor destructor,
516 Constructor constructor,
517 int size,
518 QMetaType::TypeFlags flags,
519 const QMetaObject *metaObject);
520 static int registerType(const char *typeName,
521 TypedDestructor destructor,
522 TypedConstructor constructor,
523 int size,
524 QMetaType::TypeFlags flags,
525 const QMetaObject *metaObject);
526 static bool unregisterType(int type);
527 static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, Deleter deleter,
528 Creator creator,
529 Destructor destructor,
530 Constructor constructor,
531 int size,
532 QMetaType::TypeFlags flags,
533 const QMetaObject *metaObject);
534 static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, Destructor destructor,
535 Constructor constructor,
536 int size,
537 QMetaType::TypeFlags flags,
538 const QMetaObject *metaObject);
539 static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, TypedDestructor destructor,
540 TypedConstructor constructor,
541 int size,
542 QMetaType::TypeFlags flags,
543 const QMetaObject *metaObject);
544 static int registerTypedef(const char *typeName, int aliasId);
545 static int registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, int aliasId);
546 static int type(const char *typeName);
547
548 static int type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName);
549 static const char *typeName(int type);
550 static int sizeOf(int type);
551 static TypeFlags typeFlags(int type);
552 static const QMetaObject *metaObjectForType(int type);
553 static bool isRegistered(int type);
554 static void *create(int type, const void *copy = nullptr);
555#if QT_DEPRECATED_SINCE(5, 0)
556 QT_DEPRECATED static void *construct(int type, const void *copy = nullptr)
557 { return create(type, copy); }
558#endif
559 static void destroy(int type, void *data);
560 static void *construct(int type, void *where, const void *copy);
561 static void destruct(int type, void *where);
562
563#ifndef QT_NO_DATASTREAM
564 static bool save(QDataStream &stream, int type, const void *data);
565 static bool load(QDataStream &stream, int type, void *data);
566#endif
567
568 explicit QMetaType(const int type); // ### Qt6: drop const
569 inline ~QMetaType();
570
571 inline bool isValid() const;
572 inline bool isRegistered() const;
573 inline int sizeOf() const;
574 inline TypeFlags flags() const;
575 inline const QMetaObject *metaObject() const;
576
577 inline void *create(const void *copy = nullptr) const;
578 inline void destroy(void *data) const;
579 inline void *construct(void *where, const void *copy = nullptr) const;
580 inline void destruct(void *data) const;
581
582public:
583 template<typename T>
584 static bool registerComparators()
585 {
586 Q_STATIC_ASSERT_X((!QMetaTypeId2<T>::IsBuiltIn),
587 "QMetaType::registerComparators: The type must be a custom type.");
588
589 const int typeId = qMetaTypeId<T>();
590 static const QtPrivate::BuiltInComparatorFunction<T> f;
591 return registerComparatorFunction( &f, typeId);
592 }
593 template<typename T>
594 static bool registerEqualsComparator()
595 {
596 Q_STATIC_ASSERT_X((!QMetaTypeId2<T>::IsBuiltIn),
597 "QMetaType::registerEqualsComparator: The type must be a custom type.");
598 const int typeId = qMetaTypeId<T>();
599 static const QtPrivate::BuiltInEqualsComparatorFunction<T> f;
600 return registerComparatorFunction( &f, typeId);
601 }
602
603 template<typename T>
604 static bool hasRegisteredComparators()
605 {
606 return hasRegisteredComparators(qMetaTypeId<T>());
607 }
608 static bool hasRegisteredComparators(int typeId);
609
610
611#ifndef QT_NO_DEBUG_STREAM
612 template<typename T>
613 static bool registerDebugStreamOperator()
614 {
615 Q_STATIC_ASSERT_X((!QMetaTypeId2<T>::IsBuiltIn),
616 "QMetaType::registerDebugStreamOperator: The type must be a custom type.");
617
618 const int typeId = qMetaTypeId<T>();
619 static const QtPrivate::BuiltInDebugStreamFunction<T> f;
620 return registerDebugStreamOperatorFunction(&f, typeId);
621 }
622 template<typename T>
623 static bool hasRegisteredDebugStreamOperator()
624 {
625 return hasRegisteredDebugStreamOperator(qMetaTypeId<T>());
626 }
627 static bool hasRegisteredDebugStreamOperator(int typeId);
628#endif
629
630 // implicit conversion supported like double -> float
631 template<typename From, typename To>
632 static bool registerConverter()
633 {
634 return registerConverter<From, To>(QtPrivate::convertImplicit<From, To>);
635 }
636
637#ifdef Q_CLANG_QDOC
638 template<typename MemberFunction, int>
639 static bool registerConverter(MemberFunction function);
640 template<typename MemberFunctionOk, char>
641 static bool registerConverter(MemberFunctionOk function);
642 template<typename UnaryFunction>
643 static bool registerConverter(UnaryFunction function);
644#else
645 // member function as in "QString QFont::toString() const"
646 template<typename From, typename To>
647 static bool registerConverter(To(From::*function)() const)
648 {
649 Q_STATIC_ASSERT_X((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
650 "QMetaType::registerConverter: At least one of the types must be a custom type.");
651
652 const int fromTypeId = qMetaTypeId<From>();
653 const int toTypeId = qMetaTypeId<To>();
654 static const QtPrivate::ConverterMemberFunction<From, To> f(function);
655 return registerConverterFunction(&f, fromTypeId, toTypeId);
656 }
657
658 // member function as in "double QString::toDouble(bool *ok = nullptr) const"
659 template<typename From, typename To>
660 static bool registerConverter(To(From::*function)(bool*) const)
661 {
662 Q_STATIC_ASSERT_X((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
663 "QMetaType::registerConverter: At least one of the types must be a custom type.");
664
665 const int fromTypeId = qMetaTypeId<From>();
666 const int toTypeId = qMetaTypeId<To>();
667 static const QtPrivate::ConverterMemberFunctionOk<From, To> f(function);
668 return registerConverterFunction(&f, fromTypeId, toTypeId);
669 }
670
671 // functor or function pointer
672 template<typename From, typename To, typename UnaryFunction>
673 static bool registerConverter(UnaryFunction function)
674 {
675 Q_STATIC_ASSERT_X((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
676 "QMetaType::registerConverter: At least one of the types must be a custom type.");
677
678 const int fromTypeId = qMetaTypeId<From>();
679 const int toTypeId = qMetaTypeId<To>();
680 static const QtPrivate::ConverterFunctor<From, To, UnaryFunction> f(function);
681 return registerConverterFunction(&f, fromTypeId, toTypeId);
682 }
683#endif
684
685 static bool convert(const void *from, int fromTypeId, void *to, int toTypeId);
686 static bool compare(const void *lhs, const void *rhs, int typeId, int* result);
687 static bool equals(const void *lhs, const void *rhs, int typeId, int* result);
688 static bool debugStream(QDebug& dbg, const void *rhs, int typeId);
689
690 template<typename From, typename To>
691 static bool hasRegisteredConverterFunction()
692 {
693 return hasRegisteredConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
694 }
695
696 static bool hasRegisteredConverterFunction(int fromTypeId, int toTypeId);
697
698private:
699 static QMetaType typeInfo(const int type);
700 inline QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
701 TypedConstructor creator,
702 TypedDestructor deleter,
703 SaveOperator saveOp,
704 LoadOperator loadOp,
705 Constructor constructor,
706 Destructor destructor,
707 uint sizeOf,
708 uint theTypeFlags,
709 int typeId,
710 const QMetaObject *metaObject);
711 QMetaType(const QMetaType &other);
712 QMetaType &operator =(const QMetaType &);
713 inline bool isExtended(const ExtensionFlag flag) const { return m_extensionFlags & flag; }
714
715 // Methods used for future binary compatible extensions
716 void ctor(const QMetaTypeInterface *info);
717 void dtor();
718 uint sizeExtended() const;
719 QMetaType::TypeFlags flagsExtended() const;
720 const QMetaObject *metaObjectExtended() const;
721 void *createExtended(const void *copy = nullptr) const;
722 void destroyExtended(void *data) const;
723 void *constructExtended(void *where, const void *copy = nullptr) const;
724 void destructExtended(void *data) const;
725
726 static bool registerComparatorFunction(const QtPrivate::AbstractComparatorFunction *f, int type);
727#ifndef QT_NO_DEBUG_STREAM
728 static bool registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f, int type);
729#endif
730
731// ### Qt6: FIXME: Remove the special Q_CC_MSVC handling, it was introduced to maintain BC.
732#if !defined(Q_NO_TEMPLATE_FRIENDS) && !defined(Q_CC_MSVC)
733#ifndef Q_CLANG_QDOC
734 template<typename, bool> friend struct QtPrivate::ValueTypeIsMetaType;
735 template<typename, typename> friend struct QtPrivate::ConverterMemberFunction;
736 template<typename, typename> friend struct QtPrivate::ConverterMemberFunctionOk;
737 template<typename, typename, typename> friend struct QtPrivate::ConverterFunctor;
738 template<typename, bool> friend struct QtPrivate::AssociativeValueTypeIsMetaType;
739 template<typename, bool> friend struct QtPrivate::IsMetaTypePair;
740 template<typename, typename> friend struct QtPrivate::MetaTypeSmartPointerHelper;
741#endif
742#else
743public:
744#endif
745 static bool registerConverterFunction(const QtPrivate::AbstractConverterFunction *f, int from, int to);
746 static void unregisterConverterFunction(int from, int to);
747private:
748
749 TypedConstructor m_typedConstructor;
750 TypedDestructor m_typedDestructor;
751 SaveOperator m_saveOp;
752 LoadOperator m_loadOp;
753 Constructor m_constructor;
754 Destructor m_destructor;
755 void *m_extension; // space reserved for future use
756 uint m_size;
757 uint m_typeFlags;
758 uint m_extensionFlags;
759 int m_typeId;
760 const QMetaObject *m_metaObject;
761};
762
763#undef QT_DEFINE_METATYPE_ID
764
765Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags)
766
767namespace QtPrivate {
768
769template<typename From, typename To>
770ConverterMemberFunction<From, To>::~ConverterMemberFunction()
771{
772 QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
773}
774template<typename From, typename To>
775ConverterMemberFunctionOk<From, To>::~ConverterMemberFunctionOk()
776{
777 QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
778}
779template<typename From, typename To, typename UnaryFunction>
780ConverterFunctor<From, To, UnaryFunction>::~ConverterFunctor()
781{
782 QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
783}
784
785}
786
787#define QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(C, F) \
788 } \
789 Q_DECLARE_TYPEINFO(QtMetaTypePrivate:: C, (F)); \
790 namespace QtMetaTypePrivate {
791
792namespace QtMetaTypePrivate {
793template <typename T, bool Accepted = true>
794struct QMetaTypeFunctionHelper {
795 static void Destruct(void *t)
796 {
797 Q_UNUSED(t) // Silence MSVC that warns for POD types.
798 static_cast<T*>(t)->~T();
799 }
800
801 static void *Construct(void *where, const void *t)
802 {
803 if (t)
804 return new (where) T(*static_cast<const T*>(t));
805 return new (where) T;
806 }
807#ifndef QT_NO_DATASTREAM
808 static void Save(QDataStream &stream, const void *t)
809 {
810 stream << *static_cast<const T*>(t);
811 }
812
813 static void Load(QDataStream &stream, void *t)
814 {
815 stream >> *static_cast<T*>(t);
816 }
817#endif // QT_NO_DATASTREAM
818};
819
820template <typename T>
821struct QMetaTypeFunctionHelper<T, /* Accepted */ false> {
822 static void Destruct(void *) {}
823 static void *Construct(void *, const void *) { return nullptr; }
824#ifndef QT_NO_DATASTREAM
825 static void Save(QDataStream &, const void *) {}
826 static void Load(QDataStream &, void *) {}
827#endif // QT_NO_DATASTREAM
828};
829template <>
830struct QMetaTypeFunctionHelper<void, /* Accepted */ true>
831 : public QMetaTypeFunctionHelper<void, /* Accepted */ false>
832{};
833
834struct VariantData
835{
836 VariantData(const int metaTypeId_,
837 const void *data_,
838 const uint flags_)
839 : metaTypeId(metaTypeId_)
840 , data(data_)
841 , flags(flags_)
842 {
843 }
844 VariantData(const VariantData &other)
845 : metaTypeId(other.metaTypeId), data(other.data), flags(other.flags){}
846 const int metaTypeId;
847 const void *data;
848 const uint flags;
849private:
850 // copy constructor allowed to be implicit to silence level 4 warning from MSVC
851 VariantData &operator=(const VariantData &) Q_DECL_EQ_DELETE;
852};
853
854template<typename const_iterator>
855struct IteratorOwnerCommon
856{
857 static void assign(void **ptr, const_iterator iterator)
858 {
859 *ptr = new const_iterator(iterator);
860 }
861 static void assign(void **ptr, void * const * src)
862 {
863 *ptr = new const_iterator(*static_cast<const_iterator*>(*src));
864 }
865
866 static void advance(void **iterator, int step)
867 {
868 const_iterator &it = *static_cast<const_iterator*>(*iterator);
869 std::advance(it, step);
870 }
871
872 static void destroy(void **ptr)
873 {
874 delete static_cast<const_iterator*>(*ptr);
875 }
876
877 static bool equal(void * const *it, void * const *other)
878 {
879 return *static_cast<const_iterator*>(*it) == *static_cast<const_iterator*>(*other);
880 }
881};
882
883template<typename const_iterator>
884struct IteratorOwner : IteratorOwnerCommon<const_iterator>
885{
886 static const void *getData(void * const *iterator)
887 {
888 return &**static_cast<const_iterator*>(*iterator);
889 }
890
891 static const void *getData(const_iterator it)
892 {
893 return &*it;
894 }
895};
896
897struct Q_CORE_EXPORT VectorBoolElements
898{
899 static const bool true_element;
900 static const bool false_element;
901};
902
903template<>
904struct IteratorOwner<std::vector<bool>::const_iterator> : IteratorOwnerCommon<std::vector<bool>::const_iterator>
905{
906public:
907 static const void *getData(void * const *iterator)
908 {
909 return **static_cast<std::vector<bool>::const_iterator*>(*iterator) ?
910 &VectorBoolElements::true_element : &VectorBoolElements::false_element;
911 }
912
913 static const void *getData(const std::vector<bool>::const_iterator& it)
914 {
915 return *it ? &VectorBoolElements::true_element : &VectorBoolElements::false_element;
916 }
917};
918
919template<typename value_type>
920struct IteratorOwner<const value_type*>
921{
922private:
923 // We need to disable typed overloads of assign() and getData() if the value_type
924 // is void* to avoid overloads conflicts. We do it by injecting unaccessible Dummy
925 // type as part of the overload signature.
926 struct Dummy {};
927 typedef typename std::conditional<std::is_same<value_type, void*>::value, Dummy, value_type>::type value_type_OR_Dummy;
928public:
929 static void assign(void **ptr, const value_type_OR_Dummy *iterator )
930 {
931 *ptr = const_cast<value_type*>(iterator);
932 }
933 static void assign(void **ptr, void * const * src)
934 {
935 *ptr = static_cast<value_type*>(*src);
936 }
937
938 static void advance(void **iterator, int step)
939 {
940 value_type *it = static_cast<value_type*>(*iterator);
941 std::advance(it, step);
942 *iterator = it;
943 }
944
945 static void destroy(void **)
946 {
947 }
948
949 static const void *getData(void * const *iterator)
950 {
951 return *iterator;
952 }
953
954 static const void *getData(const value_type_OR_Dummy *it)
955 {
956 return it;
957 }
958
959 static bool equal(void * const *it, void * const *other)
960 {
961 return static_cast<value_type*>(*it) == static_cast<value_type*>(*other);
962 }
963};
964
965enum IteratorCapability
966{
967 ForwardCapability = 1,
968 BiDirectionalCapability = 2,
969 RandomAccessCapability = 4
970};
971
972template<typename T, typename Category = typename std::iterator_traits<typename T::const_iterator>::iterator_category>
973struct CapabilitiesImpl;
974
975template<typename T>
976struct CapabilitiesImpl<T, std::forward_iterator_tag>
977{ enum { IteratorCapabilities = ForwardCapability }; };
978template<typename T>
979struct CapabilitiesImpl<T, std::bidirectional_iterator_tag>
980{ enum { IteratorCapabilities = BiDirectionalCapability | ForwardCapability }; };
981template<typename T>
982struct CapabilitiesImpl<T, std::random_access_iterator_tag>
983{ enum { IteratorCapabilities = RandomAccessCapability | BiDirectionalCapability | ForwardCapability }; };
984
985template<typename T>
986struct ContainerAPI : CapabilitiesImpl<T>
987{
988 static int size(const T *t) { return int(std::distance(t->begin(), t->end())); }
989};
990
991template<typename T>
992struct ContainerAPI<QList<T> > : CapabilitiesImpl<QList<T> >
993{ static int size(const QList<T> *t) { return t->size(); } };
994
995template<typename T>
996struct ContainerAPI<QVector<T> > : CapabilitiesImpl<QVector<T> >
997{ static int size(const QVector<T> *t) { return t->size(); } };
998
999template<typename T>
1000struct ContainerAPI<std::vector<T> > : CapabilitiesImpl<std::vector<T> >
1001{ static int size(const std::vector<T> *t) { return int(t->size()); } };
1002
1003template<typename T>
1004struct ContainerAPI<std::list<T> > : CapabilitiesImpl<std::list<T> >
1005{ static int size(const std::list<T> *t) { return int(t->size()); } };
1006
1007class QSequentialIterableImpl
1008{
1009public:
1010 const void * _iterable;
1011 void *_iterator;
1012 int _metaType_id;
1013 uint _metaType_flags;
1014 uint _iteratorCapabilities;
1015 typedef int(*sizeFunc)(const void *p);
1016 typedef const void * (*atFunc)(const void *p, int);
1017 typedef void (*moveIteratorFunc)(const void *p, void **);
1018 typedef void (*advanceFunc)(void **p, int);
1019 typedef VariantData (*getFunc)( void * const *p, int metaTypeId, uint flags);
1020 typedef void (*destroyIterFunc)(void **p);
1021 typedef bool (*equalIterFunc)(void * const *p, void * const *other);
1022 typedef void (*copyIterFunc)(void **, void * const *);
1023
1024 sizeFunc _size;
1025 atFunc _at;
1026 moveIteratorFunc _moveToBegin;
1027 moveIteratorFunc _moveToEnd;
1028 advanceFunc _advance;
1029 getFunc _get;
1030 destroyIterFunc _destroyIter;
1031 equalIterFunc _equalIter;
1032 copyIterFunc _copyIter;
1033
1034 template<class T>
1035 static int sizeImpl(const void *p)
1036 { return ContainerAPI<T>::size(static_cast<const T*>(p)); }
1037
1038 template<class T>
1039 static const void* atImpl(const void *p, int idx)
1040 {
1041 typename T::const_iterator i = static_cast<const T*>(p)->begin();
1042 std::advance(i, idx);
1043 return IteratorOwner<typename T::const_iterator>::getData(i);
1044 }
1045
1046 template<class T>
1047 static void moveToBeginImpl(const void *container, void **iterator)
1048 { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->begin()); }
1049
1050 template<class T>
1051 static void moveToEndImpl(const void *container, void **iterator)
1052 { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->end()); }
1053
1054 template<class T>
1055 static VariantData getImpl(void * const *iterator, int metaTypeId, uint flags)
1056 { return VariantData(metaTypeId, IteratorOwner<typename T::const_iterator>::getData(iterator), flags); }
1057
1058public:
1059 template<class T> QSequentialIterableImpl(const T*p)
1060 : _iterable(p)
1061 , _iterator(nullptr)
1062 , _metaType_id(qMetaTypeId<typename T::value_type>())
1063 , _metaType_flags(QTypeInfo<typename T::value_type>::isPointer)
1064 , _iteratorCapabilities(ContainerAPI<T>::IteratorCapabilities)
1065 , _size(sizeImpl<T>)
1066 , _at(atImpl<T>)
1067 , _moveToBegin(moveToBeginImpl<T>)
1068 , _moveToEnd(moveToEndImpl<T>)
1069 , _advance(IteratorOwner<typename T::const_iterator>::advance)
1070 , _get(getImpl<T>)
1071 , _destroyIter(IteratorOwner<typename T::const_iterator>::destroy)
1072 , _equalIter(IteratorOwner<typename T::const_iterator>::equal)
1073 , _copyIter(IteratorOwner<typename T::const_iterator>::assign)
1074 {
1075 }
1076
1077 QSequentialIterableImpl()
1078 : _iterable(nullptr)
1079 , _iterator(nullptr)
1080 , _metaType_id(QMetaType::UnknownType)
1081 , _metaType_flags(0)
1082 , _iteratorCapabilities(0)
1083 , _size(nullptr)
1084 , _at(nullptr)
1085 , _moveToBegin(nullptr)
1086 , _moveToEnd(nullptr)
1087 , _advance(nullptr)
1088 , _get(nullptr)
1089 , _destroyIter(nullptr)
1090 , _equalIter(nullptr)
1091 , _copyIter(nullptr)
1092 {
1093 }
1094
1095 inline void moveToBegin() { _moveToBegin(_iterable, &_iterator); }
1096 inline void moveToEnd() { _moveToEnd(_iterable, &_iterator); }
1097 inline bool equal(const QSequentialIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); }
1098 inline QSequentialIterableImpl &advance(int i) {
1099 Q_ASSERT(i > 0 || _iteratorCapabilities & BiDirectionalCapability);
1100 _advance(&_iterator, i);
1101 return *this;
1102 }
1103
1104 inline VariantData getCurrent() const { return _get(&_iterator, _metaType_id, _metaType_flags); }
1105
1106 VariantData at(int idx) const
1107 { return VariantData(_metaType_id, _at(_iterable, idx), _metaType_flags); }
1108
1109 int size() const { Q_ASSERT(_iterable); return _size(_iterable); }
1110
1111 inline void destroyIter() { _destroyIter(&_iterator); }
1112
1113 void copy(const QSequentialIterableImpl &other)
1114 {
1115 *this = other;
1116 _copyIter(&_iterator, &other._iterator);
1117 }
1118};
1119QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QSequentialIterableImpl, Q_MOVABLE_TYPE)
1120
1121template<typename From>
1122struct QSequentialIterableConvertFunctor
1123{
1124 QSequentialIterableImpl operator()(const From &f) const
1125 {
1126 return QSequentialIterableImpl(&f);
1127 }
1128};
1129}
1130
1131namespace QtMetaTypePrivate {
1132template<typename T, bool = std::is_same<typename T::const_iterator::value_type, typename T::mapped_type>::value>
1133struct AssociativeContainerAccessor
1134{
1135 static const typename T::key_type& getKey(const typename T::const_iterator &it)
1136 {
1137 return it.key();
1138 }
1139
1140 static const typename T::mapped_type& getValue(const typename T::const_iterator &it)
1141 {
1142 return it.value();
1143 }
1144};
1145
1146template<typename T, bool = std::is_same<typename T::const_iterator::value_type, std::pair<const typename T::key_type, typename T::mapped_type> >::value>
1147struct StlStyleAssociativeContainerAccessor;
1148
1149template<typename T>
1150struct StlStyleAssociativeContainerAccessor<T, true>
1151{
1152 static const typename T::key_type& getKey(const typename T::const_iterator &it)
1153 {
1154 return it->first;
1155 }
1156
1157 static const typename T::mapped_type& getValue(const typename T::const_iterator &it)
1158 {
1159 return it->second;
1160 }
1161};
1162
1163template<typename T>
1164struct AssociativeContainerAccessor<T, false> : public StlStyleAssociativeContainerAccessor<T>
1165{
1166};
1167
1168class QAssociativeIterableImpl
1169{
1170public:
1171 const void *_iterable;
1172 void *_iterator;
1173 int _metaType_id_key;
1174 uint _metaType_flags_key;
1175 int _metaType_id_value;
1176 uint _metaType_flags_value;
1177 typedef int(*sizeFunc)(const void *p);
1178 typedef void (*findFunc)(const void *container, const void *p, void **iterator);
1179 typedef void (*beginFunc)(const void *p, void **);
1180 typedef void (*advanceFunc)(void **p, int);
1181 typedef VariantData (*getFunc)(void * const *p, int metaTypeId, uint flags);
1182 typedef void (*destroyIterFunc)(void **p);
1183 typedef bool (*equalIterFunc)(void * const *p, void * const *other);
1184 typedef void (*copyIterFunc)(void **, void * const *);
1185
1186 sizeFunc _size;
1187 findFunc _find;
1188 beginFunc _begin;
1189 beginFunc _end;
1190 advanceFunc _advance;
1191 getFunc _getKey;
1192 getFunc _getValue;
1193 destroyIterFunc _destroyIter;
1194 equalIterFunc _equalIter;
1195 copyIterFunc _copyIter;
1196
1197 template<class T>
1198 static int sizeImpl(const void *p)
1199 { return int(std::distance(static_cast<const T*>(p)->begin(),
1200 static_cast<const T*>(p)->end())); }
1201
1202 template<class T>
1203 static void findImpl(const void *container, const void *p, void **iterator)
1204 { IteratorOwner<typename T::const_iterator>::assign(iterator,
1205 static_cast<const T*>(container)->find(*static_cast<const typename T::key_type*>(p))); }
1206
1207 template<class T>
1208 static void advanceImpl(void **p, int step)
1209 { std::advance(*static_cast<typename T::const_iterator*>(*p), step); }
1210
1211 template<class T>
1212 static void beginImpl(const void *container, void **iterator)
1213 { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->begin()); }
1214
1215 template<class T>
1216 static void endImpl(const void *container, void **iterator)
1217 { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->end()); }
1218
1219 template<class T>
1220 static VariantData getKeyImpl(void * const *iterator, int metaTypeId, uint flags)
1221 { return VariantData(metaTypeId, &AssociativeContainerAccessor<T>::getKey(*static_cast<typename T::const_iterator*>(*iterator)), flags); }
1222
1223 template<class T>
1224 static VariantData getValueImpl(void * const *iterator, int metaTypeId, uint flags)
1225 { return VariantData(metaTypeId, &AssociativeContainerAccessor<T>::getValue(*static_cast<typename T::const_iterator*>(*iterator)), flags); }
1226
1227public:
1228 template<class T> QAssociativeIterableImpl(const T*p)
1229 : _iterable(p)
1230 , _iterator(nullptr)
1231 , _metaType_id_key(qMetaTypeId<typename T::key_type>())
1232 , _metaType_flags_key(QTypeInfo<typename T::key_type>::isPointer)
1233 , _metaType_id_value(qMetaTypeId<typename T::mapped_type>())
1234 , _metaType_flags_value(QTypeInfo<typename T::mapped_type>::isPointer)
1235 , _size(sizeImpl<T>)
1236 , _find(findImpl<T>)
1237 , _begin(beginImpl<T>)
1238 , _end(endImpl<T>)
1239 , _advance(advanceImpl<T>)
1240 , _getKey(getKeyImpl<T>)
1241 , _getValue(getValueImpl<T>)
1242 , _destroyIter(IteratorOwner<typename T::const_iterator>::destroy)
1243 , _equalIter(IteratorOwner<typename T::const_iterator>::equal)
1244 , _copyIter(IteratorOwner<typename T::const_iterator>::assign)
1245 {
1246 }
1247
1248 QAssociativeIterableImpl()
1249 : _iterable(nullptr)
1250 , _iterator(nullptr)
1251 , _metaType_id_key(QMetaType::UnknownType)
1252 , _metaType_flags_key(0)
1253 , _metaType_id_value(QMetaType::UnknownType)
1254 , _metaType_flags_value(0)
1255 , _size(nullptr)
1256 , _find(nullptr)
1257 , _begin(nullptr)
1258 , _end(nullptr)
1259 , _advance(nullptr)
1260 , _getKey(nullptr)
1261 , _getValue(nullptr)
1262 , _destroyIter(nullptr)
1263 , _equalIter(nullptr)
1264 , _copyIter(nullptr)
1265 {
1266 }
1267
1268 inline void begin() { _begin(_iterable, &_iterator); }
1269 inline void end() { _end(_iterable, &_iterator); }
1270 inline bool equal(const QAssociativeIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); }
1271 inline QAssociativeIterableImpl &advance(int i) { _advance(&_iterator, i); return *this; }
1272
1273 inline void destroyIter() { _destroyIter(&_iterator); }
1274
1275 inline VariantData getCurrentKey() const { return _getKey(&_iterator, _metaType_id_key, _metaType_flags_key); }
1276 inline VariantData getCurrentValue() const { return _getValue(&_iterator, _metaType_id_value, _metaType_flags_value); }
1277
1278 inline void find(const VariantData &key)
1279 { _find(_iterable, key.data, &_iterator); }
1280
1281 int size() const { Q_ASSERT(_iterable); return _size(_iterable); }
1282
1283 void copy(const QAssociativeIterableImpl &other)
1284 {
1285 *this = other;
1286 _copyIter(&_iterator, &other._iterator);
1287 }
1288};
1289QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QAssociativeIterableImpl, Q_MOVABLE_TYPE)
1290
1291template<typename From>
1292struct QAssociativeIterableConvertFunctor
1293{
1294 QAssociativeIterableImpl operator()(const From& f) const
1295 {
1296 return QAssociativeIterableImpl(&f);
1297 }
1298};
1299
1300class QPairVariantInterfaceImpl
1301{
1302 const void *_pair;
1303 int _metaType_id_first;
1304 uint _metaType_flags_first;
1305 int _metaType_id_second;
1306 uint _metaType_flags_second;
1307
1308 typedef VariantData (*getFunc)(const void * const *p, int metaTypeId, uint flags);
1309
1310 getFunc _getFirst;
1311 getFunc _getSecond;
1312
1313 template<class T>
1314 static VariantData getFirstImpl(const void * const *pair, int metaTypeId, uint flags)
1315 { return VariantData(metaTypeId, &static_cast<const T*>(*pair)->first, flags); }
1316 template<class T>
1317 static VariantData getSecondImpl(const void * const *pair, int metaTypeId, uint flags)
1318 { return VariantData(metaTypeId, &static_cast<const T*>(*pair)->second, flags); }
1319
1320public:
1321 template<class T> QPairVariantInterfaceImpl(const T*p)
1322 : _pair(p)
1323 , _metaType_id_first(qMetaTypeId<typename T::first_type>())
1324 , _metaType_flags_first(QTypeInfo<typename T::first_type>::isPointer)
1325 , _metaType_id_second(qMetaTypeId<typename T::second_type>())
1326 , _metaType_flags_second(QTypeInfo<typename T::second_type>::isPointer)
1327 , _getFirst(getFirstImpl<T>)
1328 , _getSecond(getSecondImpl<T>)
1329 {
1330 }
1331
1332 QPairVariantInterfaceImpl()
1333 : _pair(nullptr)
1334 , _metaType_id_first(QMetaType::UnknownType)
1335 , _metaType_flags_first(0)
1336 , _metaType_id_second(QMetaType::UnknownType)
1337 , _metaType_flags_second(0)
1338 , _getFirst(nullptr)
1339 , _getSecond(nullptr)
1340 {
1341 }
1342
1343 inline VariantData first() const { return _getFirst(&_pair, _metaType_id_first, _metaType_flags_first); }
1344 inline VariantData second() const { return _getSecond(&_pair, _metaType_id_second, _metaType_flags_second); }
1345};
1346QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QPairVariantInterfaceImpl, Q_MOVABLE_TYPE)
1347
1348template<typename From>
1349struct QPairVariantInterfaceConvertFunctor;
1350
1351template<typename T, typename U>
1352struct QPairVariantInterfaceConvertFunctor<QPair<T, U> >
1353{
1354 QPairVariantInterfaceImpl operator()(const QPair<T, U>& f) const
1355 {
1356 return QPairVariantInterfaceImpl(&f);
1357 }
1358};
1359
1360template<typename T, typename U>
1361struct QPairVariantInterfaceConvertFunctor<std::pair<T, U> >
1362{
1363 QPairVariantInterfaceImpl operator()(const std::pair<T, U>& f) const
1364 {
1365 return QPairVariantInterfaceImpl(&f);
1366 }
1367};
1368
1369}
1370
1371class QObject;
1372class QWidget;
1373
1374#define QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER(Name) \
1375 template <class T> class Name; \
1376
1377QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER)
1378
1379namespace QtPrivate
1380{
1381 template<typename T>
1382 struct IsPointerToTypeDerivedFromQObject
1383 {
1384 enum { Value = false };
1385 };
1386
1387 // Specialize to avoid sizeof(void) warning
1388 template<>
1389 struct IsPointerToTypeDerivedFromQObject<void*>
1390 {
1391 enum { Value = false };
1392 };
1393 template<>
1394 struct IsPointerToTypeDerivedFromQObject<const void*>
1395 {
1396 enum { Value = false };
1397 };
1398 template<>
1399 struct IsPointerToTypeDerivedFromQObject<QObject*>
1400 {
1401 enum { Value = true };
1402 };
1403
1404 template<typename T>
1405 struct IsPointerToTypeDerivedFromQObject<T*>
1406 {
1407 typedef qint8 yes_type;
1408 typedef qint64 no_type;
1409
1410#ifndef QT_NO_QOBJECT
1411 static yes_type checkType(QObject* );
1412#endif
1413 static no_type checkType(...);
1414 Q_STATIC_ASSERT_X(sizeof(T), "Type argument of Q_DECLARE_METATYPE(T*) must be fully defined");
1415 enum { Value = sizeof(checkType(static_cast<T*>(nullptr))) == sizeof(yes_type) };
1416 };
1417
1418 template<typename T, typename Enable = void>
1419 struct IsGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; };
1420
1421 template<typename T>
1422 struct IsGadgetHelper<T, typename T::QtGadgetHelper>
1423 {
1424 template <typename X>
1425 static char checkType(void (X::*)());
1426 static void *checkType(void (T::*)());
1427 enum {
1428 IsRealGadget = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *),
1429 IsGadgetOrDerivedFrom = true
1430 };
1431 };
1432
1433 template<typename T, typename Enable = void>
1434 struct IsPointerToGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; };
1435
1436 template<typename T>
1437 struct IsPointerToGadgetHelper<T*, typename T::QtGadgetHelper>
1438 {
1439 using BaseType = T;
1440 template <typename X>
1441 static char checkType(void (X::*)());
1442 static void *checkType(void (T::*)());
1443 enum {
1444 IsRealGadget = !IsPointerToTypeDerivedFromQObject<T*>::Value && sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *),
1445 IsGadgetOrDerivedFrom = !IsPointerToTypeDerivedFromQObject<T*>::Value
1446 };
1447 };
1448
1449
1450 template<typename T> char qt_getEnumMetaObject(const T&);
1451
1452 template<typename T>
1453 struct IsQEnumHelper {
1454 static const T &declval();
1455 // If the type was declared with Q_ENUM, the friend qt_getEnumMetaObject() declared in the
1456 // Q_ENUM macro will be chosen by ADL, and the return type will be QMetaObject*.
1457 // Otherwise the chosen overload will be the catch all template function
1458 // qt_getEnumMetaObject(T) which returns 'char'
1459 enum { Value = sizeof(qt_getEnumMetaObject(declval())) == sizeof(QMetaObject*) };
1460 };
1461 template<> struct IsQEnumHelper<void> { enum { Value = false }; };
1462
1463 template<typename T, typename Enable = void>
1464 struct MetaObjectForType
1465 {
1466 static inline const QMetaObject *value() { return nullptr; }
1467 };
1468 template<>
1469 struct MetaObjectForType<void>
1470 {
1471 static inline const QMetaObject *value() { return nullptr; }
1472 };
1473 template<typename T>
1474 struct MetaObjectForType<T*, typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value>::type>
1475 {
1476 static inline const QMetaObject *value() { return &T::staticMetaObject; }
1477 };
1478 template<typename T>
1479 struct MetaObjectForType<T, typename std::enable_if<IsGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
1480 {
1481 static inline const QMetaObject *value() { return &T::staticMetaObject; }
1482 };
1483 template<typename T>
1484 struct MetaObjectForType<T, typename std::enable_if<IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
1485 {
1486 static inline const QMetaObject *value() { return &IsPointerToGadgetHelper<T>::BaseType::staticMetaObject; }
1487 };
1488 template<typename T>
1489 struct MetaObjectForType<T, typename std::enable_if<IsQEnumHelper<T>::Value>::type >
1490 {
1491 static inline const QMetaObject *value() { return qt_getEnumMetaObject(T()); }
1492 };
1493
1494 template<typename T>
1495 struct IsSharedPointerToTypeDerivedFromQObject
1496 {
1497 enum { Value = false };
1498 };
1499
1500 template<typename T>
1501 struct IsSharedPointerToTypeDerivedFromQObject<QSharedPointer<T> > : IsPointerToTypeDerivedFromQObject<T*>
1502 {
1503 };
1504
1505 template<typename T>
1506 struct IsWeakPointerToTypeDerivedFromQObject
1507 {
1508 enum { Value = false };
1509 };
1510
1511 template<typename T>
1512 struct IsWeakPointerToTypeDerivedFromQObject<QWeakPointer<T> > : IsPointerToTypeDerivedFromQObject<T*>
1513 {
1514 };
1515
1516 template<typename T>
1517 struct IsTrackingPointerToTypeDerivedFromQObject
1518 {
1519 enum { Value = false };
1520 };
1521
1522 template<typename T>
1523 struct IsTrackingPointerToTypeDerivedFromQObject<QPointer<T> >
1524 {
1525 enum { Value = true };
1526 };
1527
1528 template<typename T>
1529 struct IsSequentialContainer
1530 {
1531 enum { Value = false };
1532 };
1533
1534 template<typename T>
1535 struct IsAssociativeContainer
1536 {
1537 enum { Value = false };
1538 };
1539
1540 template<typename T, bool = QtPrivate::IsSequentialContainer<T>::Value>
1541 struct SequentialContainerConverterHelper
1542 {
1543 static bool registerConverter(int)
1544 {
1545 return false;
1546 }
1547 };
1548
1549 template<typename T, bool = QMetaTypeId2<typename T::value_type>::Defined>
1550 struct ValueTypeIsMetaType
1551 {
1552 static bool registerConverter(int)
1553 {
1554 return false;
1555 }
1556 };
1557
1558 template<typename T>
1559 struct SequentialContainerConverterHelper<T, true> : ValueTypeIsMetaType<T>
1560 {
1561 };
1562
1563 template<typename T, bool = QtPrivate::IsAssociativeContainer<T>::Value>
1564 struct AssociativeContainerConverterHelper
1565 {
1566 static bool registerConverter(int)
1567 {
1568 return false;
1569 }
1570 };
1571
1572 template<typename T, bool = QMetaTypeId2<typename T::mapped_type>::Defined>
1573 struct AssociativeValueTypeIsMetaType
1574 {
1575 static bool registerConverter(int)
1576 {
1577 return false;
1578 }
1579 };
1580
1581 template<typename T, bool = QMetaTypeId2<typename T::key_type>::Defined>
1582 struct KeyAndValueTypeIsMetaType
1583 {
1584 static bool registerConverter(int)
1585 {
1586 return false;
1587 }
1588 };
1589
1590 template<typename T>
1591 struct KeyAndValueTypeIsMetaType<T, true> : AssociativeValueTypeIsMetaType<T>
1592 {
1593 };
1594
1595 template<typename T>
1596 struct AssociativeContainerConverterHelper<T, true> : KeyAndValueTypeIsMetaType<T>
1597 {
1598 };
1599
1600 template<typename T, bool = QMetaTypeId2<typename T::first_type>::Defined
1601 && QMetaTypeId2<typename T::second_type>::Defined>
1602 struct IsMetaTypePair
1603 {
1604 static bool registerConverter(int)
1605 {
1606 return false;
1607 }
1608 };
1609
1610 template<typename T>
1611 struct IsMetaTypePair<T, true>
1612 {
1613 inline static bool registerConverter(int id);
1614 };
1615
1616 template<typename T>
1617 struct IsPair
1618 {
1619 static bool registerConverter(int)
1620 {
1621 return false;
1622 }
1623 };
1624 template<typename T, typename U>
1625 struct IsPair<QPair<T, U> > : IsMetaTypePair<QPair<T, U> > {};
1626 template<typename T, typename U>
1627 struct IsPair<std::pair<T, U> > : IsMetaTypePair<std::pair<T, U> > {};
1628
1629 template<typename T>
1630 struct MetaTypePairHelper : IsPair<T> {};
1631
1632 template<typename T, typename = void>
1633 struct MetaTypeSmartPointerHelper
1634 {
1635 static bool registerConverter(int) { return false; }
1636 };
1637
1638 Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type);
1639} // namespace QtPrivate
1640
1641template <typename T, int =
1642 QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject :
1643 QtPrivate::IsGadgetHelper<T>::IsRealGadget ? QMetaType::IsGadget :
1644 QtPrivate::IsPointerToGadgetHelper<T>::IsRealGadget ? QMetaType::PointerToGadget :
1645 QtPrivate::IsQEnumHelper<T>::Value ? QMetaType::IsEnumeration : 0>
1646struct QMetaTypeIdQObject
1647{
1648 enum {
1649 Defined = 0
1650 };
1651};
1652
1653template <typename T>
1654struct QMetaTypeId : public QMetaTypeIdQObject<T>
1655{
1656};
1657
1658template <typename T>
1659struct QMetaTypeId2
1660{
1661 enum { Defined = QMetaTypeId<T>::Defined, IsBuiltIn=false };
1662 static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }
1663};
1664
1665template <typename T>
1666struct QMetaTypeId2<const T&> : QMetaTypeId2<T> {};
1667
1668template <typename T>
1669struct QMetaTypeId2<T&> { enum {Defined = false }; };
1670
1671namespace QtPrivate {
1672 template <typename T, bool Defined = QMetaTypeId2<T>::Defined>
1673 struct QMetaTypeIdHelper {
1674 static inline Q_DECL_CONSTEXPR int qt_metatype_id()
1675 { return QMetaTypeId2<T>::qt_metatype_id(); }
1676 };
1677 template <typename T> struct QMetaTypeIdHelper<T, false> {
1678 static inline Q_DECL_CONSTEXPR int qt_metatype_id()
1679 { return -1; }
1680 };
1681
1682 // Function pointers don't derive from QObject
1683 template <typename Result, typename... Args>
1684 struct IsPointerToTypeDerivedFromQObject<Result(*)(Args...)> { enum { Value = false }; };
1685
1686 template<typename T>
1687 struct QMetaTypeTypeFlags
1688 {
1689 enum { Flags = (QTypeInfoQuery<T>::isRelocatable ? QMetaType::MovableType : 0)
1690 | (QTypeInfo<T>::isComplex ? QMetaType::NeedsConstruction : 0)
1691 | (QTypeInfo<T>::isComplex ? QMetaType::NeedsDestruction : 0)
1692 | (IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject : 0)
1693 | (IsSharedPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::SharedPointerToQObject : 0)
1694 | (IsWeakPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::WeakPointerToQObject : 0)
1695 | (IsTrackingPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::TrackingPointerToQObject : 0)
1696 | (std::is_enum<T>::value ? QMetaType::IsEnumeration : 0)
1697 | (IsGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::IsGadget : 0)
1698 | (IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::PointerToGadget : 0)
1699 };
1700 };
1701
1702 template<typename T, bool defined>
1703 struct MetaTypeDefinedHelper
1704 {
1705 enum DefinedType { Defined = defined };
1706 };
1707
1708 template<typename SmartPointer>
1709 struct QSmartPointerConvertFunctor
1710 {
1711 QObject* operator()(const SmartPointer &p) const
1712 {
1713 return p.operator->();
1714 }
1715 };
1716
1717 template<typename T>
1718 struct QSmartPointerConvertFunctor<QWeakPointer<T> >
1719 {
1720 QObject* operator()(const QWeakPointer<T> &p) const
1721 {
1722 return p.data();
1723 }
1724 };
1725}
1726
1727template <typename T>
1728int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName
1729#ifndef Q_CLANG_QDOC
1730 , T * dummy = 0
1731 , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType defined = QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined
1732#endif
1733)
1734{
1735#ifndef QT_NO_QOBJECT
1736 Q_ASSERT_X(normalizedTypeName == QMetaObject::normalizedType(normalizedTypeName.constData()), "qRegisterNormalizedMetaType", "qRegisterNormalizedMetaType was called with a not normalized type name, please call qRegisterMetaType instead.");
1737#endif
1738 const int typedefOf = dummy ? -1 : QtPrivate::QMetaTypeIdHelper<T>::qt_metatype_id();
1739 if (typedefOf != -1)
1740 return QMetaType::registerNormalizedTypedef(normalizedTypeName, typedefOf);
1741
1742 QMetaType::TypeFlags flags(QtPrivate::QMetaTypeTypeFlags<T>::Flags);
1743
1744 if (defined)
1745 flags |= QMetaType::WasDeclaredAsMetaType;
1746
1747 const int id = QMetaType::registerNormalizedType(normalizedTypeName,
1748 QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Destruct,
1749 QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Construct,
1750 int(sizeof(T)),
1751 flags,
1752 QtPrivate::MetaObjectForType<T>::value());
1753
1754 if (id > 0) {
1755 QtPrivate::SequentialContainerConverterHelper<T>::registerConverter(id);
1756 QtPrivate::AssociativeContainerConverterHelper<T>::registerConverter(id);
1757 QtPrivate::MetaTypePairHelper<T>::registerConverter(id);
1758 QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter(id);
1759 }
1760
1761 return id;
1762}
1763
1764template <typename T>
1765int qRegisterMetaType(const char *typeName
1766#ifndef Q_CLANG_QDOC
1767 , T * dummy = nullptr
1768 , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType defined = QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined
1769#endif
1770)
1771{
1772#ifdef QT_NO_QOBJECT
1773 QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = typeName;
1774#else
1775 QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
1776#endif
1777 return qRegisterNormalizedMetaType<T>(normalizedTypeName, dummy, defined);
1778}
1779
1780#ifndef QT_NO_DATASTREAM
1781template <typename T>
1782void qRegisterMetaTypeStreamOperators(const char *typeName
1783#ifndef Q_CLANG_QDOC
1784 , T * /* dummy */ = nullptr
1785#endif
1786)
1787{
1788 qRegisterMetaType<T>(typeName);
1789 QMetaType::registerStreamOperators(typeName, QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Save,
1790 QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Load);
1791}
1792#endif // QT_NO_DATASTREAM
1793
1794template <typename T>
1795inline Q_DECL_CONSTEXPR int qMetaTypeId()
1796{
1797 Q_STATIC_ASSERT_X(QMetaTypeId2<T>::Defined, "Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system");
1798 return QMetaTypeId2<T>::qt_metatype_id();
1799}
1800
1801template <typename T>
1802inline Q_DECL_CONSTEXPR int qRegisterMetaType()
1803{
1804 return qMetaTypeId<T>();
1805}
1806
1807#if QT_DEPRECATED_SINCE(5, 1) && !defined(Q_CLANG_QDOC)
1808// There used to be a T *dummy = 0 argument in Qt 4.0 to support MSVC6
1809template <typename T>
1810QT_DEPRECATED inline Q_DECL_CONSTEXPR int qMetaTypeId(T *)
1811{ return qMetaTypeId<T>(); }
1812#ifndef Q_CC_SUN
1813template <typename T>
1814QT_DEPRECATED inline Q_DECL_CONSTEXPR int qRegisterMetaType(T *)
1815{ return qRegisterMetaType<T>(); }
1816#endif
1817#endif
1818
1819#ifndef QT_NO_QOBJECT
1820template <typename T>
1821struct QMetaTypeIdQObject<T*, QMetaType::PointerToQObject>
1822{
1823 enum {
1824 Defined = 1
1825 };
1826
1827 static int qt_metatype_id()
1828 {
1829 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1830 if (const int id = metatype_id.loadAcquire())
1831 return id;
1832 const char * const cName = T::staticMetaObject.className();
1833 QByteArray typeName;
1834 typeName.reserve(int(strlen(cName)) + 1);
1835 typeName.append(cName).append('*');
1836 const int newId = qRegisterNormalizedMetaType<T*>(
1837 typeName,
1838 reinterpret_cast<T**>(quintptr(-1)));
1839 metatype_id.storeRelease(newId);
1840 return newId;
1841 }
1842};
1843
1844template <typename T>
1845struct QMetaTypeIdQObject<T, QMetaType::IsGadget>
1846{
1847 enum {
1848 Defined = std::is_default_constructible<T>::value
1849 };
1850
1851 static int qt_metatype_id()
1852 {
1853 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1854 if (const int id = metatype_id.loadAcquire())
1855 return id;
1856 const char * const cName = T::staticMetaObject.className();
1857 const int newId = qRegisterNormalizedMetaType<T>(
1858 cName,
1859 reinterpret_cast<T*>(quintptr(-1)));
1860 metatype_id.storeRelease(newId);
1861 return newId;
1862 }
1863};
1864
1865template <typename T>
1866struct QMetaTypeIdQObject<T*, QMetaType::PointerToGadget>
1867{
1868 enum {
1869 Defined = 1
1870 };
1871
1872 static int qt_metatype_id()
1873 {
1874 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1875 if (const int id = metatype_id.loadAcquire())
1876 return id;
1877 const char * const cName = T::staticMetaObject.className();
1878 QByteArray typeName;
1879 typeName.reserve(int(strlen(cName)) + 1);
1880 typeName.append(cName).append('*');
1881 const int newId = qRegisterNormalizedMetaType<T*>(
1882 typeName,
1883 reinterpret_cast<T**>(quintptr(-1)));
1884 metatype_id.storeRelease(newId);
1885 return newId;
1886 }
1887};
1888
1889template <typename T>
1890struct QMetaTypeIdQObject<T, QMetaType::IsEnumeration>
1891{
1892 enum {
1893 Defined = 1
1894 };
1895
1896 static int qt_metatype_id()
1897 {
1898 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1899 if (const int id = metatype_id.loadAcquire())
1900 return id;
1901 const char *eName = qt_getEnumName(T());
1902 const char *cName = qt_getEnumMetaObject(T())->className();
1903 QByteArray typeName;
1904 typeName.reserve(int(strlen(cName) + 2 + strlen(eName)));
1905 typeName.append(cName).append("::").append(eName);
1906 const int newId = qRegisterNormalizedMetaType<T>(
1907 typeName,
1908 reinterpret_cast<T*>(quintptr(-1)));
1909 metatype_id.storeRelease(newId);
1910 return newId;
1911 }
1912};
1913#endif
1914
1915#ifndef QT_NO_DATASTREAM
1916template <typename T>
1917inline int qRegisterMetaTypeStreamOperators()
1918{
1919 int id = qMetaTypeId<T>();
1920 QMetaType::registerStreamOperators(id, QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Save,
1921 QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Load);
1922 return id;
1923}
1924#endif
1925
1926#define Q_DECLARE_OPAQUE_POINTER(POINTER) \
1927 QT_BEGIN_NAMESPACE namespace QtPrivate { \
1928 template <> \
1929 struct IsPointerToTypeDerivedFromQObject<POINTER > \
1930 { \
1931 enum { Value = false }; \
1932 }; \
1933 } QT_END_NAMESPACE \
1934 /**/
1935
1936#ifndef Q_MOC_RUN
1937#define Q_DECLARE_METATYPE(TYPE) Q_DECLARE_METATYPE_IMPL(TYPE)
1938#define Q_DECLARE_METATYPE_IMPL(TYPE) \
1939 QT_BEGIN_NAMESPACE \
1940 template <> \
1941 struct QMetaTypeId< TYPE > \
1942 { \
1943 enum { Defined = 1 }; \
1944 static int qt_metatype_id() \
1945 { \
1946 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
1947 if (const int id = metatype_id.loadAcquire()) \
1948 return id; \
1949 const int newId = qRegisterMetaType< TYPE >(#TYPE, \
1950 reinterpret_cast< TYPE *>(quintptr(-1))); \
1951 metatype_id.storeRelease(newId); \
1952 return newId; \
1953 } \
1954 }; \
1955 QT_END_NAMESPACE
1956#endif // Q_MOC_RUN
1957
1958#define Q_DECLARE_BUILTIN_METATYPE(TYPE, METATYPEID, NAME) \
1959 QT_BEGIN_NAMESPACE \
1960 template<> struct QMetaTypeId2<NAME> \
1961 { \
1962 enum { Defined = 1, IsBuiltIn = true, MetaType = METATYPEID }; \
1963 static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return METATYPEID; } \
1964 }; \
1965 QT_END_NAMESPACE
1966
1967#define QT_FORWARD_DECLARE_STATIC_TYPES_ITER(TypeName, TypeId, Name) \
1968 class Name;
1969
1970QT_FOR_EACH_STATIC_CORE_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1971QT_FOR_EACH_STATIC_GUI_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1972QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1973
1974#undef QT_FORWARD_DECLARE_STATIC_TYPES_ITER
1975
1976typedef QList<QVariant> QVariantList;
1977typedef QMap<QString, QVariant> QVariantMap;
1978typedef QHash<QString, QVariant> QVariantHash;
1979#ifndef Q_CLANG_QDOC
1980typedef QList<QByteArray> QByteArrayList;
1981#endif
1982
1983#define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE) \
1984QT_BEGIN_NAMESPACE \
1985template <typename T> \
1986struct QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \
1987{ \
1988 enum { \
1989 Defined = QMetaTypeId2<T>::Defined \
1990 }; \
1991 static int qt_metatype_id() \
1992 { \
1993 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
1994 if (const int id = metatype_id.load()) \
1995 return id; \
1996 const char *tName = QMetaType::typeName(qMetaTypeId<T>()); \
1997 Q_ASSERT(tName); \
1998 const int tNameLen = int(qstrlen(tName)); \
1999 QByteArray typeName; \
2000 typeName.reserve(int(sizeof(#SINGLE_ARG_TEMPLATE)) + 1 + tNameLen + 1 + 1); \
2001 typeName.append(#SINGLE_ARG_TEMPLATE, int(sizeof(#SINGLE_ARG_TEMPLATE)) - 1) \
2002 .append('<').append(tName, tNameLen); \
2003 if (typeName.endsWith('>')) \
2004 typeName.append(' '); \
2005 typeName.append('>'); \
2006 const int newId = qRegisterNormalizedMetaType< SINGLE_ARG_TEMPLATE<T> >( \
2007 typeName, \
2008 reinterpret_cast< SINGLE_ARG_TEMPLATE<T> *>(quintptr(-1))); \
2009 metatype_id.storeRelease(newId); \
2010 return newId; \
2011 } \
2012}; \
2013namespace QtPrivate { \
2014template<typename T> \
2015struct IsSequentialContainer<SINGLE_ARG_TEMPLATE<T> > \
2016{ \
2017 enum { Value = true }; \
2018}; \
2019} \
2020QT_END_NAMESPACE
2021
2022#define Q_DECLARE_METATYPE_TEMPLATE_2ARG(DOUBLE_ARG_TEMPLATE) \
2023QT_BEGIN_NAMESPACE \
2024template<typename T, typename U> \
2025struct QMetaTypeId< DOUBLE_ARG_TEMPLATE<T, U> > \
2026{ \
2027 enum { \
2028 Defined = QMetaTypeId2<T>::Defined && QMetaTypeId2<U>::Defined \
2029 }; \
2030 static int qt_metatype_id() \
2031 { \
2032 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
2033 if (const int id = metatype_id.loadAcquire()) \
2034 return id; \
2035 const char *tName = QMetaType::typeName(qMetaTypeId<T>()); \
2036 const char *uName = QMetaType::typeName(qMetaTypeId<U>()); \
2037 Q_ASSERT(tName); \
2038 Q_ASSERT(uName); \
2039 const int tNameLen = int(qstrlen(tName)); \
2040 const int uNameLen = int(qstrlen(uName)); \
2041 QByteArray typeName; \
2042 typeName.reserve(int(sizeof(#DOUBLE_ARG_TEMPLATE)) + 1 + tNameLen + 1 + uNameLen + 1 + 1); \
2043 typeName.append(#DOUBLE_ARG_TEMPLATE, int(sizeof(#DOUBLE_ARG_TEMPLATE)) - 1) \
2044 .append('<').append(tName, tNameLen).append(',').append(uName, uNameLen); \
2045 if (typeName.endsWith('>')) \
2046 typeName.append(' '); \
2047 typeName.append('>'); \
2048 const int newId = qRegisterNormalizedMetaType< DOUBLE_ARG_TEMPLATE<T, U> >(\
2049 typeName, \
2050 reinterpret_cast< DOUBLE_ARG_TEMPLATE<T, U> *>(quintptr(-1))); \
2051 metatype_id.storeRelease(newId); \
2052 return newId; \
2053 } \
2054}; \
2055QT_END_NAMESPACE
2056
2057namespace QtPrivate {
2058
2059template<typename T, bool /* isSharedPointerToQObjectDerived */ = false>
2060struct SharedPointerMetaTypeIdHelper
2061{
2062 enum {
2063 Defined = 0
2064 };
2065 static int qt_metatype_id()
2066 {
2067 return -1;
2068 }
2069};
2070
2071}
2072
2073#define Q_DECLARE_SMART_POINTER_METATYPE(SMART_POINTER) \
2074QT_BEGIN_NAMESPACE \
2075namespace QtPrivate { \
2076template<typename T> \
2077struct SharedPointerMetaTypeIdHelper<SMART_POINTER<T>, true> \
2078{ \
2079 enum { \
2080 Defined = 1 \
2081 }; \
2082 static int qt_metatype_id() \
2083 { \
2084 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
2085 if (const int id = metatype_id.loadAcquire()) \
2086 return id; \
2087 const char * const cName = T::staticMetaObject.className(); \
2088 QByteArray typeName; \
2089 typeName.reserve(int(sizeof(#SMART_POINTER) + 1 + strlen(cName) + 1)); \
2090 typeName.append(#SMART_POINTER, int(sizeof(#SMART_POINTER)) - 1) \
2091 .append('<').append(cName).append('>'); \
2092 const int newId = qRegisterNormalizedMetaType< SMART_POINTER<T> >( \
2093 typeName, \
2094 reinterpret_cast< SMART_POINTER<T> *>(quintptr(-1))); \
2095 metatype_id.storeRelease(newId); \
2096 return newId; \
2097 } \
2098}; \
2099template<typename T> \
2100struct MetaTypeSmartPointerHelper<SMART_POINTER<T> , \
2101 typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value>::type> \
2102{ \
2103 static bool registerConverter(int id) \
2104 { \
2105 const int toId = QMetaType::QObjectStar; \
2106 if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { \
2107 QtPrivate::QSmartPointerConvertFunctor<SMART_POINTER<T> > o; \
2108 static const QtPrivate::ConverterFunctor<SMART_POINTER<T>, \
2109 QObject*, \
2110 QSmartPointerConvertFunctor<SMART_POINTER<T> > > f(o); \
2111 return QMetaType::registerConverterFunction(&f, id, toId); \
2112 } \
2113 return true; \
2114 } \
2115}; \
2116} \
2117template <typename T> \
2118struct QMetaTypeId< SMART_POINTER<T> > \
2119 : QtPrivate::SharedPointerMetaTypeIdHelper< SMART_POINTER<T>, \
2120 QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value> \
2121{ \
2122};\
2123QT_END_NAMESPACE
2124
2125#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER(TEMPLATENAME) \
2126 QT_BEGIN_NAMESPACE \
2127 template <class T> class TEMPLATENAME; \
2128 QT_END_NAMESPACE \
2129 Q_DECLARE_METATYPE_TEMPLATE_1ARG(TEMPLATENAME)
2130
2131QT_END_NAMESPACE
2132
2133QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER)
2134
2135#undef Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER
2136
2137#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE Q_DECLARE_METATYPE_TEMPLATE_1ARG
2138
2139Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::vector)
2140Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::list)
2141
2142#define Q_FORWARD_DECLARE_METATYPE_TEMPLATE_2ARG_ITER(TEMPLATENAME, CPPTYPE) \
2143 QT_BEGIN_NAMESPACE \
2144 template <class T1, class T2> CPPTYPE TEMPLATENAME; \
2145 QT_END_NAMESPACE \
2146
2147QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(Q_FORWARD_DECLARE_METATYPE_TEMPLATE_2ARG_ITER)
2148
2149#undef Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER
2150
2151#define Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(TEMPLATENAME) \
2152 QT_BEGIN_NAMESPACE \
2153 namespace QtPrivate { \
2154 template<typename T, typename U> \
2155 struct IsAssociativeContainer<TEMPLATENAME<T, U> > \
2156 { \
2157 enum { Value = true }; \
2158 }; \
2159 } \
2160 QT_END_NAMESPACE \
2161 Q_DECLARE_METATYPE_TEMPLATE_2ARG(TEMPLATENAME)
2162
2163Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QHash)
2164Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QMap)
2165Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(std::map)
2166
2167Q_DECLARE_METATYPE_TEMPLATE_2ARG(QPair)
2168Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::pair)
2169
2170#define Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER(TEMPLATENAME) \
2171 Q_DECLARE_SMART_POINTER_METATYPE(TEMPLATENAME)
2172
2173
2174QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER)
2175
2176QT_BEGIN_NAMESPACE
2177
2178#undef Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER
2179
2180inline QMetaType::QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
2181 TypedConstructor creator,
2182 TypedDestructor deleter,
2183 SaveOperator saveOp,
2184 LoadOperator loadOp,
2185 Constructor constructor,
2186 Destructor destructor,
2187 uint size,
2188 uint theTypeFlags,
2189 int typeId,
2190 const QMetaObject *_metaObject)
2191 : m_typedConstructor(creator)
2192 , m_typedDestructor(deleter)
2193 , m_saveOp(saveOp)
2194 , m_loadOp(loadOp)
2195 , m_constructor(constructor)
2196 , m_destructor(destructor)
2197 , m_extension(nullptr)
2198 , m_size(size)
2199 , m_typeFlags(theTypeFlags)
2200 , m_extensionFlags(extensionFlags)
2201 , m_typeId(typeId)
2202 , m_metaObject(_metaObject)
2203{
2204 if (Q_UNLIKELY(isExtended(CtorEx) || typeId == QMetaType::Void))
2205 ctor(info);
2206}
2207
2208inline QMetaType::~QMetaType()
2209{
2210 if (Q_UNLIKELY(isExtended(DtorEx)))
2211 dtor();
2212}
2213
2214inline bool QMetaType::isValid() const
2215{
2216 return m_typeId != UnknownType;
2217}
2218
2219inline bool QMetaType::isRegistered() const
2220{
2221 return isValid();
2222}
2223
2224inline void *QMetaType::create(const void *copy) const
2225{
2226 // ### TODO Qt6 remove the extension
2227 return createExtended(copy);
2228}
2229
2230inline void QMetaType::destroy(void *data) const
2231{
2232 // ### TODO Qt6 remove the extension
2233 destroyExtended(data);
2234}
2235
2236inline void *QMetaType::construct(void *where, const void *copy) const
2237{
2238 if (Q_UNLIKELY(isExtended(ConstructEx)))
2239 return constructExtended(where, copy);
2240 return m_constructor(where, copy);
2241}
2242
2243inline void QMetaType::destruct(void *data) const
2244{
2245 if (Q_UNLIKELY(isExtended(DestructEx)))
2246 return destructExtended(data);
2247 if (Q_UNLIKELY(!data))
2248 return;
2249 m_destructor(data);
2250}
2251
2252inline int QMetaType::sizeOf() const
2253{
2254 if (Q_UNLIKELY(isExtended(SizeEx)))
2255 return sizeExtended();
2256 return m_size;
2257}
2258
2259inline QMetaType::TypeFlags QMetaType::flags() const
2260{
2261 if (Q_UNLIKELY(isExtended(FlagsEx)))
2262 return flagsExtended();
2263 return QMetaType::TypeFlags(m_typeFlags);
2264}
2265
2266inline const QMetaObject *QMetaType::metaObject() const
2267{
2268 if (Q_UNLIKELY(isExtended(MetaObjectEx)))
2269 return metaObjectExtended();
2270 return m_metaObject;
2271}
2272
2273QT_END_NAMESPACE
2274
2275
2276QT_FOR_EACH_STATIC_TYPE(Q_DECLARE_BUILTIN_METATYPE)
2277
2278Q_DECLARE_METATYPE(QtMetaTypePrivate::QSequentialIterableImpl)
2279Q_DECLARE_METATYPE(QtMetaTypePrivate::QAssociativeIterableImpl)
2280Q_DECLARE_METATYPE(QtMetaTypePrivate::QPairVariantInterfaceImpl)
2281
2282QT_BEGIN_NAMESPACE
2283
2284template <typename T>
2285inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter(int id)
2286{
2287 const int toId = qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
2288 if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
2289 QtMetaTypePrivate::QPairVariantInterfaceConvertFunctor<T> o;
2290 static const QtPrivate::ConverterFunctor<T,
2291 QtMetaTypePrivate::QPairVariantInterfaceImpl,
2292 QtMetaTypePrivate::QPairVariantInterfaceConvertFunctor<T> > f(o);
2293 return QMetaType::registerConverterFunction(&f, id, toId);
2294 }
2295 return true;
2296}
2297
2298namespace QtPrivate {
2299 template<typename T>
2300 struct ValueTypeIsMetaType<T, true>
2301 {
2302 static bool registerConverter(int id)
2303 {
2304 const int toId = qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>();
2305 if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
2306 QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> o;
2307 static const QtPrivate::ConverterFunctor<T,
2308 QtMetaTypePrivate::QSequentialIterableImpl,
2309 QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> > f(o);
2310 return QMetaType::registerConverterFunction(&f, id, toId);
2311 }
2312 return true;
2313 }
2314 };
2315
2316 template<typename T>
2317 struct AssociativeValueTypeIsMetaType<T, true>
2318 {
2319 static bool registerConverter(int id)
2320 {
2321 const int toId = qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>();
2322 if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
2323 QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> o;
2324 static const QtPrivate::ConverterFunctor<T,
2325 QtMetaTypePrivate::QAssociativeIterableImpl,
2326 QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> > f(o);
2327 return QMetaType::registerConverterFunction(&f, id, toId);
2328 }
2329 return true;
2330 }
2331 };
2332}
2333
2334QT_END_NAMESPACE
2335
2336#endif // QMETATYPE_H
2337