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