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