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 id() const;
574 inline int sizeOf() const;
575 inline TypeFlags flags() const;
576 inline const QMetaObject *metaObject() const;
577
578 inline void *create(const void *copy = nullptr) const;
579 inline void destroy(void *data) const;
580 inline void *construct(void *where, const void *copy = nullptr) const;
581 inline void destruct(void *data) const;
582
583public:
584 template<typename T>
585 static bool registerComparators()
586 {
587 Q_STATIC_ASSERT_X((!QMetaTypeId2<T>::IsBuiltIn),
588 "QMetaType::registerComparators: The type must be a custom type.");
589
590 const int typeId = qMetaTypeId<T>();
591 static const QtPrivate::BuiltInComparatorFunction<T> f;
592 return registerComparatorFunction( &f, typeId);
593 }
594 template<typename T>
595 static bool registerEqualsComparator()
596 {
597 Q_STATIC_ASSERT_X((!QMetaTypeId2<T>::IsBuiltIn),
598 "QMetaType::registerEqualsComparator: The type must be a custom type.");
599 const int typeId = qMetaTypeId<T>();
600 static const QtPrivate::BuiltInEqualsComparatorFunction<T> f;
601 return registerComparatorFunction( &f, typeId);
602 }
603
604 template<typename T>
605 static bool hasRegisteredComparators()
606 {
607 return hasRegisteredComparators(qMetaTypeId<T>());
608 }
609 static bool hasRegisteredComparators(int typeId);
610
611
612#ifndef QT_NO_DEBUG_STREAM
613 template<typename T>
614 static bool registerDebugStreamOperator()
615 {
616 Q_STATIC_ASSERT_X((!QMetaTypeId2<T>::IsBuiltIn),
617 "QMetaType::registerDebugStreamOperator: The type must be a custom type.");
618
619 const int typeId = qMetaTypeId<T>();
620 static const QtPrivate::BuiltInDebugStreamFunction<T> f;
621 return registerDebugStreamOperatorFunction(&f, typeId);
622 }
623 template<typename T>
624 static bool hasRegisteredDebugStreamOperator()
625 {
626 return hasRegisteredDebugStreamOperator(qMetaTypeId<T>());
627 }
628 static bool hasRegisteredDebugStreamOperator(int typeId);
629#endif
630
631 // implicit conversion supported like double -> float
632 template<typename From, typename To>
633 static bool registerConverter()
634 {
635 return registerConverter<From, To>(QtPrivate::convertImplicit<From, To>);
636 }
637
638#ifdef Q_CLANG_QDOC
639 template<typename MemberFunction, int>
640 static bool registerConverter(MemberFunction function);
641 template<typename MemberFunctionOk, char>
642 static bool registerConverter(MemberFunctionOk function);
643 template<typename UnaryFunction>
644 static bool registerConverter(UnaryFunction function);
645#else
646 // member function as in "QString QFont::toString() const"
647 template<typename From, typename To>
648 static bool registerConverter(To(From::*function)() const)
649 {
650 Q_STATIC_ASSERT_X((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
651 "QMetaType::registerConverter: At least one of the types must be a custom type.");
652
653 const int fromTypeId = qMetaTypeId<From>();
654 const int toTypeId = qMetaTypeId<To>();
655 static const QtPrivate::ConverterMemberFunction<From, To> f(function);
656 return registerConverterFunction(&f, fromTypeId, toTypeId);
657 }
658
659 // member function as in "double QString::toDouble(bool *ok = nullptr) const"
660 template<typename From, typename To>
661 static bool registerConverter(To(From::*function)(bool*) const)
662 {
663 Q_STATIC_ASSERT_X((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
664 "QMetaType::registerConverter: At least one of the types must be a custom type.");
665
666 const int fromTypeId = qMetaTypeId<From>();
667 const int toTypeId = qMetaTypeId<To>();
668 static const QtPrivate::ConverterMemberFunctionOk<From, To> f(function);
669 return registerConverterFunction(&f, fromTypeId, toTypeId);
670 }
671
672 // functor or function pointer
673 template<typename From, typename To, typename UnaryFunction>
674 static bool registerConverter(UnaryFunction function)
675 {
676 Q_STATIC_ASSERT_X((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
677 "QMetaType::registerConverter: At least one of the types must be a custom type.");
678
679 const int fromTypeId = qMetaTypeId<From>();
680 const int toTypeId = qMetaTypeId<To>();
681 static const QtPrivate::ConverterFunctor<From, To, UnaryFunction> f(function);
682 return registerConverterFunction(&f, fromTypeId, toTypeId);
683 }
684#endif
685
686 static bool convert(const void *from, int fromTypeId, void *to, int toTypeId);
687 static bool compare(const void *lhs, const void *rhs, int typeId, int* result);
688 static bool equals(const void *lhs, const void *rhs, int typeId, int* result);
689 static bool debugStream(QDebug& dbg, const void *rhs, int typeId);
690
691 template<typename From, typename To>
692 static bool hasRegisteredConverterFunction()
693 {
694 return hasRegisteredConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
695 }
696
697 static bool hasRegisteredConverterFunction(int fromTypeId, int toTypeId);
698
699private:
700 static QMetaType typeInfo(const int type);
701 inline QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
702 TypedConstructor creator,
703 TypedDestructor deleter,
704 SaveOperator saveOp,
705 LoadOperator loadOp,
706 Constructor constructor,
707 Destructor destructor,
708 uint sizeOf,
709 uint theTypeFlags,
710 int typeId,
711 const QMetaObject *metaObject);
712 QMetaType(const QMetaType &other);
713 QMetaType &operator =(const QMetaType &);
714 inline bool isExtended(const ExtensionFlag flag) const { return m_extensionFlags & flag; }
715
716 // Methods used for future binary compatible extensions
717 void ctor(const QMetaTypeInterface *info);
718 void dtor();
719 uint sizeExtended() const;
720 QMetaType::TypeFlags flagsExtended() const;
721 const QMetaObject *metaObjectExtended() const;
722 void *createExtended(const void *copy = nullptr) const;
723 void destroyExtended(void *data) const;
724 void *constructExtended(void *where, const void *copy = nullptr) const;
725 void destructExtended(void *data) const;
726
727 static bool registerComparatorFunction(const QtPrivate::AbstractComparatorFunction *f, int type);
728#ifndef QT_NO_DEBUG_STREAM
729 static bool registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f, int type);
730#endif
731
732// ### Qt6: FIXME: Remove the special Q_CC_MSVC handling, it was introduced to maintain BC.
733#if !defined(Q_NO_TEMPLATE_FRIENDS) && !defined(Q_CC_MSVC)
734#ifndef Q_CLANG_QDOC
735 template<typename, bool> friend struct QtPrivate::ValueTypeIsMetaType;
736 template<typename, typename> friend struct QtPrivate::ConverterMemberFunction;
737 template<typename, typename> friend struct QtPrivate::ConverterMemberFunctionOk;
738 template<typename, typename, typename> friend struct QtPrivate::ConverterFunctor;
739 template<typename, bool> friend struct QtPrivate::AssociativeValueTypeIsMetaType;
740 template<typename, bool> friend struct QtPrivate::IsMetaTypePair;
741 template<typename, typename> friend struct QtPrivate::MetaTypeSmartPointerHelper;
742#endif
743#else
744public:
745#endif
746 static bool registerConverterFunction(const QtPrivate::AbstractConverterFunction *f, int from, int to);
747 static void unregisterConverterFunction(int from, int to);
748private:
749
750 TypedConstructor m_typedConstructor;
751 TypedDestructor m_typedDestructor;
752 SaveOperator m_saveOp;
753 LoadOperator m_loadOp;
754 Constructor m_constructor;
755 Destructor m_destructor;
756 void *m_extension; // space reserved for future use
757 uint m_size;
758 uint m_typeFlags;
759 uint m_extensionFlags;
760 int m_typeId;
761 const QMetaObject *m_metaObject;
762};
763
764#undef QT_DEFINE_METATYPE_ID
765
766Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags)
767
768namespace QtPrivate {
769
770template<typename From, typename To>
771ConverterMemberFunction<From, To>::~ConverterMemberFunction()
772{
773 QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
774}
775template<typename From, typename To>
776ConverterMemberFunctionOk<From, To>::~ConverterMemberFunctionOk()
777{
778 QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
779}
780template<typename From, typename To, typename UnaryFunction>
781ConverterFunctor<From, To, UnaryFunction>::~ConverterFunctor()
782{
783 QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
784}
785
786}
787
788#define QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(C, F) \
789 } \
790 Q_DECLARE_TYPEINFO(QtMetaTypePrivate:: C, (F)); \
791 namespace QtMetaTypePrivate {
792
793namespace QtMetaTypePrivate {
794template <typename T, bool Accepted = true>
795struct QMetaTypeFunctionHelper {
796 static void Destruct(void *t)
797 {
798 Q_UNUSED(t) // Silence MSVC that warns for POD types.
799 static_cast<T*>(t)->~T();
800 }
801
802 static void *Construct(void *where, const void *t)
803 {
804 if (t)
805 return new (where) T(*static_cast<const T*>(t));
806 return new (where) T;
807 }
808#ifndef QT_NO_DATASTREAM
809 static void Save(QDataStream &stream, const void *t)
810 {
811 stream << *static_cast<const T*>(t);
812 }
813
814 static void Load(QDataStream &stream, void *t)
815 {
816 stream >> *static_cast<T*>(t);
817 }
818#endif // QT_NO_DATASTREAM
819};
820
821template <typename T>
822struct QMetaTypeFunctionHelper<T, /* Accepted */ false> {
823 static void Destruct(void *) {}
824 static void *Construct(void *, const void *) { return nullptr; }
825#ifndef QT_NO_DATASTREAM
826 static void Save(QDataStream &, const void *) {}
827 static void Load(QDataStream &, void *) {}
828#endif // QT_NO_DATASTREAM
829};
830template <>
831struct QMetaTypeFunctionHelper<void, /* Accepted */ true>
832 : public QMetaTypeFunctionHelper<void, /* Accepted */ false>
833{};
834
835struct VariantData
836{
837 VariantData(const int metaTypeId_,
838 const void *data_,
839 const uint flags_)
840 : metaTypeId(metaTypeId_)
841 , data(data_)
842 , flags(flags_)
843 {
844 }
845 VariantData(const VariantData &other)
846 : metaTypeId(other.metaTypeId), data(other.data), flags(other.flags){}
847 const int metaTypeId;
848 const void *data;
849 const uint flags;
850private:
851 // copy constructor allowed to be implicit to silence level 4 warning from MSVC
852 VariantData &operator=(const VariantData &) Q_DECL_EQ_DELETE;
853};
854
855template<typename const_iterator>
856struct IteratorOwnerCommon
857{
858 static void assign(void **ptr, const_iterator iterator)
859 {
860 *ptr = new const_iterator(iterator);
861 }
862 static void assign(void **ptr, void * const * src)
863 {
864 *ptr = new const_iterator(*static_cast<const_iterator*>(*src));
865 }
866
867 static void advance(void **iterator, int step)
868 {
869 const_iterator &it = *static_cast<const_iterator*>(*iterator);
870 std::advance(it, step);
871 }
872
873 static void destroy(void **ptr)
874 {
875 delete static_cast<const_iterator*>(*ptr);
876 }
877
878 static bool equal(void * const *it, void * const *other)
879 {
880 return *static_cast<const_iterator*>(*it) == *static_cast<const_iterator*>(*other);
881 }
882};
883
884template<typename const_iterator>
885struct IteratorOwner : IteratorOwnerCommon<const_iterator>
886{
887 static const void *getData(void * const *iterator)
888 {
889 return &**static_cast<const_iterator*>(*iterator);
890 }
891
892 static const void *getData(const_iterator it)
893 {
894 return &*it;
895 }
896};
897
898struct Q_CORE_EXPORT VectorBoolElements
899{
900 static const bool true_element;
901 static const bool false_element;
902};
903
904template<>
905struct IteratorOwner<std::vector<bool>::const_iterator> : IteratorOwnerCommon<std::vector<bool>::const_iterator>
906{
907public:
908 static const void *getData(void * const *iterator)
909 {
910 return **static_cast<std::vector<bool>::const_iterator*>(*iterator) ?
911 &VectorBoolElements::true_element : &VectorBoolElements::false_element;
912 }
913
914 static const void *getData(const std::vector<bool>::const_iterator& it)
915 {
916 return *it ? &VectorBoolElements::true_element : &VectorBoolElements::false_element;
917 }
918};
919
920template<typename value_type>
921struct IteratorOwner<const value_type*>
922{
923private:
924 // We need to disable typed overloads of assign() and getData() if the value_type
925 // is void* to avoid overloads conflicts. We do it by injecting unaccessible Dummy
926 // type as part of the overload signature.
927 struct Dummy {};
928 typedef typename std::conditional<std::is_same<value_type, void*>::value, Dummy, value_type>::type value_type_OR_Dummy;
929public:
930 static void assign(void **ptr, const value_type_OR_Dummy *iterator )
931 {
932 *ptr = const_cast<value_type*>(iterator);
933 }
934 static void assign(void **ptr, void * const * src)
935 {
936 *ptr = static_cast<value_type*>(*src);
937 }
938
939 static void advance(void **iterator, int step)
940 {
941 value_type *it = static_cast<value_type*>(*iterator);
942 std::advance(it, step);
943 *iterator = it;
944 }
945
946 static void destroy(void **)
947 {
948 }
949
950 static const void *getData(void * const *iterator)
951 {
952 return *iterator;
953 }
954
955 static const void *getData(const value_type_OR_Dummy *it)
956 {
957 return it;
958 }
959
960 static bool equal(void * const *it, void * const *other)
961 {
962 return static_cast<value_type*>(*it) == static_cast<value_type*>(*other);
963 }
964};
965
966enum IteratorCapability
967{
968 ForwardCapability = 1,
969 BiDirectionalCapability = 2,
970 RandomAccessCapability = 4
971};
972
973template<typename T, typename Category = typename std::iterator_traits<typename T::const_iterator>::iterator_category>
974struct CapabilitiesImpl;
975
976template<typename T>
977struct CapabilitiesImpl<T, std::forward_iterator_tag>
978{ enum { IteratorCapabilities = ForwardCapability }; };
979template<typename T>
980struct CapabilitiesImpl<T, std::bidirectional_iterator_tag>
981{ enum { IteratorCapabilities = BiDirectionalCapability | ForwardCapability }; };
982template<typename T>
983struct CapabilitiesImpl<T, std::random_access_iterator_tag>
984{ enum { IteratorCapabilities = RandomAccessCapability | BiDirectionalCapability | ForwardCapability }; };
985
986template<typename T>
987struct ContainerAPI : CapabilitiesImpl<T>
988{
989 static int size(const T *t) { return int(std::distance(t->begin(), t->end())); }
990};
991
992template<typename T>
993struct ContainerAPI<QList<T> > : CapabilitiesImpl<QList<T> >
994{ static int size(const QList<T> *t) { return t->size(); } };
995
996template<typename T>
997struct ContainerAPI<QVector<T> > : CapabilitiesImpl<QVector<T> >
998{ static int size(const QVector<T> *t) { return t->size(); } };
999
1000template<typename T>
1001struct ContainerAPI<std::vector<T> > : CapabilitiesImpl<std::vector<T> >
1002{ static int size(const std::vector<T> *t) { return int(t->size()); } };
1003
1004template<typename T>
1005struct ContainerAPI<std::list<T> > : CapabilitiesImpl<std::list<T> >
1006{ static int size(const std::list<T> *t) { return int(t->size()); } };
1007
1008class QSequentialIterableImpl
1009{
1010public:
1011 const void * _iterable;
1012 void *_iterator;
1013 int _metaType_id;
1014 uint _metaType_flags;
1015 uint _iteratorCapabilities;
1016 typedef int(*sizeFunc)(const void *p);
1017 typedef const void * (*atFunc)(const void *p, int);
1018 typedef void (*moveIteratorFunc)(const void *p, void **);
1019 typedef void (*advanceFunc)(void **p, int);
1020 typedef VariantData (*getFunc)( void * const *p, int metaTypeId, uint flags);
1021 typedef void (*destroyIterFunc)(void **p);
1022 typedef bool (*equalIterFunc)(void * const *p, void * const *other);
1023 typedef void (*copyIterFunc)(void **, void * const *);
1024
1025 sizeFunc _size;
1026 atFunc _at;
1027 moveIteratorFunc _moveToBegin;
1028 moveIteratorFunc _moveToEnd;
1029 advanceFunc _advance;
1030 getFunc _get;
1031 destroyIterFunc _destroyIter;
1032 equalIterFunc _equalIter;
1033 copyIterFunc _copyIter;
1034
1035 template<class T>
1036 static int sizeImpl(const void *p)
1037 { return ContainerAPI<T>::size(static_cast<const T*>(p)); }
1038
1039 template<class T>
1040 static const void* atImpl(const void *p, int idx)
1041 {
1042 typename T::const_iterator i = static_cast<const T*>(p)->begin();
1043 std::advance(i, idx);
1044 return IteratorOwner<typename T::const_iterator>::getData(i);
1045 }
1046
1047 template<class T>
1048 static void moveToBeginImpl(const void *container, void **iterator)
1049 { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->begin()); }
1050
1051 template<class T>
1052 static void moveToEndImpl(const void *container, void **iterator)
1053 { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->end()); }
1054
1055 template<class T>
1056 static VariantData getImpl(void * const *iterator, int metaTypeId, uint flags)
1057 { return VariantData(metaTypeId, IteratorOwner<typename T::const_iterator>::getData(iterator), flags); }
1058
1059public:
1060 template<class T> QSequentialIterableImpl(const T*p)
1061 : _iterable(p)
1062 , _iterator(nullptr)
1063 , _metaType_id(qMetaTypeId<typename T::value_type>())
1064 , _metaType_flags(QTypeInfo<typename T::value_type>::isPointer)
1065 , _iteratorCapabilities(ContainerAPI<T>::IteratorCapabilities)
1066 , _size(sizeImpl<T>)
1067 , _at(atImpl<T>)
1068 , _moveToBegin(moveToBeginImpl<T>)
1069 , _moveToEnd(moveToEndImpl<T>)
1070 , _advance(IteratorOwner<typename T::const_iterator>::advance)
1071 , _get(getImpl<T>)
1072 , _destroyIter(IteratorOwner<typename T::const_iterator>::destroy)
1073 , _equalIter(IteratorOwner<typename T::const_iterator>::equal)
1074 , _copyIter(IteratorOwner<typename T::const_iterator>::assign)
1075 {
1076 }
1077
1078 QSequentialIterableImpl()
1079 : _iterable(nullptr)
1080 , _iterator(nullptr)
1081 , _metaType_id(QMetaType::UnknownType)
1082 , _metaType_flags(0)
1083 , _iteratorCapabilities(0)
1084 , _size(nullptr)
1085 , _at(nullptr)
1086 , _moveToBegin(nullptr)
1087 , _moveToEnd(nullptr)
1088 , _advance(nullptr)
1089 , _get(nullptr)
1090 , _destroyIter(nullptr)
1091 , _equalIter(nullptr)
1092 , _copyIter(nullptr)
1093 {
1094 }
1095
1096 inline void moveToBegin() { _moveToBegin(_iterable, &_iterator); }
1097 inline void moveToEnd() { _moveToEnd(_iterable, &_iterator); }
1098 inline bool equal(const QSequentialIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); }
1099 inline QSequentialIterableImpl &advance(int i) {
1100 Q_ASSERT(i > 0 || _iteratorCapabilities & BiDirectionalCapability);
1101 _advance(&_iterator, i);
1102 return *this;
1103 }
1104
1105 inline VariantData getCurrent() const { return _get(&_iterator, _metaType_id, _metaType_flags); }
1106
1107 VariantData at(int idx) const
1108 { return VariantData(_metaType_id, _at(_iterable, idx), _metaType_flags); }
1109
1110 int size() const { Q_ASSERT(_iterable); return _size(_iterable); }
1111
1112 inline void destroyIter() { _destroyIter(&_iterator); }
1113
1114 void copy(const QSequentialIterableImpl &other)
1115 {
1116 *this = other;
1117 _copyIter(&_iterator, &other._iterator);
1118 }
1119};
1120QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QSequentialIterableImpl, Q_MOVABLE_TYPE)
1121
1122template<typename From>
1123struct QSequentialIterableConvertFunctor
1124{
1125 QSequentialIterableImpl operator()(const From &f) const
1126 {
1127 return QSequentialIterableImpl(&f);
1128 }
1129};
1130}
1131
1132namespace QtMetaTypePrivate {
1133template<typename T, bool = std::is_same<typename T::const_iterator::value_type, typename T::mapped_type>::value>
1134struct AssociativeContainerAccessor
1135{
1136 static const typename T::key_type& getKey(const typename T::const_iterator &it)
1137 {
1138 return it.key();
1139 }
1140
1141 static const typename T::mapped_type& getValue(const typename T::const_iterator &it)
1142 {
1143 return it.value();
1144 }
1145};
1146
1147template<typename T, bool = std::is_same<typename T::const_iterator::value_type, std::pair<const typename T::key_type, typename T::mapped_type> >::value>
1148struct StlStyleAssociativeContainerAccessor;
1149
1150template<typename T>
1151struct StlStyleAssociativeContainerAccessor<T, true>
1152{
1153 static const typename T::key_type& getKey(const typename T::const_iterator &it)
1154 {
1155 return it->first;
1156 }
1157
1158 static const typename T::mapped_type& getValue(const typename T::const_iterator &it)
1159 {
1160 return it->second;
1161 }
1162};
1163
1164template<typename T>
1165struct AssociativeContainerAccessor<T, false> : public StlStyleAssociativeContainerAccessor<T>
1166{
1167};
1168
1169class QAssociativeIterableImpl
1170{
1171public:
1172 const void *_iterable;
1173 void *_iterator;
1174 int _metaType_id_key;
1175 uint _metaType_flags_key;
1176 int _metaType_id_value;
1177 uint _metaType_flags_value;
1178 typedef int(*sizeFunc)(const void *p);
1179 typedef void (*findFunc)(const void *container, const void *p, void **iterator);
1180 typedef void (*beginFunc)(const void *p, void **);
1181 typedef void (*advanceFunc)(void **p, int);
1182 typedef VariantData (*getFunc)(void * const *p, int metaTypeId, uint flags);
1183 typedef void (*destroyIterFunc)(void **p);
1184 typedef bool (*equalIterFunc)(void * const *p, void * const *other);
1185 typedef void (*copyIterFunc)(void **, void * const *);
1186
1187 sizeFunc _size;
1188 findFunc _find;
1189 beginFunc _begin;
1190 beginFunc _end;
1191 advanceFunc _advance;
1192 getFunc _getKey;
1193 getFunc _getValue;
1194 destroyIterFunc _destroyIter;
1195 equalIterFunc _equalIter;
1196 copyIterFunc _copyIter;
1197
1198 template<class T>
1199 static int sizeImpl(const void *p)
1200 { return int(std::distance(static_cast<const T*>(p)->begin(),
1201 static_cast<const T*>(p)->end())); }
1202
1203 template<class T>
1204 static void findImpl(const void *container, const void *p, void **iterator)
1205 { IteratorOwner<typename T::const_iterator>::assign(iterator,
1206 static_cast<const T*>(container)->find(*static_cast<const typename T::key_type*>(p))); }
1207
1208 template<class T>
1209 static void advanceImpl(void **p, int step)
1210 { std::advance(*static_cast<typename T::const_iterator*>(*p), step); }
1211
1212 template<class T>
1213 static void beginImpl(const void *container, void **iterator)
1214 { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->begin()); }
1215
1216 template<class T>
1217 static void endImpl(const void *container, void **iterator)
1218 { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->end()); }
1219
1220 template<class T>
1221 static VariantData getKeyImpl(void * const *iterator, int metaTypeId, uint flags)
1222 { return VariantData(metaTypeId, &AssociativeContainerAccessor<T>::getKey(*static_cast<typename T::const_iterator*>(*iterator)), flags); }
1223
1224 template<class T>
1225 static VariantData getValueImpl(void * const *iterator, int metaTypeId, uint flags)
1226 { return VariantData(metaTypeId, &AssociativeContainerAccessor<T>::getValue(*static_cast<typename T::const_iterator*>(*iterator)), flags); }
1227
1228public:
1229 template<class T> QAssociativeIterableImpl(const T*p)
1230 : _iterable(p)
1231 , _iterator(nullptr)
1232 , _metaType_id_key(qMetaTypeId<typename T::key_type>())
1233 , _metaType_flags_key(QTypeInfo<typename T::key_type>::isPointer)
1234 , _metaType_id_value(qMetaTypeId<typename T::mapped_type>())
1235 , _metaType_flags_value(QTypeInfo<typename T::mapped_type>::isPointer)
1236 , _size(sizeImpl<T>)
1237 , _find(findImpl<T>)
1238 , _begin(beginImpl<T>)
1239 , _end(endImpl<T>)
1240 , _advance(advanceImpl<T>)
1241 , _getKey(getKeyImpl<T>)
1242 , _getValue(getValueImpl<T>)
1243 , _destroyIter(IteratorOwner<typename T::const_iterator>::destroy)
1244 , _equalIter(IteratorOwner<typename T::const_iterator>::equal)
1245 , _copyIter(IteratorOwner<typename T::const_iterator>::assign)
1246 {
1247 }
1248
1249 QAssociativeIterableImpl()
1250 : _iterable(nullptr)
1251 , _iterator(nullptr)
1252 , _metaType_id_key(QMetaType::UnknownType)
1253 , _metaType_flags_key(0)
1254 , _metaType_id_value(QMetaType::UnknownType)
1255 , _metaType_flags_value(0)
1256 , _size(nullptr)
1257 , _find(nullptr)
1258 , _begin(nullptr)
1259 , _end(nullptr)
1260 , _advance(nullptr)
1261 , _getKey(nullptr)
1262 , _getValue(nullptr)
1263 , _destroyIter(nullptr)
1264 , _equalIter(nullptr)
1265 , _copyIter(nullptr)
1266 {
1267 }
1268
1269 inline void begin() { _begin(_iterable, &_iterator); }
1270 inline void end() { _end(_iterable, &_iterator); }
1271 inline bool equal(const QAssociativeIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); }
1272 inline QAssociativeIterableImpl &advance(int i) { _advance(&_iterator, i); return *this; }
1273
1274 inline void destroyIter() { _destroyIter(&_iterator); }
1275
1276 inline VariantData getCurrentKey() const { return _getKey(&_iterator, _metaType_id_key, _metaType_flags_key); }
1277 inline VariantData getCurrentValue() const { return _getValue(&_iterator, _metaType_id_value, _metaType_flags_value); }
1278
1279 inline void find(const VariantData &key)
1280 { _find(_iterable, key.data, &_iterator); }
1281
1282 int size() const { Q_ASSERT(_iterable); return _size(_iterable); }
1283
1284 void copy(const QAssociativeIterableImpl &other)
1285 {
1286 *this = other;
1287 _copyIter(&_iterator, &other._iterator);
1288 }
1289};
1290QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QAssociativeIterableImpl, Q_MOVABLE_TYPE)
1291
1292template<typename From>
1293struct QAssociativeIterableConvertFunctor
1294{
1295 QAssociativeIterableImpl operator()(const From& f) const
1296 {
1297 return QAssociativeIterableImpl(&f);
1298 }
1299};
1300
1301class QPairVariantInterfaceImpl
1302{
1303 const void *_pair;
1304 int _metaType_id_first;
1305 uint _metaType_flags_first;
1306 int _metaType_id_second;
1307 uint _metaType_flags_second;
1308
1309 typedef VariantData (*getFunc)(const void * const *p, int metaTypeId, uint flags);
1310
1311 getFunc _getFirst;
1312 getFunc _getSecond;
1313
1314 template<class T>
1315 static VariantData getFirstImpl(const void * const *pair, int metaTypeId, uint flags)
1316 { return VariantData(metaTypeId, &static_cast<const T*>(*pair)->first, flags); }
1317 template<class T>
1318 static VariantData getSecondImpl(const void * const *pair, int metaTypeId, uint flags)
1319 { return VariantData(metaTypeId, &static_cast<const T*>(*pair)->second, flags); }
1320
1321public:
1322 template<class T> QPairVariantInterfaceImpl(const T*p)
1323 : _pair(p)
1324 , _metaType_id_first(qMetaTypeId<typename T::first_type>())
1325 , _metaType_flags_first(QTypeInfo<typename T::first_type>::isPointer)
1326 , _metaType_id_second(qMetaTypeId<typename T::second_type>())
1327 , _metaType_flags_second(QTypeInfo<typename T::second_type>::isPointer)
1328 , _getFirst(getFirstImpl<T>)
1329 , _getSecond(getSecondImpl<T>)
1330 {
1331 }
1332
1333 QPairVariantInterfaceImpl()
1334 : _pair(nullptr)
1335 , _metaType_id_first(QMetaType::UnknownType)
1336 , _metaType_flags_first(0)
1337 , _metaType_id_second(QMetaType::UnknownType)
1338 , _metaType_flags_second(0)
1339 , _getFirst(nullptr)
1340 , _getSecond(nullptr)
1341 {
1342 }
1343
1344 inline VariantData first() const { return _getFirst(&_pair, _metaType_id_first, _metaType_flags_first); }
1345 inline VariantData second() const { return _getSecond(&_pair, _metaType_id_second, _metaType_flags_second); }
1346};
1347QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QPairVariantInterfaceImpl, Q_MOVABLE_TYPE)
1348
1349template<typename From>
1350struct QPairVariantInterfaceConvertFunctor;
1351
1352template<typename T, typename U>
1353struct QPairVariantInterfaceConvertFunctor<QPair<T, U> >
1354{
1355 QPairVariantInterfaceImpl operator()(const QPair<T, U>& f) const
1356 {
1357 return QPairVariantInterfaceImpl(&f);
1358 }
1359};
1360
1361template<typename T, typename U>
1362struct QPairVariantInterfaceConvertFunctor<std::pair<T, U> >
1363{
1364 QPairVariantInterfaceImpl operator()(const std::pair<T, U>& f) const
1365 {
1366 return QPairVariantInterfaceImpl(&f);
1367 }
1368};
1369
1370}
1371
1372class QObject;
1373class QWidget;
1374
1375#define QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER(Name) \
1376 template <class T> class Name; \
1377
1378QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER)
1379
1380namespace QtPrivate
1381{
1382 template<typename T>
1383 struct IsPointerToTypeDerivedFromQObject
1384 {
1385 enum { Value = false };
1386 };
1387
1388 // Specialize to avoid sizeof(void) warning
1389 template<>
1390 struct IsPointerToTypeDerivedFromQObject<void*>
1391 {
1392 enum { Value = false };
1393 };
1394 template<>
1395 struct IsPointerToTypeDerivedFromQObject<const void*>
1396 {
1397 enum { Value = false };
1398 };
1399 template<>
1400 struct IsPointerToTypeDerivedFromQObject<QObject*>
1401 {
1402 enum { Value = true };
1403 };
1404
1405 template<typename T>
1406 struct IsPointerToTypeDerivedFromQObject<T*>
1407 {
1408 typedef qint8 yes_type;
1409 typedef qint64 no_type;
1410
1411#ifndef QT_NO_QOBJECT
1412 static yes_type checkType(QObject* );
1413#endif
1414 static no_type checkType(...);
1415 Q_STATIC_ASSERT_X(sizeof(T), "Type argument of Q_DECLARE_METATYPE(T*) must be fully defined");
1416 enum { Value = sizeof(checkType(static_cast<T*>(nullptr))) == sizeof(yes_type) };
1417 };
1418
1419 template<typename T, typename Enable = void>
1420 struct IsGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; };
1421
1422 template<typename T>
1423 struct IsGadgetHelper<T, typename T::QtGadgetHelper>
1424 {
1425 template <typename X>
1426 static char checkType(void (X::*)());
1427 static void *checkType(void (T::*)());
1428 enum {
1429 IsRealGadget = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *),
1430 IsGadgetOrDerivedFrom = true
1431 };
1432 };
1433
1434 template<typename T, typename Enable = void>
1435 struct IsPointerToGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; };
1436
1437 template<typename T>
1438 struct IsPointerToGadgetHelper<T*, typename T::QtGadgetHelper>
1439 {
1440 using BaseType = T;
1441 template <typename X>
1442 static char checkType(void (X::*)());
1443 static void *checkType(void (T::*)());
1444 enum {
1445 IsRealGadget = !IsPointerToTypeDerivedFromQObject<T*>::Value && sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *),
1446 IsGadgetOrDerivedFrom = !IsPointerToTypeDerivedFromQObject<T*>::Value
1447 };
1448 };
1449
1450
1451 template<typename T> char qt_getEnumMetaObject(const T&);
1452
1453 template<typename T>
1454 struct IsQEnumHelper {
1455 static const T &declval();
1456 // If the type was declared with Q_ENUM, the friend qt_getEnumMetaObject() declared in the
1457 // Q_ENUM macro will be chosen by ADL, and the return type will be QMetaObject*.
1458 // Otherwise the chosen overload will be the catch all template function
1459 // qt_getEnumMetaObject(T) which returns 'char'
1460 enum { Value = sizeof(qt_getEnumMetaObject(declval())) == sizeof(QMetaObject*) };
1461 };
1462 template<> struct IsQEnumHelper<void> { enum { Value = false }; };
1463
1464 template<typename T, typename Enable = void>
1465 struct MetaObjectForType
1466 {
1467 static inline const QMetaObject *value() { return nullptr; }
1468 };
1469 template<>
1470 struct MetaObjectForType<void>
1471 {
1472 static inline const QMetaObject *value() { return nullptr; }
1473 };
1474 template<typename T>
1475 struct MetaObjectForType<T*, typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value>::type>
1476 {
1477 static inline const QMetaObject *value() { return &T::staticMetaObject; }
1478 };
1479 template<typename T>
1480 struct MetaObjectForType<T, typename std::enable_if<IsGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
1481 {
1482 static inline const QMetaObject *value() { return &T::staticMetaObject; }
1483 };
1484 template<typename T>
1485 struct MetaObjectForType<T, typename std::enable_if<IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
1486 {
1487 static inline const QMetaObject *value() { return &IsPointerToGadgetHelper<T>::BaseType::staticMetaObject; }
1488 };
1489 template<typename T>
1490 struct MetaObjectForType<T, typename std::enable_if<IsQEnumHelper<T>::Value>::type >
1491 {
1492 static inline const QMetaObject *value() { return qt_getEnumMetaObject(T()); }
1493 };
1494
1495 template<typename T>
1496 struct IsSharedPointerToTypeDerivedFromQObject
1497 {
1498 enum { Value = false };
1499 };
1500
1501 template<typename T>
1502 struct IsSharedPointerToTypeDerivedFromQObject<QSharedPointer<T> > : IsPointerToTypeDerivedFromQObject<T*>
1503 {
1504 };
1505
1506 template<typename T>
1507 struct IsWeakPointerToTypeDerivedFromQObject
1508 {
1509 enum { Value = false };
1510 };
1511
1512 template<typename T>
1513 struct IsWeakPointerToTypeDerivedFromQObject<QWeakPointer<T> > : IsPointerToTypeDerivedFromQObject<T*>
1514 {
1515 };
1516
1517 template<typename T>
1518 struct IsTrackingPointerToTypeDerivedFromQObject
1519 {
1520 enum { Value = false };
1521 };
1522
1523 template<typename T>
1524 struct IsTrackingPointerToTypeDerivedFromQObject<QPointer<T> >
1525 {
1526 enum { Value = true };
1527 };
1528
1529 template<typename T>
1530 struct IsSequentialContainer
1531 {
1532 enum { Value = false };
1533 };
1534
1535 template<typename T>
1536 struct IsAssociativeContainer
1537 {
1538 enum { Value = false };
1539 };
1540
1541 template<typename T, bool = QtPrivate::IsSequentialContainer<T>::Value>
1542 struct SequentialContainerConverterHelper
1543 {
1544 static bool registerConverter(int)
1545 {
1546 return false;
1547 }
1548 };
1549
1550 template<typename T, bool = QMetaTypeId2<typename T::value_type>::Defined>
1551 struct ValueTypeIsMetaType
1552 {
1553 static bool registerConverter(int)
1554 {
1555 return false;
1556 }
1557 };
1558
1559 template<typename T>
1560 struct SequentialContainerConverterHelper<T, true> : ValueTypeIsMetaType<T>
1561 {
1562 };
1563
1564 template<typename T, bool = QtPrivate::IsAssociativeContainer<T>::Value>
1565 struct AssociativeContainerConverterHelper
1566 {
1567 static bool registerConverter(int)
1568 {
1569 return false;
1570 }
1571 };
1572
1573 template<typename T, bool = QMetaTypeId2<typename T::mapped_type>::Defined>
1574 struct AssociativeValueTypeIsMetaType
1575 {
1576 static bool registerConverter(int)
1577 {
1578 return false;
1579 }
1580 };
1581
1582 template<typename T, bool = QMetaTypeId2<typename T::key_type>::Defined>
1583 struct KeyAndValueTypeIsMetaType
1584 {
1585 static bool registerConverter(int)
1586 {
1587 return false;
1588 }
1589 };
1590
1591 template<typename T>
1592 struct KeyAndValueTypeIsMetaType<T, true> : AssociativeValueTypeIsMetaType<T>
1593 {
1594 };
1595
1596 template<typename T>
1597 struct AssociativeContainerConverterHelper<T, true> : KeyAndValueTypeIsMetaType<T>
1598 {
1599 };
1600
1601 template<typename T, bool = QMetaTypeId2<typename T::first_type>::Defined
1602 && QMetaTypeId2<typename T::second_type>::Defined>
1603 struct IsMetaTypePair
1604 {
1605 static bool registerConverter(int)
1606 {
1607 return false;
1608 }
1609 };
1610
1611 template<typename T>
1612 struct IsMetaTypePair<T, true>
1613 {
1614 inline static bool registerConverter(int id);
1615 };
1616
1617 template<typename T>
1618 struct IsPair
1619 {
1620 static bool registerConverter(int)
1621 {
1622 return false;
1623 }
1624 };
1625 template<typename T, typename U>
1626 struct IsPair<QPair<T, U> > : IsMetaTypePair<QPair<T, U> > {};
1627 template<typename T, typename U>
1628 struct IsPair<std::pair<T, U> > : IsMetaTypePair<std::pair<T, U> > {};
1629
1630 template<typename T>
1631 struct MetaTypePairHelper : IsPair<T> {};
1632
1633 template<typename T, typename = void>
1634 struct MetaTypeSmartPointerHelper
1635 {
1636 static bool registerConverter(int) { return false; }
1637 };
1638
1639 Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type);
1640} // namespace QtPrivate
1641
1642template <typename T, int =
1643 QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject :
1644 QtPrivate::IsGadgetHelper<T>::IsRealGadget ? QMetaType::IsGadget :
1645 QtPrivate::IsPointerToGadgetHelper<T>::IsRealGadget ? QMetaType::PointerToGadget :
1646 QtPrivate::IsQEnumHelper<T>::Value ? QMetaType::IsEnumeration : 0>
1647struct QMetaTypeIdQObject
1648{
1649 enum {
1650 Defined = 0
1651 };
1652};
1653
1654template <typename T>
1655struct QMetaTypeId : public QMetaTypeIdQObject<T>
1656{
1657};
1658
1659template <typename T>
1660struct QMetaTypeId2
1661{
1662 enum { Defined = QMetaTypeId<T>::Defined, IsBuiltIn=false };
1663 static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }
1664};
1665
1666template <typename T>
1667struct QMetaTypeId2<const T&> : QMetaTypeId2<T> {};
1668
1669template <typename T>
1670struct QMetaTypeId2<T&> { enum {Defined = false }; };
1671
1672namespace QtPrivate {
1673 template <typename T, bool Defined = QMetaTypeId2<T>::Defined>
1674 struct QMetaTypeIdHelper {
1675 static inline Q_DECL_CONSTEXPR int qt_metatype_id()
1676 { return QMetaTypeId2<T>::qt_metatype_id(); }
1677 };
1678 template <typename T> struct QMetaTypeIdHelper<T, false> {
1679 static inline Q_DECL_CONSTEXPR int qt_metatype_id()
1680 { return -1; }
1681 };
1682
1683 // Function pointers don't derive from QObject
1684 template <typename Result, typename... Args>
1685 struct IsPointerToTypeDerivedFromQObject<Result(*)(Args...)> { enum { Value = false }; };
1686
1687 template<typename T>
1688 struct QMetaTypeTypeFlags
1689 {
1690 enum { Flags = (QTypeInfoQuery<T>::isRelocatable ? QMetaType::MovableType : 0)
1691 | (QTypeInfo<T>::isComplex ? QMetaType::NeedsConstruction : 0)
1692 | (QTypeInfo<T>::isComplex ? QMetaType::NeedsDestruction : 0)
1693 | (IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject : 0)
1694 | (IsSharedPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::SharedPointerToQObject : 0)
1695 | (IsWeakPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::WeakPointerToQObject : 0)
1696 | (IsTrackingPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::TrackingPointerToQObject : 0)
1697 | (std::is_enum<T>::value ? QMetaType::IsEnumeration : 0)
1698 | (IsGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::IsGadget : 0)
1699 | (IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::PointerToGadget : 0)
1700 };
1701 };
1702
1703 template<typename T, bool defined>
1704 struct MetaTypeDefinedHelper
1705 {
1706 enum DefinedType { Defined = defined };
1707 };
1708
1709 template<typename SmartPointer>
1710 struct QSmartPointerConvertFunctor
1711 {
1712 QObject* operator()(const SmartPointer &p) const
1713 {
1714 return p.operator->();
1715 }
1716 };
1717
1718 template<typename T>
1719 struct QSmartPointerConvertFunctor<QWeakPointer<T> >
1720 {
1721 QObject* operator()(const QWeakPointer<T> &p) const
1722 {
1723 return p.data();
1724 }
1725 };
1726}
1727
1728template <typename T>
1729int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName
1730#ifndef Q_CLANG_QDOC
1731 , T * dummy = 0
1732 , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType defined = QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined
1733#endif
1734)
1735{
1736#ifndef QT_NO_QOBJECT
1737 Q_ASSERT_X(normalizedTypeName == QMetaObject::normalizedType(normalizedTypeName.constData()), "qRegisterNormalizedMetaType", "qRegisterNormalizedMetaType was called with a not normalized type name, please call qRegisterMetaType instead.");
1738#endif
1739 const int typedefOf = dummy ? -1 : QtPrivate::QMetaTypeIdHelper<T>::qt_metatype_id();
1740 if (typedefOf != -1)
1741 return QMetaType::registerNormalizedTypedef(normalizedTypeName, typedefOf);
1742
1743 QMetaType::TypeFlags flags(QtPrivate::QMetaTypeTypeFlags<T>::Flags);
1744
1745 if (defined)
1746 flags |= QMetaType::WasDeclaredAsMetaType;
1747
1748 const int id = QMetaType::registerNormalizedType(normalizedTypeName,
1749 QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Destruct,
1750 QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Construct,
1751 int(sizeof(T)),
1752 flags,
1753 QtPrivate::MetaObjectForType<T>::value());
1754
1755 if (id > 0) {
1756 QtPrivate::SequentialContainerConverterHelper<T>::registerConverter(id);
1757 QtPrivate::AssociativeContainerConverterHelper<T>::registerConverter(id);
1758 QtPrivate::MetaTypePairHelper<T>::registerConverter(id);
1759 QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter(id);
1760 }
1761
1762 return id;
1763}
1764
1765template <typename T>
1766int qRegisterMetaType(const char *typeName
1767#ifndef Q_CLANG_QDOC
1768 , T * dummy = nullptr
1769 , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType defined = QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined
1770#endif
1771)
1772{
1773#ifdef QT_NO_QOBJECT
1774 QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = typeName;
1775#else
1776 QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
1777#endif
1778 return qRegisterNormalizedMetaType<T>(normalizedTypeName, dummy, defined);
1779}
1780
1781#ifndef QT_NO_DATASTREAM
1782template <typename T>
1783void qRegisterMetaTypeStreamOperators(const char *typeName
1784#ifndef Q_CLANG_QDOC
1785 , T * /* dummy */ = nullptr
1786#endif
1787)
1788{
1789 qRegisterMetaType<T>(typeName);
1790 QMetaType::registerStreamOperators(typeName, QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Save,
1791 QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Load);
1792}
1793#endif // QT_NO_DATASTREAM
1794
1795template <typename T>
1796inline Q_DECL_CONSTEXPR int qMetaTypeId()
1797{
1798 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");
1799 return QMetaTypeId2<T>::qt_metatype_id();
1800}
1801
1802template <typename T>
1803inline Q_DECL_CONSTEXPR int qRegisterMetaType()
1804{
1805 return qMetaTypeId<T>();
1806}
1807
1808#if QT_DEPRECATED_SINCE(5, 1) && !defined(Q_CLANG_QDOC)
1809// There used to be a T *dummy = 0 argument in Qt 4.0 to support MSVC6
1810template <typename T>
1811QT_DEPRECATED inline Q_DECL_CONSTEXPR int qMetaTypeId(T *)
1812{ return qMetaTypeId<T>(); }
1813#ifndef Q_CC_SUN
1814template <typename T>
1815QT_DEPRECATED inline Q_DECL_CONSTEXPR int qRegisterMetaType(T *)
1816{ return qRegisterMetaType<T>(); }
1817#endif
1818#endif
1819
1820#ifndef QT_NO_QOBJECT
1821template <typename T>
1822struct QMetaTypeIdQObject<T*, QMetaType::PointerToQObject>
1823{
1824 enum {
1825 Defined = 1
1826 };
1827
1828 static int qt_metatype_id()
1829 {
1830 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1831 if (const int id = metatype_id.loadAcquire())
1832 return id;
1833 const char * const cName = T::staticMetaObject.className();
1834 QByteArray typeName;
1835 typeName.reserve(int(strlen(cName)) + 1);
1836 typeName.append(cName).append('*');
1837 const int newId = qRegisterNormalizedMetaType<T*>(
1838 typeName,
1839 reinterpret_cast<T**>(quintptr(-1)));
1840 metatype_id.storeRelease(newId);
1841 return newId;
1842 }
1843};
1844
1845template <typename T>
1846struct QMetaTypeIdQObject<T, QMetaType::IsGadget>
1847{
1848 enum {
1849 Defined = std::is_default_constructible<T>::value
1850 };
1851
1852 static int qt_metatype_id()
1853 {
1854 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1855 if (const int id = metatype_id.loadAcquire())
1856 return id;
1857 const char * const cName = T::staticMetaObject.className();
1858 const int newId = qRegisterNormalizedMetaType<T>(
1859 cName,
1860 reinterpret_cast<T*>(quintptr(-1)));
1861 metatype_id.storeRelease(newId);
1862 return newId;
1863 }
1864};
1865
1866template <typename T>
1867struct QMetaTypeIdQObject<T*, QMetaType::PointerToGadget>
1868{
1869 enum {
1870 Defined = 1
1871 };
1872
1873 static int qt_metatype_id()
1874 {
1875 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1876 if (const int id = metatype_id.loadAcquire())
1877 return id;
1878 const char * const cName = T::staticMetaObject.className();
1879 QByteArray typeName;
1880 typeName.reserve(int(strlen(cName)) + 1);
1881 typeName.append(cName).append('*');
1882 const int newId = qRegisterNormalizedMetaType<T*>(
1883 typeName,
1884 reinterpret_cast<T**>(quintptr(-1)));
1885 metatype_id.storeRelease(newId);
1886 return newId;
1887 }
1888};
1889
1890template <typename T>
1891struct QMetaTypeIdQObject<T, QMetaType::IsEnumeration>
1892{
1893 enum {
1894 Defined = 1
1895 };
1896
1897 static int qt_metatype_id()
1898 {
1899 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
1900 if (const int id = metatype_id.loadAcquire())
1901 return id;
1902 const char *eName = qt_getEnumName(T());
1903 const char *cName = qt_getEnumMetaObject(T())->className();
1904 QByteArray typeName;
1905 typeName.reserve(int(strlen(cName) + 2 + strlen(eName)));
1906 typeName.append(cName).append("::").append(eName);
1907 const int newId = qRegisterNormalizedMetaType<T>(
1908 typeName,
1909 reinterpret_cast<T*>(quintptr(-1)));
1910 metatype_id.storeRelease(newId);
1911 return newId;
1912 }
1913};
1914#endif
1915
1916#ifndef QT_NO_DATASTREAM
1917template <typename T>
1918inline int qRegisterMetaTypeStreamOperators()
1919{
1920 int id = qMetaTypeId<T>();
1921 QMetaType::registerStreamOperators(id, QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Save,
1922 QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Load);
1923 return id;
1924}
1925#endif
1926
1927#define Q_DECLARE_OPAQUE_POINTER(POINTER) \
1928 QT_BEGIN_NAMESPACE namespace QtPrivate { \
1929 template <> \
1930 struct IsPointerToTypeDerivedFromQObject<POINTER > \
1931 { \
1932 enum { Value = false }; \
1933 }; \
1934 } QT_END_NAMESPACE \
1935 /**/
1936
1937#ifndef Q_MOC_RUN
1938#define Q_DECLARE_METATYPE(TYPE) Q_DECLARE_METATYPE_IMPL(TYPE)
1939#define Q_DECLARE_METATYPE_IMPL(TYPE) \
1940 QT_BEGIN_NAMESPACE \
1941 template <> \
1942 struct QMetaTypeId< TYPE > \
1943 { \
1944 enum { Defined = 1 }; \
1945 static int qt_metatype_id() \
1946 { \
1947 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
1948 if (const int id = metatype_id.loadAcquire()) \
1949 return id; \
1950 const int newId = qRegisterMetaType< TYPE >(#TYPE, \
1951 reinterpret_cast< TYPE *>(quintptr(-1))); \
1952 metatype_id.storeRelease(newId); \
1953 return newId; \
1954 } \
1955 }; \
1956 QT_END_NAMESPACE
1957#endif // Q_MOC_RUN
1958
1959#define Q_DECLARE_BUILTIN_METATYPE(TYPE, METATYPEID, NAME) \
1960 QT_BEGIN_NAMESPACE \
1961 template<> struct QMetaTypeId2<NAME> \
1962 { \
1963 enum { Defined = 1, IsBuiltIn = true, MetaType = METATYPEID }; \
1964 static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return METATYPEID; } \
1965 }; \
1966 QT_END_NAMESPACE
1967
1968#define QT_FORWARD_DECLARE_STATIC_TYPES_ITER(TypeName, TypeId, Name) \
1969 class Name;
1970
1971QT_FOR_EACH_STATIC_CORE_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1972QT_FOR_EACH_STATIC_GUI_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1973QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
1974
1975#undef QT_FORWARD_DECLARE_STATIC_TYPES_ITER
1976
1977typedef QList<QVariant> QVariantList;
1978typedef QMap<QString, QVariant> QVariantMap;
1979typedef QHash<QString, QVariant> QVariantHash;
1980#ifdef Q_CLANG_QDOC
1981class QByteArrayList;
1982#else
1983typedef QList<QByteArray> QByteArrayList;
1984#endif
1985
1986#define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE) \
1987QT_BEGIN_NAMESPACE \
1988template <typename T> \
1989struct QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \
1990{ \
1991 enum { \
1992 Defined = QMetaTypeId2<T>::Defined \
1993 }; \
1994 static int qt_metatype_id() \
1995 { \
1996 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
1997 if (const int id = metatype_id.load()) \
1998 return id; \
1999 const char *tName = QMetaType::typeName(qMetaTypeId<T>()); \
2000 Q_ASSERT(tName); \
2001 const int tNameLen = int(qstrlen(tName)); \
2002 QByteArray typeName; \
2003 typeName.reserve(int(sizeof(#SINGLE_ARG_TEMPLATE)) + 1 + tNameLen + 1 + 1); \
2004 typeName.append(#SINGLE_ARG_TEMPLATE, int(sizeof(#SINGLE_ARG_TEMPLATE)) - 1) \
2005 .append('<').append(tName, tNameLen); \
2006 if (typeName.endsWith('>')) \
2007 typeName.append(' '); \
2008 typeName.append('>'); \
2009 const int newId = qRegisterNormalizedMetaType< SINGLE_ARG_TEMPLATE<T> >( \
2010 typeName, \
2011 reinterpret_cast< SINGLE_ARG_TEMPLATE<T> *>(quintptr(-1))); \
2012 metatype_id.storeRelease(newId); \
2013 return newId; \
2014 } \
2015}; \
2016namespace QtPrivate { \
2017template<typename T> \
2018struct IsSequentialContainer<SINGLE_ARG_TEMPLATE<T> > \
2019{ \
2020 enum { Value = true }; \
2021}; \
2022} \
2023QT_END_NAMESPACE
2024
2025#define Q_DECLARE_METATYPE_TEMPLATE_2ARG(DOUBLE_ARG_TEMPLATE) \
2026QT_BEGIN_NAMESPACE \
2027template<typename T, typename U> \
2028struct QMetaTypeId< DOUBLE_ARG_TEMPLATE<T, U> > \
2029{ \
2030 enum { \
2031 Defined = QMetaTypeId2<T>::Defined && QMetaTypeId2<U>::Defined \
2032 }; \
2033 static int qt_metatype_id() \
2034 { \
2035 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
2036 if (const int id = metatype_id.loadAcquire()) \
2037 return id; \
2038 const char *tName = QMetaType::typeName(qMetaTypeId<T>()); \
2039 const char *uName = QMetaType::typeName(qMetaTypeId<U>()); \
2040 Q_ASSERT(tName); \
2041 Q_ASSERT(uName); \
2042 const int tNameLen = int(qstrlen(tName)); \
2043 const int uNameLen = int(qstrlen(uName)); \
2044 QByteArray typeName; \
2045 typeName.reserve(int(sizeof(#DOUBLE_ARG_TEMPLATE)) + 1 + tNameLen + 1 + uNameLen + 1 + 1); \
2046 typeName.append(#DOUBLE_ARG_TEMPLATE, int(sizeof(#DOUBLE_ARG_TEMPLATE)) - 1) \
2047 .append('<').append(tName, tNameLen).append(',').append(uName, uNameLen); \
2048 if (typeName.endsWith('>')) \
2049 typeName.append(' '); \
2050 typeName.append('>'); \
2051 const int newId = qRegisterNormalizedMetaType< DOUBLE_ARG_TEMPLATE<T, U> >(\
2052 typeName, \
2053 reinterpret_cast< DOUBLE_ARG_TEMPLATE<T, U> *>(quintptr(-1))); \
2054 metatype_id.storeRelease(newId); \
2055 return newId; \
2056 } \
2057}; \
2058QT_END_NAMESPACE
2059
2060namespace QtPrivate {
2061
2062template<typename T, bool /* isSharedPointerToQObjectDerived */ = false>
2063struct SharedPointerMetaTypeIdHelper
2064{
2065 enum {
2066 Defined = 0
2067 };
2068 static int qt_metatype_id()
2069 {
2070 return -1;
2071 }
2072};
2073
2074}
2075
2076#define Q_DECLARE_SMART_POINTER_METATYPE(SMART_POINTER) \
2077QT_BEGIN_NAMESPACE \
2078namespace QtPrivate { \
2079template<typename T> \
2080struct SharedPointerMetaTypeIdHelper<SMART_POINTER<T>, true> \
2081{ \
2082 enum { \
2083 Defined = 1 \
2084 }; \
2085 static int qt_metatype_id() \
2086 { \
2087 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
2088 if (const int id = metatype_id.loadAcquire()) \
2089 return id; \
2090 const char * const cName = T::staticMetaObject.className(); \
2091 QByteArray typeName; \
2092 typeName.reserve(int(sizeof(#SMART_POINTER) + 1 + strlen(cName) + 1)); \
2093 typeName.append(#SMART_POINTER, int(sizeof(#SMART_POINTER)) - 1) \
2094 .append('<').append(cName).append('>'); \
2095 const int newId = qRegisterNormalizedMetaType< SMART_POINTER<T> >( \
2096 typeName, \
2097 reinterpret_cast< SMART_POINTER<T> *>(quintptr(-1))); \
2098 metatype_id.storeRelease(newId); \
2099 return newId; \
2100 } \
2101}; \
2102template<typename T> \
2103struct MetaTypeSmartPointerHelper<SMART_POINTER<T> , \
2104 typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value>::type> \
2105{ \
2106 static bool registerConverter(int id) \
2107 { \
2108 const int toId = QMetaType::QObjectStar; \
2109 if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { \
2110 QtPrivate::QSmartPointerConvertFunctor<SMART_POINTER<T> > o; \
2111 static const QtPrivate::ConverterFunctor<SMART_POINTER<T>, \
2112 QObject*, \
2113 QSmartPointerConvertFunctor<SMART_POINTER<T> > > f(o); \
2114 return QMetaType::registerConverterFunction(&f, id, toId); \
2115 } \
2116 return true; \
2117 } \
2118}; \
2119} \
2120template <typename T> \
2121struct QMetaTypeId< SMART_POINTER<T> > \
2122 : QtPrivate::SharedPointerMetaTypeIdHelper< SMART_POINTER<T>, \
2123 QtPrivate::IsPointerToTypeDerivedFromQObject<T*>::Value> \
2124{ \
2125};\
2126QT_END_NAMESPACE
2127
2128#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER(TEMPLATENAME) \
2129 QT_BEGIN_NAMESPACE \
2130 template <class T> class TEMPLATENAME; \
2131 QT_END_NAMESPACE \
2132 Q_DECLARE_METATYPE_TEMPLATE_1ARG(TEMPLATENAME)
2133
2134QT_END_NAMESPACE
2135
2136QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER)
2137
2138#undef Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER
2139
2140#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE Q_DECLARE_METATYPE_TEMPLATE_1ARG
2141
2142Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::vector)
2143Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::list)
2144
2145#define Q_FORWARD_DECLARE_METATYPE_TEMPLATE_2ARG_ITER(TEMPLATENAME, CPPTYPE) \
2146 QT_BEGIN_NAMESPACE \
2147 template <class T1, class T2> CPPTYPE TEMPLATENAME; \
2148 QT_END_NAMESPACE \
2149
2150QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(Q_FORWARD_DECLARE_METATYPE_TEMPLATE_2ARG_ITER)
2151
2152#undef Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER
2153
2154#define Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(TEMPLATENAME) \
2155 QT_BEGIN_NAMESPACE \
2156 namespace QtPrivate { \
2157 template<typename T, typename U> \
2158 struct IsAssociativeContainer<TEMPLATENAME<T, U> > \
2159 { \
2160 enum { Value = true }; \
2161 }; \
2162 } \
2163 QT_END_NAMESPACE \
2164 Q_DECLARE_METATYPE_TEMPLATE_2ARG(TEMPLATENAME)
2165
2166Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QHash)
2167Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(QMap)
2168Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(std::map)
2169
2170Q_DECLARE_METATYPE_TEMPLATE_2ARG(QPair)
2171Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::pair)
2172
2173#define Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER(TEMPLATENAME) \
2174 Q_DECLARE_SMART_POINTER_METATYPE(TEMPLATENAME)
2175
2176
2177QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER)
2178
2179QT_BEGIN_NAMESPACE
2180
2181#undef Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER
2182
2183inline QMetaType::QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
2184 TypedConstructor creator,
2185 TypedDestructor deleter,
2186 SaveOperator saveOp,
2187 LoadOperator loadOp,
2188 Constructor constructor,
2189 Destructor destructor,
2190 uint size,
2191 uint theTypeFlags,
2192 int typeId,
2193 const QMetaObject *_metaObject)
2194 : m_typedConstructor(creator)
2195 , m_typedDestructor(deleter)
2196 , m_saveOp(saveOp)
2197 , m_loadOp(loadOp)
2198 , m_constructor(constructor)
2199 , m_destructor(destructor)
2200 , m_extension(nullptr)
2201 , m_size(size)
2202 , m_typeFlags(theTypeFlags)
2203 , m_extensionFlags(extensionFlags)
2204 , m_typeId(typeId)
2205 , m_metaObject(_metaObject)
2206{
2207 if (Q_UNLIKELY(isExtended(CtorEx) || typeId == QMetaType::Void))
2208 ctor(info);
2209}
2210
2211inline QMetaType::~QMetaType()
2212{
2213 if (Q_UNLIKELY(isExtended(DtorEx)))
2214 dtor();
2215}
2216
2217inline bool QMetaType::isValid() const
2218{
2219 return m_typeId != UnknownType;
2220}
2221
2222inline bool QMetaType::isRegistered() const
2223{
2224 return isValid();
2225}
2226
2227inline int QMetaType::id() const
2228{
2229 return m_typeId;
2230}
2231
2232inline void *QMetaType::create(const void *copy) const
2233{
2234 // ### TODO Qt6 remove the extension
2235 return createExtended(copy);
2236}
2237
2238inline void QMetaType::destroy(void *data) const
2239{
2240 // ### TODO Qt6 remove the extension
2241 destroyExtended(data);
2242}
2243
2244inline void *QMetaType::construct(void *where, const void *copy) const
2245{
2246 if (Q_UNLIKELY(isExtended(ConstructEx)))
2247 return constructExtended(where, copy);
2248 return m_constructor(where, copy);
2249}
2250
2251inline void QMetaType::destruct(void *data) const
2252{
2253 if (Q_UNLIKELY(isExtended(DestructEx)))
2254 return destructExtended(data);
2255 if (Q_UNLIKELY(!data))
2256 return;
2257 m_destructor(data);
2258}
2259
2260inline int QMetaType::sizeOf() const
2261{
2262 if (Q_UNLIKELY(isExtended(SizeEx)))
2263 return sizeExtended();
2264 return m_size;
2265}
2266
2267inline QMetaType::TypeFlags QMetaType::flags() const
2268{
2269 if (Q_UNLIKELY(isExtended(FlagsEx)))
2270 return flagsExtended();
2271 return QMetaType::TypeFlags(m_typeFlags);
2272}
2273
2274inline const QMetaObject *QMetaType::metaObject() const
2275{
2276 if (Q_UNLIKELY(isExtended(MetaObjectEx)))
2277 return metaObjectExtended();
2278 return m_metaObject;
2279}
2280
2281QT_END_NAMESPACE
2282
2283
2284QT_FOR_EACH_STATIC_TYPE(Q_DECLARE_BUILTIN_METATYPE)
2285
2286Q_DECLARE_METATYPE(QtMetaTypePrivate::QSequentialIterableImpl)
2287Q_DECLARE_METATYPE(QtMetaTypePrivate::QAssociativeIterableImpl)
2288Q_DECLARE_METATYPE(QtMetaTypePrivate::QPairVariantInterfaceImpl)
2289
2290QT_BEGIN_NAMESPACE
2291
2292template <typename T>
2293inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter(int id)
2294{
2295 const int toId = qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
2296 if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
2297 QtMetaTypePrivate::QPairVariantInterfaceConvertFunctor<T> o;
2298 static const QtPrivate::ConverterFunctor<T,
2299 QtMetaTypePrivate::QPairVariantInterfaceImpl,
2300 QtMetaTypePrivate::QPairVariantInterfaceConvertFunctor<T> > f(o);
2301 return QMetaType::registerConverterFunction(&f, id, toId);
2302 }
2303 return true;
2304}
2305
2306namespace QtPrivate {
2307 template<typename T>
2308 struct ValueTypeIsMetaType<T, true>
2309 {
2310 static bool registerConverter(int id)
2311 {
2312 const int toId = qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>();
2313 if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
2314 QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> o;
2315 static const QtPrivate::ConverterFunctor<T,
2316 QtMetaTypePrivate::QSequentialIterableImpl,
2317 QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> > f(o);
2318 return QMetaType::registerConverterFunction(&f, id, toId);
2319 }
2320 return true;
2321 }
2322 };
2323
2324 template<typename T>
2325 struct AssociativeValueTypeIsMetaType<T, true>
2326 {
2327 static bool registerConverter(int id)
2328 {
2329 const int toId = qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>();
2330 if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
2331 QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> o;
2332 static const QtPrivate::ConverterFunctor<T,
2333 QtMetaTypePrivate::QAssociativeIterableImpl,
2334 QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> > f(o);
2335 return QMetaType::registerConverterFunction(&f, id, toId);
2336 }
2337 return true;
2338 }
2339 };
2340}
2341
2342QT_END_NAMESPACE
2343
2344#endif // QMETATYPE_H
2345