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