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

source code of qtbase/src/corelib/kernel/qmetatype.h