1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
3// Copyright (C) 2021 Intel Corporation.
4// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
5
6#include "qmetatype.h"
7#include "qmetatype_p.h"
8#include "qobject.h"
9#include "qobjectdefs.h"
10#include "qdatetime.h"
11#include "qbytearray.h"
12#include "qreadwritelock.h"
13#include "qhash.h"
14#include "qmap.h"
15#include "qstring.h"
16#include "qstringlist.h"
17#include "qlist.h"
18#include "qlocale.h"
19#include "qdebug.h"
20#if QT_CONFIG(easingcurve)
21#include "qeasingcurve.h"
22#endif
23#include "quuid.h"
24#include "qvariant.h"
25#include "qdatastream.h"
26
27#if QT_CONFIG(regularexpression)
28# include "qregularexpression.h"
29#endif
30
31#ifndef QT_BOOTSTRAPPED
32# include "qbitarray.h"
33# include "qurl.h"
34# include "qvariant.h"
35# include "qjsonvalue.h"
36# include "qjsonobject.h"
37# include "qjsonarray.h"
38# include "qjsondocument.h"
39# include "qcborvalue.h"
40# include "qcborarray.h"
41# include "qcbormap.h"
42# include "qbytearraylist.h"
43# include "qmetaobject.h"
44# include "qsequentialiterable.h"
45# include "qassociativeiterable.h"
46#endif
47
48#if QT_CONFIG(itemmodel)
49# include "qabstractitemmodel.h"
50#endif
51
52#ifndef QT_NO_GEOM_VARIANT
53# include "qsize.h"
54# include "qpoint.h"
55# include "qrect.h"
56# include "qline.h"
57#endif
58
59#include <bitset>
60#include <new>
61#include <cstring>
62
63QT_BEGIN_NAMESPACE
64
65#define NS(x) QT_PREPEND_NAMESPACE(x)
66
67QT_IMPL_METATYPE_EXTERN_TAGGED(QtMetaTypePrivate::QPairVariantInterfaceImpl, QPairVariantInterfaceImpl)
68
69using QtMetaTypePrivate::isInterfaceFor;
70
71namespace {
72struct QMetaTypeDeleter
73{
74 const QtPrivate::QMetaTypeInterface *iface;
75 void operator()(void *data)
76 {
77 if (iface->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
78 operator delete(data, std::align_val_t(iface->alignment));
79 } else {
80 operator delete(data);
81 }
82 }
83};
84
85struct QMetaTypeCustomRegistry
86{
87
88#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
89 QMetaTypeCustomRegistry()
90 {
91 /* qfloat16 was neither a builtin, nor unconditionally registered
92 in QtCore in Qt <= 6.2.
93 Inserting it as an alias ensures that a QMetaType::id call
94 will get the correct built-in type-id (the interface pointers
95 might still not match, but we already deal with that case.
96 */
97 aliases.insert(key: "qfloat16", value: QtPrivate::qMetaTypeInterfaceForType<qfloat16>());
98 }
99#endif
100
101 QReadWriteLock lock;
102 QList<const QtPrivate::QMetaTypeInterface *> registry;
103 QHash<QByteArray, const QtPrivate::QMetaTypeInterface *> aliases;
104 // index of first empty (unregistered) type in registry, if any.
105 int firstEmpty = 0;
106
107 int registerCustomType(const QtPrivate::QMetaTypeInterface *cti)
108 {
109 // we got here because cti->typeId is 0, so this is a custom meta type
110 // (not read-only)
111 auto ti = const_cast<QtPrivate::QMetaTypeInterface *>(cti);
112 {
113 QWriteLocker l(&lock);
114 if (int id = ti->typeId.loadRelaxed())
115 return id;
116 QByteArray name =
117#ifndef QT_NO_QOBJECT
118 QMetaObject::normalizedType
119#endif
120 (type: ti->name);
121 if (auto ti2 = aliases.value(key: name)) {
122 const auto id = ti2->typeId.loadRelaxed();
123 ti->typeId.storeRelaxed(newValue: id);
124 return id;
125 }
126 aliases[name] = ti;
127 int size = registry.size();
128 while (firstEmpty < size && registry[firstEmpty])
129 ++firstEmpty;
130 if (firstEmpty < size) {
131 registry[firstEmpty] = ti;
132 ++firstEmpty;
133 } else {
134 registry.append(t: ti);
135 firstEmpty = registry.size();
136 }
137 ti->typeId.storeRelaxed(newValue: firstEmpty + QMetaType::User);
138 }
139 if (ti->legacyRegisterOp)
140 ti->legacyRegisterOp();
141 return ti->typeId.loadRelaxed();
142 };
143
144 void unregisterDynamicType(int id)
145 {
146 if (!id)
147 return;
148 Q_ASSERT(id > QMetaType::User);
149 QWriteLocker l(&lock);
150 int idx = id - QMetaType::User - 1;
151 auto &ti = registry[idx];
152
153 // We must unregister all names.
154 auto it = aliases.begin();
155 while (it != aliases.end()) {
156 if (it.value() == ti)
157 it = aliases.erase(it);
158 else
159 ++it;
160 }
161
162 ti = nullptr;
163
164 firstEmpty = std::min(a: firstEmpty, b: idx);
165 }
166
167 const QtPrivate::QMetaTypeInterface *getCustomType(int id)
168 {
169 QReadLocker l(&lock);
170 return registry.value(i: id - QMetaType::User - 1);
171 }
172};
173
174Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
175
176} // namespace
177
178// used by QVariant::save(): returns the name used in the Q_DECLARE_METATYPE
179// macro (one of them, indetermine which one)
180const char *QtMetaTypePrivate::typedefNameForType(const QtPrivate::QMetaTypeInterface *type_d)
181{
182 const char *name = nullptr;
183 if (!customTypeRegistry.exists())
184 return name;
185 QMetaTypeCustomRegistry *r = &*customTypeRegistry;
186
187 QByteArrayView officialName(type_d->name);
188 QReadLocker l(&r->lock);
189 auto it = r->aliases.constBegin();
190 auto end = r->aliases.constEnd();
191 for ( ; it != end; ++it) {
192 if (it.value() != type_d)
193 continue;
194 if (it.key() == officialName)
195 continue; // skip the official name
196 name = it.key().constData();
197 ++it;
198 break;
199 }
200
201#ifndef QT_NO_DEBUG
202 QByteArrayList otherNames;
203 for ( ; it != end; ++it) {
204 if (it.value() == type_d && it.key() != officialName)
205 otherNames << it.key();
206 }
207 l.unlock();
208 if (!otherNames.isEmpty())
209 qWarning(msg: "QMetaType: type %s has more than one typedef alias: %s, %s",
210 type_d->name, name, otherNames.join(sep: ", ").constData());
211#endif
212
213 return name;
214}
215
216/*!
217 \macro Q_DECLARE_OPAQUE_POINTER(PointerType)
218 \relates QMetaType
219 \since 5.0
220
221 This macro enables pointers to forward-declared types (\a PointerType)
222 to be registered with QMetaType using either Q_DECLARE_METATYPE()
223 or qRegisterMetaType().
224
225 \sa Q_DECLARE_METATYPE(), qRegisterMetaType()
226*/
227
228/*!
229 \macro Q_DECLARE_METATYPE(Type)
230 \relates QMetaType
231
232 This macro makes the type \a Type known to QMetaType as long as it
233 provides a public default constructor, a public copy constructor and
234 a public destructor.
235 It is needed to use the type \a Type as a custom type in QVariant.
236
237 This macro requires that \a Type is a fully defined type at the point where
238 it is used. For pointer types, it also requires that the pointed to type is
239 fully defined. Use in conjunction with Q_DECLARE_OPAQUE_POINTER() to
240 register pointers to forward declared types.
241
242 Ideally, this macro should be placed below the declaration of
243 the class or struct. If that is not possible, it can be put in
244 a private header file which has to be included every time that
245 type is used in a QVariant.
246
247 Adding a Q_DECLARE_METATYPE() makes the type known to all template
248 based functions, including QVariant. Note that if you intend to
249 use the type in \e queued signal and slot connections or in
250 QObject's property system, you also have to call
251 qRegisterMetaType() since the names are resolved at runtime.
252
253 This example shows a typical use case of Q_DECLARE_METATYPE():
254
255 \snippet code/src_corelib_kernel_qmetatype.cpp 0
256
257 If \c MyStruct is in a namespace, the Q_DECLARE_METATYPE() macro
258 has to be outside the namespace:
259
260 \snippet code/src_corelib_kernel_qmetatype.cpp 1
261
262 Since \c{MyStruct} is now known to QMetaType, it can be used in QVariant:
263
264 \snippet code/src_corelib_kernel_qmetatype.cpp 2
265
266 Some types are registered automatically and do not need this macro:
267
268 \list
269 \li Pointers to classes derived from QObject
270 \li QList<T>, QQueue<T>, QStack<T> or QSet<T>
271 where T is a registered meta type
272 \li QHash<T1, T2>, QMap<T1, T2> or QPair<T1, T2> where T1 and T2 are
273 registered meta types
274 \li QPointer<T>, QSharedPointer<T>, QWeakPointer<T>, where T is a class that derives from QObject
275 \li Enumerations registered with Q_ENUM or Q_FLAG
276 \li Classes that have a Q_GADGET macro
277 \endlist
278
279 \note This method also registers the stream and debug operators for the type if they
280 are visible at registration time. As this is done automatically in some places,
281 it is strongly recommended to declare the stream operators for a type directly
282 after the type itself. Because of the argument dependent lookup rules of C++, it is
283 also strongly recommended to declare the operators in the same namespace as the type itself.
284
285 The stream operators should have the following signatures:
286
287 \snippet code/src_corelib_kernel_qmetatype.cpp 6
288
289 \sa qRegisterMetaType()
290*/
291
292/*!
293 \macro Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(Container)
294 \relates QMetaType
295
296 This macro makes the container \a Container known to QMetaType as a sequential
297 container. This makes it possible to put an instance of Container<T> into
298 a QVariant, if T itself is known to QMetaType.
299
300 Note that all of the Qt sequential containers already have built-in
301 support, and it is not necessary to use this macro with them. The
302 std::vector and std::list containers also have built-in support.
303
304 This example shows a typical use of Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE():
305
306 \snippet code/src_corelib_kernel_qmetatype.cpp 10
307*/
308
309/*!
310 \macro Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(Container)
311 \relates QMetaType
312
313 This macro makes the container \a Container known to QMetaType as an associative
314 container. This makes it possible to put an instance of Container<T, U> into
315 a QVariant, if T and U are themselves known to QMetaType.
316
317 Note that all of the Qt associative containers already have built-in
318 support, and it is not necessary to use this macro with them. The
319 std::map container also has built-in support.
320
321 This example shows a typical use of Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE():
322
323 \snippet code/src_corelib_kernel_qmetatype.cpp 11
324*/
325
326/*!
327 \macro Q_DECLARE_SMART_POINTER_METATYPE(SmartPointer)
328 \relates QMetaType
329
330 This macro makes the smart pointer \a SmartPointer known to QMetaType as a
331 smart pointer. This makes it possible to put an instance of SmartPointer<T> into
332 a QVariant, if T is a type which inherits QObject.
333
334 Note that the QWeakPointer, QSharedPointer and QPointer already have built-in
335 support, and it is not necessary to use this macro with them.
336
337 This example shows a typical use of Q_DECLARE_SMART_POINTER_METATYPE():
338
339 \snippet code/src_corelib_kernel_qmetatype.cpp 13
340*/
341
342/*!
343 \enum QMetaType::Type
344
345 These are the built-in types supported by QMetaType:
346
347 \value Void \c void
348 \value Bool \c bool
349 \value Int \c int
350 \value UInt \c{unsigned int}
351 \value Double \c double
352 \value QChar QChar
353 \value QString QString
354 \value QByteArray QByteArray
355 \value Nullptr \c{std::nullptr_t}
356
357 \value VoidStar \c{void *}
358 \value Long \c{long}
359 \value LongLong LongLong
360 \value Short \c{short}
361 \value Char \c{char}
362 \value Char16 \c{char16_t}
363 \value Char32 \c{char32_t}
364 \value ULong \c{unsigned long}
365 \value ULongLong ULongLong
366 \value UShort \c{unsigned short}
367 \value SChar \c{signed char}
368 \value UChar \c{unsigned char}
369 \value Float \c float
370 \value Float16 qfloat16
371 \omitvalue Float128
372 \omitvalue BFloat16
373 \omitvalue Int128
374 \omitvalue UInt128
375 \value QObjectStar QObject *
376
377 \value QCursor QCursor
378 \value QDate QDate
379 \value QSize QSize
380 \value QTime QTime
381 \value QVariantList QVariantList
382 \value QPolygon QPolygon
383 \value QPolygonF QPolygonF
384 \value QColor QColor
385 \value QColorSpace QColorSpace (introduced in Qt 5.15)
386 \value QSizeF QSizeF
387 \value QRectF QRectF
388 \value QLine QLine
389 \value QTextLength QTextLength
390 \value QStringList QStringList
391 \value QVariantMap QVariantMap
392 \value QVariantHash QVariantHash
393 \value QVariantPair QVariantPair
394 \value QIcon QIcon
395 \value QPen QPen
396 \value QLineF QLineF
397 \value QTextFormat QTextFormat
398 \value QRect QRect
399 \value QPoint QPoint
400 \value QUrl QUrl
401 \value QRegularExpression QRegularExpression
402 \value QDateTime QDateTime
403 \value QPointF QPointF
404 \value QPalette QPalette
405 \value QFont QFont
406 \value QBrush QBrush
407 \value QRegion QRegion
408 \value QBitArray QBitArray
409 \value QImage QImage
410 \value QKeySequence QKeySequence
411 \value QSizePolicy QSizePolicy
412 \value QPixmap QPixmap
413 \value QLocale QLocale
414 \value QBitmap QBitmap
415 \value QTransform QTransform
416 \value QMatrix4x4 QMatrix4x4
417 \value QVector2D QVector2D
418 \value QVector3D QVector3D
419 \value QVector4D QVector4D
420 \value QQuaternion QQuaternion
421 \value QEasingCurve QEasingCurve
422 \value QJsonValue QJsonValue
423 \value QJsonObject QJsonObject
424 \value QJsonArray QJsonArray
425 \value QJsonDocument QJsonDocument
426 \value QCborValue QCborValue
427 \value QCborArray QCborArray
428 \value QCborMap QCborMap
429 \value QCborSimpleType QCborSimpleType
430 \value QModelIndex QModelIndex
431 \value QPersistentModelIndex QPersistentModelIndex (introduced in Qt 5.5)
432 \value QUuid QUuid
433 \value QByteArrayList QByteArrayList
434 \value QVariant QVariant
435
436 \value User Base value for user types
437 \value UnknownType This is an invalid type id. It is returned from QMetaType for types that are not registered
438
439 Additional types can be registered using qRegisterMetaType() or by calling
440 registerType().
441
442 \sa type(), typeName()
443*/
444
445/*!
446 \enum QMetaType::TypeFlag
447
448 The enum describes attributes of a type supported by QMetaType.
449
450 \value NeedsConstruction This type has a default constructor. If the flag is not set, instances can be safely initialized with memset to 0.
451 \value NeedsCopyConstruction (since 6.5) This type has a non-trivial copy constructor. If the flag is not set, instances can be copied with memcpy.
452 \value NeedsMoveConstruction (since 6.5) This type has a non-trivial move constructor. If the flag is not set, instances can be moved with memcpy.
453 \value NeedsDestruction This type has a non-trivial destructor. If the flag is not set, calls to the destructor are not necessary before discarding objects.
454 \value RelocatableType An instance of a type having this attribute can be safely moved to a different memory location using memcpy.
455 \omitvalue MovableType
456 \omitvalue SharedPointerToQObject
457 \value IsEnumeration This type is an enumeration.
458 \value IsUnsignedEnumeration If the type is an Enumeration, its underlying type is unsigned.
459 \value PointerToQObject This type is a pointer to a class derived from QObject.
460 \value IsPointer This type is a pointer to another type.
461 \omitvalue WeakPointerToQObject
462 \omitvalue TrackingPointerToQObject
463 \omitvalue IsGadget \omit (since Qt 5.5) This type is a Q_GADGET and its corresponding QMetaObject can be accessed with QMetaType::metaObject. \endomit
464 \omitvalue PointerToGadget
465 \omitvalue IsQmlList
466 \value IsConst Indicates that values of this type are immutable; for instance, because they are pointers to const objects.
467
468 \note Before Qt 6.5, both the NeedsConstruction and NeedsDestruction flags
469 were incorrectly set if the either copy construtor or destructor were
470 non-trivial (that is, if the type was not trivial).
471
472 Note that the Needs flags may be set but the meta type may not have a
473 publicly-accessible constructor of the relevant type or a
474 publicly-accessible destructor.
475*/
476
477/*!
478 \class QMetaType
479 \inmodule QtCore
480 \brief The QMetaType class manages named types in the meta-object system.
481
482 \ingroup objectmodel
483 \threadsafe
484
485 The class is used as a helper to marshall types in QVariant and
486 in queued signals and slots connections. It associates a type
487 name to a type so that it can be created and destructed
488 dynamically at run-time.
489
490 Type names can be registered with QMetaType by using either
491 qRegisterMetaType() or registerType(). Registration is not required for
492 most operations; it's only required for operations that attempt to resolve
493 a type name in string form back to a QMetaType object or the type's ID.
494 Those include some old-style signal-slot connections using
495 QObject::connect(), reading user-types from \l QDataStream to \l QVariant,
496 or binding to other languages and IPC mechanisms, like QML, D-Bus,
497 JavaScript, etc.
498
499 The following code allocates and destructs an instance of \c{MyClass} by
500 its name, which requires that \c{MyClass} have been previously registered:
501
502 \snippet code/src_corelib_kernel_qmetatype.cpp 3
503
504 If we want the stream operators \c operator<<() and \c
505 operator>>() to work on QVariant objects that store custom types,
506 the custom type must provide \c operator<<() and \c operator>>()
507 operators.
508
509 \sa Q_DECLARE_METATYPE(), QVariant::setValue(), QVariant::value(), QVariant::fromValue()
510*/
511
512/*!
513 \fn bool QMetaType::isValid() const
514 \since 5.0
515
516 Returns \c true if this QMetaType object contains valid
517 information about a type, false otherwise.
518
519 \sa isRegistered()
520*/
521bool QMetaType::isValid() const
522{
523 return d_ptr;
524}
525
526/*!
527 \fn bool QMetaType::isRegistered() const
528 \since 5.0
529
530 Returns \c true if this QMetaType object has been registered with the Qt
531 global metatype registry. Registration allows the type to be found by its
532 name (using QMetaType::fromName()) or by its ID (using the constructor).
533
534 \sa qRegisterMetaType(), isValid()
535*/
536bool QMetaType::isRegistered() const
537{
538 return d_ptr && d_ptr->typeId.loadRelaxed();
539}
540
541/*!
542 \fn int QMetaType::id() const
543 \since 5.13
544
545 Returns id type held by this QMetatype instance.
546*/
547
548/*!
549 \fn void QMetaType::registerType() const
550 \since 6.5
551
552 Registers this QMetaType with the type registry so it can be found by name,
553 using QMetaType::fromName().
554
555 \sa qRegisterMetaType()
556 */
557/*!
558 \internal
559 Out-of-line path for registerType() and slow path id().
560 */
561int QMetaType::registerHelper(const QtPrivate::QMetaTypeInterface *iface)
562{
563 Q_ASSERT(iface);
564 auto reg = customTypeRegistry();
565 if (reg) {
566 return reg->registerCustomType(cti: iface);
567 }
568 return 0;
569}
570
571/*!
572 \fn constexpr qsizetype QMetaType::sizeOf() const
573 \since 5.0
574
575 Returns the size of the type in bytes (i.e. sizeof(T),
576 where T is the actual type for which this QMetaType instance
577 was constructed for).
578
579 This function is typically used together with construct()
580 to perform low-level management of the memory used by a type.
581
582 \sa QMetaType::construct(), QMetaType::sizeOf(), QMetaType::alignOf()
583*/
584
585/*!
586 \fn constexpr int QMetaType::alignOf() const
587 \since 6.0
588
589 Returns the alignment of the type in bytes (i.e. alignof(T),
590 where T is the actual type for which this QMetaType instance
591 was constructed for).
592
593 This function is typically used together with construct()
594 to perform low-level management of the memory used by a type.
595
596 \sa QMetaType::construct(), QMetaType::sizeOf()
597
598 */
599
600/*!
601 \fn constexpr TypeFlags QMetaType::flags() const
602 \since 5.0
603
604 Returns flags of the type for which this QMetaType instance was
605 constructed. To inspect specific type traits, prefer using one of the "is-"
606 functions rather than the flags directly.
607
608 \sa QMetaType::TypeFlags, QMetaType::flags(), isDefaultConstructible(),
609 isCopyConstructible(), isMoveConstructible(), isDestructible(),
610 isEqualityComparable(), isOrdered()
611*/
612
613/*!
614 \fn constexpr const QMetaObject *QMetaType::metaObject() const
615 \since 5.5
616
617 Returns a QMetaObject relative to this type.
618
619 If the type is a pointer type to a subclass of QObject, flags() contains
620 QMetaType::PointerToQObject and this function returns the corresponding QMetaObject.
621 This can be used in combination with QMetaObject::newInstance() to create QObjects of this type.
622
623 If the type is a Q_GADGET, flags() contains QMetaType::IsGadget.
624 If the type is a pointer to a Q_GADGET, flags() contains QMetaType::PointerToGadget.
625 In both cases, this function returns its QMetaObject.
626 This can be used to retrieve QMetaMethod and QMetaProperty and use them on a
627 pointer of this type for example, as given by QVariant::data().
628
629 If the type is an enumeration, flags() contains QMetaType::IsEnumeration.
630 In this case, this function returns the QMetaObject of the enclosing
631 object if the enum was registered as a Q_ENUM or \nullptr otherwise.
632
633 \sa QMetaType::flags()
634*/
635
636/*!
637 \fn void *QMetaType::create(const void *copy = nullptr) const
638 \since 5.0
639
640 Returns a copy of \a copy, assuming it is of the type that this
641 QMetaType instance was created for. If \a copy is \nullptr, creates
642 a default constructed instance.
643
644 \sa QMetaType::destroy()
645*/
646void *QMetaType::create(const void *copy) const
647{
648 if (copy ? !isCopyConstructible() : !isDefaultConstructible())
649 return nullptr;
650
651 std::unique_ptr<void, QMetaTypeDeleter> where(nullptr, {.iface: d_ptr});
652 if (d_ptr->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
653 where.reset(p: operator new(d_ptr->size, std::align_val_t(d_ptr->alignment)));
654 else
655 where.reset(p: operator new(d_ptr->size));
656
657 QtMetaTypePrivate::construct(iface: d_ptr, where: where.get(), copy);
658 return where.release();
659}
660
661/*!
662 \fn void QMetaType::destroy(void *data) const
663 \since 5.0
664
665 Destroys the \a data, assuming it is of the type that this
666 QMetaType instance was created for.
667
668 \sa QMetaType::create()
669*/
670void QMetaType::destroy(void *data) const
671{
672 if (data && isDestructible()) {
673 QtMetaTypePrivate::destruct(iface: d_ptr, where: data);
674 QMetaTypeDeleter{.iface: d_ptr}(data);
675 }
676}
677
678/*!
679 \fn void *QMetaType::construct(void *where, const void *copy = nullptr) const
680 \since 5.0
681
682 Constructs a value of the type that this QMetaType instance
683 was constructed for in the existing memory addressed by \a where,
684 that is a copy of \a copy, and returns \a where. If \a copy is
685 zero, the value is default constructed.
686
687 This is a low-level function for explicitly managing the memory
688 used to store the type. Consider calling create() if you don't
689 need this level of control (that is, use "new" rather than
690 "placement new").
691
692 You must ensure that \a where points to a location where the new
693 value can be stored and that \a where is suitably aligned.
694 The type's size can be queried by calling sizeOf().
695
696 The rule of thumb for alignment is that a type is aligned to its
697 natural boundary, which is the smallest power of 2 that is bigger
698 than the type, unless that alignment is larger than the maximum
699 useful alignment for the platform. For practical purposes,
700 alignment larger than 2 * sizeof(void*) is only necessary for
701 special hardware instructions (e.g., aligned SSE loads and stores
702 on x86).
703*/
704void *QMetaType::construct(void *where, const void *copy) const
705{
706 if (!where)
707 return nullptr;
708 if (copy ? !isCopyConstructible() : !isDefaultConstructible())
709 return nullptr;
710
711 QtMetaTypePrivate::construct(iface: d_ptr, where, copy);
712 return where;
713}
714
715/*!
716 \fn void QMetaType::destruct(void *data) const
717 \since 5.0
718
719 Destructs the value, located at \a data, assuming that it is
720 of the type for which this QMetaType instance was constructed for.
721
722 Unlike destroy(), this function only invokes the type's
723 destructor, it doesn't invoke the delete operator.
724 \sa QMetaType::construct()
725*/
726void QMetaType::destruct(void *data) const
727{
728 if (data && isDestructible())
729 QtMetaTypePrivate::destruct(iface: d_ptr, where: data);
730}
731
732static QPartialOrdering threeWayCompare(const void *ptr1, const void *ptr2)
733{
734 std::less<const void *> less;
735 if (less(ptr1, ptr2))
736 return QPartialOrdering::Less;
737 if (less(ptr2, ptr1))
738 return QPartialOrdering::Greater;
739 return QPartialOrdering::Equivalent;
740}
741
742/*!
743 Compares the objects at \a lhs and \a rhs for ordering.
744
745 Returns QPartialOrdering::Unordered if comparison is not supported
746 or the values are unordered. Otherwise, returns
747 QPartialOrdering::Less, QPartialOrdering::Equivalent or
748 QPartialOrdering::Greater if \a lhs is less than, equivalent
749 to or greater than \a rhs, respectively.
750
751 Both objects must be of the type described by this metatype. If either \a lhs
752 or \a rhs is \nullptr, the values are unordered. Comparison is only supported
753 if the type's less than operator was visible to the metatype declaration.
754
755 If the type's equality operator was also visible, values will only compare equal if the
756 equality operator says they are. In the absence of an equality operator, when neither
757 value is less than the other, values are considered equal; if equality is also available
758 and two such values are not equal, they are considered unordered, just as NaN (not a
759 number) values of a floating point type lie outside its ordering.
760
761 \note If no less than operator was visible to the metatype declaration, values are
762 unordered even if an equality operator visible to the declaration considers them equal:
763 \c{compare() == 0} only agrees with equals() if the less than operator was visible.
764
765 \since 6.0
766 \sa equals(), isOrdered()
767*/
768QPartialOrdering QMetaType::compare(const void *lhs, const void *rhs) const
769{
770 if (!lhs || !rhs)
771 return QPartialOrdering::Unordered;
772 if (d_ptr && d_ptr->flags & QMetaType::IsPointer)
773 return threeWayCompare(ptr1: *reinterpret_cast<const void * const *>(lhs),
774 ptr2: *reinterpret_cast<const void * const *>(rhs));
775 if (d_ptr && d_ptr->lessThan) {
776 if (d_ptr->equals && d_ptr->equals(d_ptr, lhs, rhs))
777 return QPartialOrdering::Equivalent;
778 if (d_ptr->lessThan(d_ptr, lhs, rhs))
779 return QPartialOrdering::Less;
780 if (d_ptr->lessThan(d_ptr, rhs, lhs))
781 return QPartialOrdering::Greater;
782 if (!d_ptr->equals)
783 return QPartialOrdering::Equivalent;
784 }
785 return QPartialOrdering::Unordered;
786}
787
788/*!
789 Compares the objects at \a lhs and \a rhs for equality.
790
791 Both objects must be of the type described by this metatype. Can only compare the
792 two objects if a less than or equality operator for the type was visible to the
793 metatype declaration. Otherwise, the metatype never considers values equal. When
794 an equality operator was visible to the metatype declaration, it is authoritative;
795 otherwise, if less than is visible, when neither value is less than the other, the
796 two are considered equal. If values are unordered (see compare() for details) they
797 are not equal.
798
799 Returns true if the two objects compare equal, otherwise false.
800
801 \since 6.0
802 \sa isEqualityComparable(), compare()
803*/
804bool QMetaType::equals(const void *lhs, const void *rhs) const
805{
806 if (!lhs || !rhs)
807 return false;
808 if (d_ptr) {
809 if (d_ptr->flags & QMetaType::IsPointer)
810 return *reinterpret_cast<const void * const *>(lhs) == *reinterpret_cast<const void * const *>(rhs);
811
812 if (d_ptr->equals)
813 return d_ptr->equals(d_ptr, lhs, rhs);
814 if (d_ptr->lessThan && !d_ptr->lessThan(d_ptr, lhs, rhs) && !d_ptr->lessThan(d_ptr, rhs, lhs))
815 return true;
816 }
817 return false;
818}
819
820/*!
821 \fn bool QMetaType::isDefaultConstructible() const noexcept
822 \since 6.5
823
824 Returns true if this type can be default-constructed. If it can be, then
825 construct() and create() can be used with a \c{copy} parameter that is
826 null.
827
828 \sa flags(), isCopyConstructible(), isMoveConstructible(), isDestructible()
829 */
830
831/*!
832 \fn bool QMetaType::isCopyConstructible() const noexcept
833 \since 6.5
834
835 Returns true if this type can be copy-constructed. If it can be, then
836 construct() and create() can be used with a \c{copy} parameter that is
837 not null.
838
839 \sa flags(), isDefaultConstructible(), isMoveConstructible(), isDestructible()
840 */
841
842/*!
843 \fn bool QMetaType::isMoveConstructible() const noexcept
844 \since 6.5
845
846 Returns true if this type can be move-constructed. QMetaType currently does
847 not have an API to make use of this trait.
848
849 \sa flags(), isDefaultConstructible(), isCopyConstructible(), isDestructible()
850 */
851
852/*!
853 \fn bool QMetaType::isDestructible() const noexcept
854 \since 6.5
855
856 Returns true if this type can be destroyed. If it can be, then destroy()
857 and destruct() can be called.
858
859 \sa flags(), isDefaultConstructible(), isCopyConstructible(), isMoveConstructible()
860 */
861
862bool QMetaType::isDefaultConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
863{
864 return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isDefaultConstructible(iface);
865}
866
867bool QMetaType::isCopyConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
868{
869 return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isCopyConstructible(iface);
870}
871
872bool QMetaType::isMoveConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
873{
874 return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isMoveConstructible(iface);
875}
876
877bool QMetaType::isDestructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
878{
879 return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isDestructible(iface);
880}
881
882/*!
883 Returns \c true if a less than or equality operator for the type described by
884 this metatype was visible to the metatype declaration, otherwise \c false.
885
886 \sa equals(), isOrdered()
887*/
888bool QMetaType::isEqualityComparable() const
889{
890 return d_ptr && (d_ptr->flags & QMetaType::IsPointer || d_ptr->equals != nullptr || d_ptr->lessThan != nullptr);
891}
892
893/*!
894 Returns \c true if a less than operator for the type described by this metatype
895 was visible to the metatype declaration, otherwise \c false.
896
897 \sa compare(), isEqualityComparable()
898*/
899bool QMetaType::isOrdered() const
900{
901 return d_ptr && (d_ptr->flags & QMetaType::IsPointer || d_ptr->lessThan != nullptr);
902}
903
904
905/*!
906 \internal
907*/
908void QMetaType::unregisterMetaType(QMetaType type)
909{
910 if (type.d_ptr && type.d_ptr->typeId.loadRelaxed() >= QMetaType::User) {
911 // this is a custom meta type (not read-only)
912 auto d = const_cast<QtPrivate::QMetaTypeInterface *>(type.d_ptr);
913 if (auto reg = customTypeRegistry())
914 reg->unregisterDynamicType(id: d->typeId.loadRelaxed());
915 d->typeId.storeRelease(newValue: 0);
916 }
917}
918
919/*!
920 \fn template<typename T> QMetaType QMetaType::fromType()
921 \since 5.15
922
923 Returns the QMetaType corresponding to the type in the template parameter.
924*/
925
926/*! \fn bool QMetaType::operator==(QMetaType a, QMetaType b)
927 \since 5.15
928 \overload
929
930 Returns \c true if the QMetaType \a a represents the same type
931 as the QMetaType \a b, otherwise returns \c false.
932*/
933
934/*! \fn bool QMetaType::operator!=(QMetaType a, QMetaType b)
935 \since 5.15
936 \overload
937
938 Returns \c true if the QMetaType \a a represents a different type
939 than the QMetaType \a b, otherwise returns \c false.
940*/
941
942#define QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, RealName) \
943 { #RealName, sizeof(#RealName) - 1, MetaTypeId },
944
945#define QT_ADD_STATIC_METATYPE_ALIASES_ITER(MetaTypeName, MetaTypeId, AliasingName, RealNameStr) \
946 { RealNameStr, sizeof(RealNameStr) - 1, QMetaType::MetaTypeName },
947
948
949
950static const struct { const char * typeName; int typeNameLength; int type; } types[] = {
951 QT_FOR_EACH_STATIC_TYPE(QT_ADD_STATIC_METATYPE)
952 QT_FOR_EACH_STATIC_ALIAS_TYPE(QT_ADD_STATIC_METATYPE_ALIASES_ITER)
953 QT_ADD_STATIC_METATYPE(_, QMetaTypeId2<qreal>::MetaType, qreal)
954 {.typeName: nullptr, .typeNameLength: 0, .type: QMetaType::UnknownType}
955};
956
957static const struct : QMetaTypeModuleHelper
958{
959 template<typename T, typename LiteralWrapper =
960 std::conditional_t<std::is_same_v<T, QString>, QLatin1StringView, const char *>>
961 static inline bool convertToBool(const T &source)
962 {
963 T str = source.toLower();
964 return !(str.isEmpty() || str == LiteralWrapper("0") || str == LiteralWrapper("false"));
965 }
966
967 const QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override {
968 switch (type) {
969 QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_CONVERT_ID_TO_TYPE)
970 QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_CONVERT_ID_TO_TYPE)
971 QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_CONVERT_ID_TO_TYPE)
972 QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_CONVERT_ID_TO_TYPE)
973 QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_CONVERT_ID_TO_TYPE)
974 default:
975 return nullptr;
976 }
977 }
978
979 bool convert(const void *from, int fromTypeId, void *to, int toTypeId) const override
980 {
981 Q_ASSERT(fromTypeId != toTypeId);
982
983 // canConvert calls with two nullptr
984 bool onlyCheck = (from == nullptr && to == nullptr);
985
986 // other callers must provide two valid pointers
987 Q_ASSERT(onlyCheck || (bool(from) && bool(to)));
988
989 using Char = char;
990 using SChar = signed char;
991 using UChar = unsigned char;
992 using Short = short;
993 using UShort = unsigned short;
994 using Int = int;
995 using UInt = unsigned int;
996 using Long = long;
997 using LongLong = qlonglong;
998 using ULong = unsigned long;
999 using ULongLong = qulonglong;
1000 using Float = float;
1001 using Double = double;
1002 using Bool = bool;
1003 using Nullptr = std::nullptr_t;
1004
1005#define QMETATYPE_CONVERTER_ASSIGN_DOUBLE(To, From) \
1006 QMETATYPE_CONVERTER(To, From, result = double(source); return true;)
1007#define QMETATYPE_CONVERTER_ASSIGN_NUMBER(To, From) \
1008 QMETATYPE_CONVERTER(To, From, result = To::number(source); return true;)
1009#ifndef QT_BOOTSTRAPPED
1010#define CONVERT_CBOR_AND_JSON(To) \
1011 QMETATYPE_CONVERTER(To, QCborValue, \
1012 if constexpr(std::is_same_v<To, Bool>) { \
1013 if (!source.isBool()) \
1014 return false; \
1015 result = source.toBool(); \
1016 } else { \
1017 if (!source.isInteger() && !source.isDouble()) \
1018 return false; \
1019 if constexpr(std::is_integral_v<To>) \
1020 result = source.toInteger(); \
1021 else \
1022 result = source.toDouble(); \
1023 } \
1024 return true; \
1025 ); \
1026 QMETATYPE_CONVERTER(To, QJsonValue, \
1027 if constexpr(std::is_same_v<To, Bool>) { \
1028 if (!source.isBool()) \
1029 return false; \
1030 result = source.toBool(); \
1031 } else { \
1032 if (!source.isDouble()) \
1033 return false; \
1034 if constexpr(std::is_integral_v<To>) \
1035 result = source.toInteger(); \
1036 else \
1037 result = source.toDouble(); \
1038 } \
1039 return true; \
1040 )
1041#else
1042#define CONVERT_CBOR_AND_JSON(To)
1043#endif
1044
1045#define INTEGRAL_CONVERTER(To) \
1046 QMETATYPE_CONVERTER_ASSIGN(To, Bool); \
1047 QMETATYPE_CONVERTER_ASSIGN(To, Char); \
1048 QMETATYPE_CONVERTER_ASSIGN(To, UChar); \
1049 QMETATYPE_CONVERTER_ASSIGN(To, SChar); \
1050 QMETATYPE_CONVERTER_ASSIGN(To, Short); \
1051 QMETATYPE_CONVERTER_ASSIGN(To, UShort); \
1052 QMETATYPE_CONVERTER_ASSIGN(To, Int); \
1053 QMETATYPE_CONVERTER_ASSIGN(To, UInt); \
1054 QMETATYPE_CONVERTER_ASSIGN(To, Long); \
1055 QMETATYPE_CONVERTER_ASSIGN(To, ULong); \
1056 QMETATYPE_CONVERTER_ASSIGN(To, LongLong); \
1057 QMETATYPE_CONVERTER_ASSIGN(To, ULongLong); \
1058 QMETATYPE_CONVERTER(To, Float, result = qRound64(source); return true;); \
1059 QMETATYPE_CONVERTER(To, Double, result = qRound64(source); return true;); \
1060 QMETATYPE_CONVERTER(To, QChar, result = source.unicode(); return true;); \
1061 QMETATYPE_CONVERTER(To, QString, \
1062 bool ok = false; \
1063 if constexpr(std::is_same_v<To, bool>) \
1064 result = (ok = true, convertToBool(source)); \
1065 else if constexpr(std::is_signed_v<To>) \
1066 result = To(source.toLongLong(&ok)); \
1067 else \
1068 result = To(source.toULongLong(&ok)); \
1069 return ok; \
1070 ); \
1071 QMETATYPE_CONVERTER(To, QByteArray, \
1072 bool ok = false; \
1073 if constexpr(std::is_same_v<To, bool>) \
1074 result = (ok = true, convertToBool(source)); \
1075 else if constexpr(std::is_signed_v<To>) \
1076 result = To(source.toLongLong(&ok)); \
1077 else \
1078 result = To(source.toULongLong(&ok)); \
1079 return ok; \
1080 ); \
1081 CONVERT_CBOR_AND_JSON(To)
1082
1083#define FLOAT_CONVERTER(To) \
1084 QMETATYPE_CONVERTER_ASSIGN(To, Bool); \
1085 QMETATYPE_CONVERTER_ASSIGN(To, Char); \
1086 QMETATYPE_CONVERTER_ASSIGN(To, UChar); \
1087 QMETATYPE_CONVERTER_ASSIGN(To, SChar); \
1088 QMETATYPE_CONVERTER_ASSIGN(To, Short); \
1089 QMETATYPE_CONVERTER_ASSIGN(To, UShort); \
1090 QMETATYPE_CONVERTER_ASSIGN(To, Int); \
1091 QMETATYPE_CONVERTER_ASSIGN(To, UInt); \
1092 QMETATYPE_CONVERTER_ASSIGN(To, Long); \
1093 QMETATYPE_CONVERTER_ASSIGN(To, ULong); \
1094 QMETATYPE_CONVERTER_ASSIGN(To, LongLong); \
1095 QMETATYPE_CONVERTER_ASSIGN(To, ULongLong); \
1096 QMETATYPE_CONVERTER_ASSIGN(To, Float); \
1097 QMETATYPE_CONVERTER_ASSIGN(To, Double); \
1098 QMETATYPE_CONVERTER(To, QString, \
1099 bool ok = false; \
1100 result = source.toDouble(&ok); \
1101 return ok; \
1102 ); \
1103 QMETATYPE_CONVERTER(To, QByteArray, \
1104 bool ok = false; \
1105 result = source.toDouble(&ok); \
1106 return ok; \
1107 ); \
1108 CONVERT_CBOR_AND_JSON(To)
1109
1110 switch (makePair(from: toTypeId, to: fromTypeId)) {
1111
1112 // integral conversions
1113 INTEGRAL_CONVERTER(Bool);
1114 INTEGRAL_CONVERTER(Char);
1115 INTEGRAL_CONVERTER(UChar);
1116 INTEGRAL_CONVERTER(SChar);
1117 INTEGRAL_CONVERTER(Short);
1118 INTEGRAL_CONVERTER(UShort);
1119 INTEGRAL_CONVERTER(Int);
1120 INTEGRAL_CONVERTER(UInt);
1121 INTEGRAL_CONVERTER(Long);
1122 INTEGRAL_CONVERTER(ULong);
1123 INTEGRAL_CONVERTER(LongLong);
1124 INTEGRAL_CONVERTER(ULongLong);
1125 FLOAT_CONVERTER(Float);
1126 FLOAT_CONVERTER(Double);
1127
1128#ifndef QT_BOOTSTRAPPED
1129 QMETATYPE_CONVERTER_ASSIGN(QUrl, QString);
1130 QMETATYPE_CONVERTER(QUrl, QCborValue,
1131 if (source.isUrl()) {
1132 result = source.toUrl();
1133 return true;
1134 }
1135 return false;
1136 );
1137#endif
1138#if QT_CONFIG(itemmodel)
1139 QMETATYPE_CONVERTER_ASSIGN(QModelIndex, QPersistentModelIndex);
1140 QMETATYPE_CONVERTER_ASSIGN(QPersistentModelIndex, QModelIndex);
1141#endif // QT_CONFIG(itemmodel)
1142
1143 // QChar methods
1144#define QMETATYPE_CONVERTER_ASSIGN_QCHAR(From) \
1145 QMETATYPE_CONVERTER(QChar, From, result = QChar::fromUcs2(source); return true;)
1146 QMETATYPE_CONVERTER_ASSIGN_QCHAR(Char);
1147 QMETATYPE_CONVERTER_ASSIGN_QCHAR(SChar);
1148 QMETATYPE_CONVERTER_ASSIGN_QCHAR(Short);
1149 QMETATYPE_CONVERTER_ASSIGN_QCHAR(Long);
1150 QMETATYPE_CONVERTER_ASSIGN_QCHAR(Int);
1151 QMETATYPE_CONVERTER_ASSIGN_QCHAR(LongLong);
1152 QMETATYPE_CONVERTER_ASSIGN_QCHAR(Float);
1153 QMETATYPE_CONVERTER_ASSIGN_QCHAR(UChar);
1154 QMETATYPE_CONVERTER_ASSIGN_QCHAR(UShort);
1155 QMETATYPE_CONVERTER_ASSIGN_QCHAR(ULong);
1156 QMETATYPE_CONVERTER_ASSIGN_QCHAR(UInt);
1157 QMETATYPE_CONVERTER_ASSIGN_QCHAR(ULongLong);
1158
1159 // conversions to QString
1160 QMETATYPE_CONVERTER_ASSIGN(QString, QChar);
1161 QMETATYPE_CONVERTER(QString, Bool,
1162 result = source ? QStringLiteral("true") : QStringLiteral("false");
1163 return true;
1164 );
1165 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, Short);
1166 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, Long);
1167 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, Int);
1168 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, LongLong);
1169 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, UShort);
1170 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, ULong);
1171 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, UInt);
1172 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, ULongLong);
1173 QMETATYPE_CONVERTER(QString, Float,
1174 result = QString::number(source, 'g', QLocale::FloatingPointShortest);
1175 return true;
1176 );
1177 QMETATYPE_CONVERTER(QString, Double,
1178 result = QString::number(source, 'g', QLocale::FloatingPointShortest);
1179 return true;
1180 );
1181 QMETATYPE_CONVERTER(QString, Char,
1182 result = QString::fromLatin1(&source, 1);
1183 return true;
1184 );
1185 QMETATYPE_CONVERTER(QString, SChar,
1186 char s = source;
1187 result = QString::fromLatin1(&s, 1);
1188 return true;
1189 );
1190 QMETATYPE_CONVERTER(QString, UChar,
1191 char s = source;
1192 result = QString::fromLatin1(&s, 1);
1193 return true;
1194 );
1195#if QT_CONFIG(datestring)
1196 QMETATYPE_CONVERTER(QString, QDate, result = source.toString(Qt::ISODate); return true;);
1197 QMETATYPE_CONVERTER(QString, QTime, result = source.toString(Qt::ISODateWithMs); return true;);
1198 QMETATYPE_CONVERTER(QString, QDateTime, result = source.toString(Qt::ISODateWithMs); return true;);
1199#endif
1200 QMETATYPE_CONVERTER(QString, QByteArray, result = QString::fromUtf8(source); return true;);
1201 QMETATYPE_CONVERTER(QString, QStringList,
1202 return (source.size() == 1) ? (result = source.at(0), true) : false;
1203 );
1204#ifndef QT_BOOTSTRAPPED
1205 QMETATYPE_CONVERTER(QString, QUrl, result = source.toString(); return true;);
1206 QMETATYPE_CONVERTER(QString, QJsonValue,
1207 if (source.isString() || source.isNull()) {
1208 result = source.toString();
1209 return true;
1210 }
1211 return false;
1212 );
1213#endif
1214 QMETATYPE_CONVERTER(QString, Nullptr, Q_UNUSED(source); result = QString(); return true;);
1215
1216 // QByteArray
1217 QMETATYPE_CONVERTER(QByteArray, QString, result = source.toUtf8(); return true;);
1218 QMETATYPE_CONVERTER(QByteArray, Bool,
1219 result = source ? "true" : "false";
1220 return true;
1221 );
1222 QMETATYPE_CONVERTER(QByteArray, Char, result = QByteArray(source, 1); return true;);
1223 QMETATYPE_CONVERTER(QByteArray, SChar, result = QByteArray(source, 1); return true;);
1224 QMETATYPE_CONVERTER(QByteArray, UChar, result = QByteArray(source, 1); return true;);
1225 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, Short);
1226 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, Long);
1227 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, Int);
1228 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, LongLong);
1229 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, UShort);
1230 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, ULong);
1231 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, UInt);
1232 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, ULongLong);
1233 QMETATYPE_CONVERTER(QByteArray, Float,
1234 result = QByteArray::number(source, 'g', QLocale::FloatingPointShortest);
1235 return true;
1236 );
1237 QMETATYPE_CONVERTER(QByteArray, Double,
1238 result = QByteArray::number(source, 'g', QLocale::FloatingPointShortest);
1239 return true;
1240 );
1241 QMETATYPE_CONVERTER(QByteArray, Nullptr, Q_UNUSED(source); result = QByteArray(); return true;);
1242
1243 QMETATYPE_CONVERTER(QString, QUuid, result = source.toString(); return true;);
1244 QMETATYPE_CONVERTER(QUuid, QString, result = QUuid(source); return true;);
1245 QMETATYPE_CONVERTER(QByteArray, QUuid, result = source.toByteArray(); return true;);
1246 QMETATYPE_CONVERTER(QUuid, QByteArray, result = QUuid(source); return true;);
1247
1248#ifndef QT_NO_GEOM_VARIANT
1249 QMETATYPE_CONVERTER(QSize, QSizeF, result = source.toSize(); return true;);
1250 QMETATYPE_CONVERTER_ASSIGN(QSizeF, QSize);
1251 QMETATYPE_CONVERTER(QLine, QLineF, result = source.toLine(); return true;);
1252 QMETATYPE_CONVERTER_ASSIGN(QLineF, QLine);
1253 QMETATYPE_CONVERTER(QRect, QRectF, result = source.toRect(); return true;);
1254 QMETATYPE_CONVERTER_ASSIGN(QRectF, QRect);
1255 QMETATYPE_CONVERTER(QPoint, QPointF, result = source.toPoint(); return true;);
1256 QMETATYPE_CONVERTER_ASSIGN(QPointF, QPoint);
1257 #endif
1258
1259 QMETATYPE_CONVERTER(QByteArrayList, QVariantList,
1260 result.reserve(source.size());
1261 for (const auto &v: source)
1262 result.append(v.toByteArray());
1263 return true;
1264 );
1265 QMETATYPE_CONVERTER(QVariantList, QByteArrayList,
1266 result.reserve(source.size());
1267 for (const auto &v: source)
1268 result.append(QVariant(v));
1269 return true;
1270 );
1271
1272 QMETATYPE_CONVERTER(QStringList, QVariantList,
1273 result.reserve(source.size());
1274 for (const auto &v: source)
1275 result.append(v.toString());
1276 return true;
1277 );
1278 QMETATYPE_CONVERTER(QVariantList, QStringList,
1279 result.reserve(source.size());
1280 for (const auto &v: source)
1281 result.append(QVariant(v));
1282 return true;
1283 );
1284 QMETATYPE_CONVERTER(QStringList, QString, result = QStringList() << source; return true;);
1285
1286 QMETATYPE_CONVERTER(QVariantHash, QVariantMap,
1287 for (auto it = source.begin(); it != source.end(); ++it)
1288 result.insert(it.key(), it.value());
1289 return true;
1290 );
1291 QMETATYPE_CONVERTER(QVariantMap, QVariantHash,
1292 for (auto it = source.begin(); it != source.end(); ++it)
1293 result.insert(it.key(), it.value());
1294 return true;
1295 );
1296
1297#ifndef QT_BOOTSTRAPPED
1298 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QString);
1299 QMETATYPE_CONVERTER(QString, QCborValue,
1300 if (source.isContainer() || source.isTag())
1301 return false;
1302 result = source.toVariant().toString();
1303 return true;
1304 );
1305 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QByteArray);
1306 QMETATYPE_CONVERTER(QByteArray, QCborValue,
1307 if (source.isByteArray()) {
1308 result = source.toByteArray();
1309 return true;
1310 }
1311 return false;
1312 );
1313 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QUuid);
1314 QMETATYPE_CONVERTER(QUuid, QCborValue,
1315 if (!source.isUuid())
1316 return false;
1317 result = source.toUuid();
1318 return true;
1319 );
1320 QMETATYPE_CONVERTER(QCborValue, QVariantList, result = QCborArray::fromVariantList(source); return true;);
1321 QMETATYPE_CONVERTER(QVariantList, QCborValue,
1322 if (!source.isArray())
1323 return false;
1324 result = source.toArray().toVariantList();
1325 return true;
1326 );
1327 QMETATYPE_CONVERTER(QCborValue, QVariantMap, result = QCborMap::fromVariantMap(source); return true;);
1328 QMETATYPE_CONVERTER(QVariantMap, QCborValue,
1329 if (!source.isMap())
1330 return false;
1331 result = source.toMap().toVariantMap();
1332 return true;
1333 );
1334 QMETATYPE_CONVERTER(QCborValue, QVariantHash, result = QCborMap::fromVariantHash(source); return true;);
1335 QMETATYPE_CONVERTER(QVariantHash, QCborValue,
1336 if (!source.isMap())
1337 return false;
1338 result = source.toMap().toVariantHash();
1339 return true;
1340 );
1341#if QT_CONFIG(regularexpression)
1342 QMETATYPE_CONVERTER(QCborValue, QRegularExpression, result = QCborValue(source); return true;);
1343 QMETATYPE_CONVERTER(QRegularExpression, QCborValue,
1344 if (!source.isRegularExpression())
1345 return false;
1346 result = source.toRegularExpression();
1347 return true;
1348 );
1349#endif
1350
1351 QMETATYPE_CONVERTER(QCborValue, Nullptr,
1352 Q_UNUSED(source);
1353 result = QCborValue(QCborValue::Null);
1354 return true;
1355 );
1356 QMETATYPE_CONVERTER(Nullptr, QCborValue,
1357 result = nullptr;
1358 return source.isNull();
1359 );
1360 QMETATYPE_CONVERTER_ASSIGN(QCborValue, Bool);
1361 QMETATYPE_CONVERTER_ASSIGN(QCborValue, Int);
1362 QMETATYPE_CONVERTER_ASSIGN(QCborValue, UInt);
1363 QMETATYPE_CONVERTER(QCborValue, ULong, result = qlonglong(source); return true;);
1364 QMETATYPE_CONVERTER(QCborValue, Long, result = qlonglong(source); return true;);
1365 QMETATYPE_CONVERTER_ASSIGN(QCborValue, LongLong);
1366 QMETATYPE_CONVERTER(QCborValue, ULongLong, result = qlonglong(source); return true;);
1367 QMETATYPE_CONVERTER_ASSIGN(QCborValue, UShort);
1368 QMETATYPE_CONVERTER_ASSIGN(QCborValue, UChar);
1369 QMETATYPE_CONVERTER_ASSIGN(QCborValue, Char);
1370 QMETATYPE_CONVERTER_ASSIGN(QCborValue, SChar);
1371 QMETATYPE_CONVERTER_ASSIGN(QCborValue, Short);
1372 QMETATYPE_CONVERTER_ASSIGN(QCborValue, Double);
1373 QMETATYPE_CONVERTER_ASSIGN(QCborValue, Float);
1374 QMETATYPE_CONVERTER(QCborValue, QStringList,
1375 result = QCborArray::fromStringList(source);
1376 return true;
1377 );
1378 QMETATYPE_CONVERTER(QCborValue, QDate,
1379 result = QCborValue(source.startOfDay());
1380 return true;
1381 );
1382 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QUrl);
1383 QMETATYPE_CONVERTER(QCborValue, QJsonValue,
1384 result = QCborValue::fromJsonValue(source);
1385 return true;
1386 );
1387 QMETATYPE_CONVERTER(QCborValue, QJsonObject,
1388 result = QCborMap::fromJsonObject(source);
1389 return true;
1390 );
1391 QMETATYPE_CONVERTER(QCborValue, QJsonArray,
1392 result = QCborArray::fromJsonArray(source);
1393 return true;
1394 );
1395 QMETATYPE_CONVERTER(QCborValue, QJsonDocument,
1396 QJsonDocument doc = source;
1397 if (doc.isArray())
1398 result = QCborArray::fromJsonArray(doc.array());
1399 else
1400 result = QCborMap::fromJsonObject(doc.object());
1401 return true;
1402 );
1403 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QCborMap);
1404 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QCborArray);
1405
1406 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QDateTime);
1407 QMETATYPE_CONVERTER(QDateTime, QCborValue,
1408 if (source.isDateTime()) {
1409 result = source.toDateTime();
1410 return true;
1411 }
1412 return false;
1413 );
1414
1415 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QCborSimpleType);
1416 QMETATYPE_CONVERTER(QCborSimpleType, QCborValue,
1417 if (source.isSimpleType()) {
1418 result = source.toSimpleType();
1419 return true;
1420 }
1421 return false;
1422 );
1423
1424 QMETATYPE_CONVERTER(QCborArray, QVariantList, result = QCborArray::fromVariantList(source); return true;);
1425 QMETATYPE_CONVERTER(QVariantList, QCborArray, result = source.toVariantList(); return true;);
1426 QMETATYPE_CONVERTER(QCborArray, QStringList, result = QCborArray::fromStringList(source); return true;);
1427 QMETATYPE_CONVERTER(QCborMap, QVariantMap, result = QCborMap::fromVariantMap(source); return true;);
1428 QMETATYPE_CONVERTER(QVariantMap, QCborMap, result = source.toVariantMap(); return true;);
1429 QMETATYPE_CONVERTER(QCborMap, QVariantHash, result = QCborMap::fromVariantHash(source); return true;);
1430 QMETATYPE_CONVERTER(QVariantHash, QCborMap, result = source.toVariantHash(); return true;);
1431
1432 QMETATYPE_CONVERTER(QCborArray, QCborValue,
1433 if (!source.isArray())
1434 return false;
1435 result = source.toArray();
1436 return true;
1437 );
1438 QMETATYPE_CONVERTER(QCborArray, QJsonDocument,
1439 if (!source.isArray())
1440 return false;
1441 result = QCborArray::fromJsonArray(source.array());
1442 return true;
1443 );
1444 QMETATYPE_CONVERTER(QCborArray, QJsonValue,
1445 if (!source.isArray())
1446 return false;
1447 result = QCborArray::fromJsonArray(source.toArray());
1448 return true;
1449 );
1450 QMETATYPE_CONVERTER(QCborArray, QJsonArray,
1451 result = QCborArray::fromJsonArray(source);
1452 return true;
1453 );
1454 QMETATYPE_CONVERTER(QCborMap, QCborValue,
1455 if (!source.isMap())
1456 return false;
1457 result = source.toMap();
1458 return true;
1459 );
1460 QMETATYPE_CONVERTER(QCborMap, QJsonDocument,
1461 if (source.isArray())
1462 return false;
1463 result = QCborMap::fromJsonObject(source.object());
1464 return true;
1465 );
1466 QMETATYPE_CONVERTER(QCborMap, QJsonValue,
1467 if (!source.isObject())
1468 return false;
1469 result = QCborMap::fromJsonObject(source.toObject());
1470 return true;
1471 );
1472 QMETATYPE_CONVERTER(QCborMap, QJsonObject,
1473 result = QCborMap::fromJsonObject(source);
1474 return true;
1475 );
1476
1477
1478 QMETATYPE_CONVERTER(QVariantList, QJsonValue,
1479 if (!source.isArray())
1480 return false;
1481 result = source.toArray().toVariantList();
1482 return true;
1483 );
1484 QMETATYPE_CONVERTER(QVariantList, QJsonArray, result = source.toVariantList(); return true;);
1485 QMETATYPE_CONVERTER(QVariantMap, QJsonValue,
1486 if (!source.isObject())
1487 return false;
1488 result = source.toObject().toVariantMap();
1489 return true;
1490 );
1491 QMETATYPE_CONVERTER(QVariantMap, QJsonObject, result = source.toVariantMap(); return true;);
1492 QMETATYPE_CONVERTER(QVariantHash, QJsonValue,
1493 if (!source.isObject())
1494 return false;
1495 result = source.toObject().toVariantHash();
1496 return true;
1497 );
1498 QMETATYPE_CONVERTER(QVariantHash, QJsonObject, result = source.toVariantHash(); return true;);
1499
1500
1501 QMETATYPE_CONVERTER(QJsonArray, QStringList, result = QJsonArray::fromStringList(source); return true;);
1502 QMETATYPE_CONVERTER(QJsonArray, QVariantList, result = QJsonArray::fromVariantList(source); return true;);
1503 QMETATYPE_CONVERTER(QJsonArray, QJsonValue,
1504 if (!source.isArray())
1505 return false;
1506 result = source.toArray();
1507 return true;
1508 );
1509 QMETATYPE_CONVERTER(QJsonArray, QJsonDocument,
1510 if (!source.isArray())
1511 return false;
1512 result = source.array();
1513 return true;
1514 );
1515 QMETATYPE_CONVERTER(QJsonArray, QCborValue,
1516 if (!source.isArray())
1517 return false;
1518 result = source.toArray().toJsonArray();
1519 return true;
1520 );
1521 QMETATYPE_CONVERTER(QJsonArray, QCborArray, result = source.toJsonArray(); return true;);
1522 QMETATYPE_CONVERTER(QJsonObject, QVariantMap, result = QJsonObject::fromVariantMap(source); return true;);
1523 QMETATYPE_CONVERTER(QJsonObject, QVariantHash, result = QJsonObject::fromVariantHash(source); return true;);
1524 QMETATYPE_CONVERTER(QJsonObject, QJsonValue,
1525 if (!source.isObject())
1526 return false;
1527 result = source.toObject();
1528 return true;
1529 );
1530 QMETATYPE_CONVERTER(QJsonObject, QJsonDocument,
1531 if (source.isArray())
1532 return false;
1533 result = source.object();
1534 return true;
1535 );
1536 QMETATYPE_CONVERTER(QJsonObject, QCborValue,
1537 if (!source.isMap())
1538 return false;
1539 result = source.toMap().toJsonObject();
1540 return true;
1541 );
1542 QMETATYPE_CONVERTER(QJsonObject, QCborMap, result = source.toJsonObject(); return true; );
1543
1544 QMETATYPE_CONVERTER(QJsonValue, Nullptr,
1545 Q_UNUSED(source);
1546 result = QJsonValue(QJsonValue::Null);
1547 return true;
1548 );
1549 QMETATYPE_CONVERTER(Nullptr, QJsonValue,
1550 result = nullptr;
1551 return source.isNull();
1552 );
1553 QMETATYPE_CONVERTER(QJsonValue, Bool,
1554 result = QJsonValue(source);
1555 return true;);
1556 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Int);
1557 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, UInt);
1558 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Double);
1559 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Float);
1560 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, ULong);
1561 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Long);
1562 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, LongLong);
1563 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, ULongLong);
1564 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, UShort);
1565 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, UChar);
1566 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Char);
1567 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, SChar);
1568 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Short);
1569 QMETATYPE_CONVERTER_ASSIGN(QJsonValue, QString);
1570 QMETATYPE_CONVERTER(QJsonValue, QStringList,
1571 result = QJsonValue(QJsonArray::fromStringList(source));
1572 return true;
1573 );
1574 QMETATYPE_CONVERTER(QJsonValue, QVariantList,
1575 result = QJsonValue(QJsonArray::fromVariantList(source));
1576 return true;
1577 );
1578 QMETATYPE_CONVERTER(QJsonValue, QVariantMap,
1579 result = QJsonValue(QJsonObject::fromVariantMap(source));
1580 return true;
1581 );
1582 QMETATYPE_CONVERTER(QJsonValue, QVariantHash,
1583 result = QJsonValue(QJsonObject::fromVariantHash(source));
1584 return true;
1585 );
1586 QMETATYPE_CONVERTER(QJsonValue, QJsonObject,
1587 result = source;
1588 return true;
1589 );
1590 QMETATYPE_CONVERTER(QJsonValue, QJsonArray,
1591 result = source;
1592 return true;
1593 );
1594 QMETATYPE_CONVERTER(QJsonValue, QJsonDocument,
1595 QJsonDocument doc = source;
1596 result = doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object());
1597 return true;
1598 );
1599 QMETATYPE_CONVERTER(QJsonValue, QCborValue,
1600 result = source.toJsonValue();
1601 return true;
1602 );
1603 QMETATYPE_CONVERTER(QJsonValue, QCborMap,
1604 result = source.toJsonObject();
1605 return true;
1606 );
1607 QMETATYPE_CONVERTER(QJsonValue, QCborArray,
1608 result = source.toJsonArray();
1609 return true;
1610 );
1611
1612#endif
1613
1614 QMETATYPE_CONVERTER(QDate, QDateTime, result = source.date(); return true;);
1615 QMETATYPE_CONVERTER(QTime, QDateTime, result = source.time(); return true;);
1616 QMETATYPE_CONVERTER(QDateTime, QDate, result = source.startOfDay(); return true;);
1617#if QT_CONFIG(datestring)
1618 QMETATYPE_CONVERTER(QDate, QString,
1619 result = QDate::fromString(source, Qt::ISODate);
1620 return result.isValid();
1621 );
1622 QMETATYPE_CONVERTER(QTime, QString,
1623 result = QTime::fromString(source, Qt::ISODate);
1624 return result.isValid();
1625 );
1626 QMETATYPE_CONVERTER(QDateTime, QString,
1627 result = QDateTime::fromString(source, Qt::ISODate);
1628 return result.isValid();
1629 );
1630#endif
1631
1632 }
1633 return false;
1634 }
1635} metatypeHelper = {};
1636
1637Q_CONSTINIT Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeGuiHelper = nullptr;
1638Q_CONSTINIT Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeWidgetsHelper = nullptr;
1639
1640static const QMetaTypeModuleHelper *qModuleHelperForType(int type)
1641{
1642 if (type <= QMetaType::LastCoreType)
1643 return &metatypeHelper;
1644 if (type >= QMetaType::FirstGuiType && type <= QMetaType::LastGuiType)
1645 return qMetaTypeGuiHelper;
1646 else if (type >= QMetaType::FirstWidgetsType && type <= QMetaType::LastWidgetsType)
1647 return qMetaTypeWidgetsHelper;
1648 return nullptr;
1649}
1650
1651template<typename T, typename Key>
1652class QMetaTypeFunctionRegistry
1653{
1654public:
1655 ~QMetaTypeFunctionRegistry()
1656 {
1657 const QWriteLocker locker(&lock);
1658 map.clear();
1659 }
1660
1661 bool contains(Key k) const
1662 {
1663 const QReadLocker locker(&lock);
1664 return map.contains(k);
1665 }
1666
1667 bool insertIfNotContains(Key k, const T &f)
1668 {
1669 const QWriteLocker locker(&lock);
1670 const qsizetype oldSize = map.size();
1671 auto &e = map[k];
1672 if (map.size() == oldSize) // already present
1673 return false;
1674 e = f;
1675 return true;
1676 }
1677
1678 const T *function(Key k) const
1679 {
1680 const QReadLocker locker(&lock);
1681 auto it = map.find(k);
1682 return it == map.end() ? nullptr : std::addressof(*it);
1683 }
1684
1685 void remove(int from, int to)
1686 {
1687 const Key k(from, to);
1688 const QWriteLocker locker(&lock);
1689 map.remove(k);
1690 }
1691private:
1692 mutable QReadWriteLock lock;
1693 QHash<Key, T> map;
1694};
1695
1696typedef QMetaTypeFunctionRegistry<QMetaType::ConverterFunction,QPair<int,int> >
1697QMetaTypeConverterRegistry;
1698
1699Q_GLOBAL_STATIC(QMetaTypeConverterRegistry, customTypesConversionRegistry)
1700
1701using QMetaTypeMutableViewRegistry
1702 = QMetaTypeFunctionRegistry<QMetaType::MutableViewFunction, QPair<int,int>>;
1703Q_GLOBAL_STATIC(QMetaTypeMutableViewRegistry, customTypesMutableViewRegistry)
1704
1705/*!
1706 \fn bool QMetaType::registerConverter()
1707 \since 5.2
1708 Registers the possibility of an implicit conversion from type From to type To in the meta
1709 type system. Returns \c true if the registration succeeded, otherwise false.
1710
1711 \snippet qmetatype/registerConverters.cpp implicit
1712*/
1713
1714/*!
1715 \fn template<typename From, typename To> static bool QMetaType::registerConverter(To(From::*function)() const)
1716 \since 5.2
1717 \overload
1718 Registers a method \a function like To From::function() const as converter from type From
1719 to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
1720
1721 \snippet qmetatype/registerConverters.cpp member
1722*/
1723
1724/*!
1725 \fn template<typename From, typename To> static bool QMetaType::registerConverter(To(From::*function)(bool*) const)
1726 \since 5.2
1727 \overload
1728 Registers a method \a function like To From::function(bool *ok) const as converter from type From
1729 to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
1730
1731 The \c ok pointer can be used by the function to indicate whether the conversion succeeded.
1732 \snippet qmetatype/registerConverters.cpp memberOk
1733
1734*/
1735
1736/*!
1737 \fn template<typename From, typename To, typename UnaryFunction> static bool QMetaType::registerConverter(UnaryFunction function)
1738 \since 5.2
1739 \overload
1740 Registers a unary function object \a function as converter from type From
1741 to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
1742
1743 \a function must take an instance of type \c From and return an instance of \c To. It can be a function
1744 pointer, a lambda or a functor object. Since Qt 6.5, the \a function can also return an instance of
1745 \c std::optional<To> to be able to indicate failed conversions.
1746 \snippet qmetatype/registerConverters.cpp unaryfunc
1747*/
1748
1749/*!
1750 Registers function \a f as converter function from type id \a from to \a to.
1751 If there's already a conversion registered, this does nothing but deleting \a f.
1752 Returns \c true if the registration succeeded, otherwise false.
1753 \since 5.2
1754 \internal
1755*/
1756bool QMetaType::registerConverterFunction(const ConverterFunction &f, QMetaType from, QMetaType to)
1757{
1758 if (!customTypesConversionRegistry()->insertIfNotContains(k: qMakePair(value1: from.id(), value2: to.id()), f)) {
1759 qWarning(msg: "Type conversion already registered from type %s to type %s",
1760 from.name(), to.name());
1761 return false;
1762 }
1763 return true;
1764}
1765
1766/*!
1767 \fn template<typename From, typename To> static bool QMetaType::registerMutableView(To(From::*function)())
1768 \since 6.0
1769 \overload
1770 Registers a method \a function like \c {To From::function()} as mutable view of type \c {To} on
1771 type \c {From} in the meta type system. Returns \c true if the registration succeeded, otherwise
1772 \c false.
1773*/
1774
1775/*!
1776 \fn template<typename From, typename To, typename UnaryFunction> static bool QMetaType::registerMutableView(UnaryFunction function)
1777 \since 6.0
1778 \overload
1779 Registers a unary function object \a function as mutable view of type To on type From
1780 in the meta type system. Returns \c true if the registration succeeded, otherwise \c false.
1781*/
1782
1783/*!
1784 Registers function \a f as mutable view of type id \a to on type id \a from.
1785 Returns \c true if the registration succeeded, otherwise \c false.
1786 \since 6.0
1787 \internal
1788*/
1789bool QMetaType::registerMutableViewFunction(const MutableViewFunction &f, QMetaType from, QMetaType to)
1790{
1791 if (!customTypesMutableViewRegistry()->insertIfNotContains(k: qMakePair(value1: from.id(), value2: to.id()), f)) {
1792 qWarning(msg: "Mutable view on type already registered from type %s to type %s",
1793 from.name(), to.name());
1794 return false;
1795 }
1796 return true;
1797}
1798
1799/*!
1800 \internal
1801 */
1802void QMetaType::unregisterMutableViewFunction(QMetaType from, QMetaType to)
1803{
1804 if (customTypesMutableViewRegistry.isDestroyed())
1805 return;
1806 customTypesMutableViewRegistry()->remove(from: from.id(), to: to.id());
1807}
1808
1809/*!
1810 \internal
1811
1812 Invoked automatically when a converter function object is destroyed.
1813 */
1814void QMetaType::unregisterConverterFunction(QMetaType from, QMetaType to)
1815{
1816 if (customTypesConversionRegistry.isDestroyed())
1817 return;
1818 customTypesConversionRegistry()->remove(from: from.id(), to: to.id());
1819}
1820
1821#ifndef QT_NO_DEBUG_STREAM
1822
1823/*!
1824 \fn QDebug QMetaType::operator<<(QDebug d, QMetaType m)
1825 \since 6.5
1826 Writes the QMetaType \a m to the stream \a d, and returns the stream.
1827*/
1828QDebug operator<<(QDebug d, QMetaType m)
1829{
1830 const QDebugStateSaver saver(d);
1831 return d.nospace() << "QMetaType(" << m.name() << ")";
1832}
1833
1834/*!
1835 Streams the object at \a rhs to the debug stream \a dbg. Returns \c true
1836 on success, otherwise false.
1837 \since 5.2
1838*/
1839bool QMetaType::debugStream(QDebug& dbg, const void *rhs)
1840{
1841 if (d_ptr && d_ptr->flags & QMetaType::IsPointer) {
1842 dbg << *reinterpret_cast<const void * const *>(rhs);
1843 return true;
1844 }
1845 if (d_ptr && d_ptr->debugStream) {
1846 d_ptr->debugStream(d_ptr, dbg, rhs);
1847 return true;
1848 }
1849 return false;
1850}
1851
1852/*!
1853 \fn bool QMetaType::debugStream(QDebug& dbg, const void *rhs, int typeId)
1854 \overload
1855 \deprecated
1856*/
1857
1858/*!
1859 \fn bool QMetaType::hasRegisteredDebugStreamOperator()
1860 \deprecated
1861 \since 5.2
1862
1863 Returns \c true, if the meta type system has a registered debug stream operator for type T.
1864 */
1865
1866/*!
1867 \fn bool QMetaType::hasRegisteredDebugStreamOperator(int typeId)
1868 \deprecated Use QMetaType::hasRegisteredDebugStreamOperator() instead.
1869
1870 Returns \c true, if the meta type system has a registered debug stream operator for type
1871 id \a typeId.
1872 \since 5.2
1873*/
1874
1875/*!
1876 \since 6.0
1877
1878 Returns \c true, if the meta type system has a registered debug stream operator for this
1879 meta type.
1880*/
1881bool QMetaType::hasRegisteredDebugStreamOperator() const
1882{
1883 return d_ptr && d_ptr->debugStream != nullptr;
1884}
1885#endif
1886
1887#ifndef QT_NO_QOBJECT
1888/*!
1889 \internal
1890 returns a QMetaEnum for a given meta tape type id if possible
1891*/
1892static QMetaEnum metaEnumFromType(QMetaType t)
1893{
1894 if (t.flags() & QMetaType::IsEnumeration) {
1895 if (const QMetaObject *metaObject = t.metaObject()) {
1896 QByteArrayView qflagsNamePrefix = "QFlags<";
1897 QByteArray enumName = t.name();
1898 if (enumName.endsWith(c: '>') && enumName.startsWith(bv: qflagsNamePrefix)) {
1899 // extract the template argument
1900 enumName.chop(n: 1);
1901 enumName = enumName.sliced(pos: qflagsNamePrefix.size());
1902 }
1903 if (qsizetype lastColon = enumName.lastIndexOf(c: ':'); lastColon != -1)
1904 enumName = enumName.sliced(pos: lastColon + 1);
1905 return metaObject->enumerator(index: metaObject->indexOfEnumerator(name: enumName));
1906 }
1907 }
1908 return QMetaEnum();
1909}
1910#endif
1911
1912static bool convertFromEnum(QMetaType fromType, const void *from, QMetaType toType, void *to)
1913{
1914 qlonglong ll;
1915 if (fromType.flags() & QMetaType::IsUnsignedEnumeration) {
1916 qulonglong ull;
1917 switch (fromType.sizeOf()) {
1918 case 1:
1919 ull = *static_cast<const unsigned char *>(from);
1920 break;
1921 case 2:
1922 ull = *static_cast<const unsigned short *>(from);
1923 break;
1924 case 4:
1925 ull = *static_cast<const unsigned int *>(from);
1926 break;
1927 case 8:
1928 ull = *static_cast<const quint64 *>(from);
1929 break;
1930 default:
1931 Q_UNREACHABLE();
1932 }
1933 if (toType.id() == QMetaType::ULongLong) {
1934 *static_cast<qulonglong *>(to) = ull;
1935 return true;
1936 }
1937 if (toType.id() != QMetaType::QString && toType.id() != QMetaType::QByteArray)
1938 return QMetaType::convert(fromType: QMetaType::fromType<qulonglong>(), from: &ull, toType, to);
1939 ll = qlonglong(ull);
1940 } else {
1941 switch (fromType.sizeOf()) {
1942 case 1:
1943 ll = *static_cast<const signed char *>(from);
1944 break;
1945 case 2:
1946 ll = *static_cast<const short *>(from);
1947 break;
1948 case 4:
1949 ll = *static_cast<const int *>(from);
1950 break;
1951 case 8:
1952 ll = *static_cast<const qint64 *>(from);
1953 break;
1954 default:
1955 Q_UNREACHABLE();
1956 }
1957 if (toType.id() == QMetaType::LongLong) {
1958 *static_cast<qlonglong *>(to) = ll;
1959 return true;
1960 }
1961 if (toType.id() != QMetaType::QString && toType.id() != QMetaType::QByteArray)
1962 return QMetaType::convert(fromType: QMetaType::fromType<qlonglong>(), from: &ll, toType, to);
1963 }
1964#ifndef QT_NO_QOBJECT
1965 QMetaEnum en = metaEnumFromType(t: fromType);
1966 if (en.isValid()) {
1967 if (en.isFlag()) {
1968 const QByteArray keys = en.valueToKeys(value: static_cast<int>(ll));
1969 if (toType.id() == QMetaType::QString)
1970 *static_cast<QString *>(to) = QString::fromUtf8(ba: keys);
1971 else
1972 *static_cast<QByteArray *>(to) = keys;
1973 } else {
1974 const char *key = en.valueToKey(value: static_cast<int>(ll));
1975 if (toType.id() == QMetaType::QString)
1976 *static_cast<QString *>(to) = QString::fromUtf8(utf8: key);
1977 else
1978 *static_cast<QByteArray *>(to) = key;
1979 }
1980 return true;
1981 }
1982#endif
1983 if (toType.id() == QMetaType::QString || toType.id() == QMetaType::QByteArray)
1984 return QMetaType::convert(fromType: QMetaType::fromType<qlonglong>(), from: &ll, toType, to);
1985 return false;
1986}
1987
1988static bool convertToEnum(QMetaType fromType, const void *from, QMetaType toType, void *to)
1989{
1990 int fromTypeId = fromType.id();
1991 qlonglong value = -1;
1992 bool ok = false;
1993#ifndef QT_NO_QOBJECT
1994 if (fromTypeId == QMetaType::QString || fromTypeId == QMetaType::QByteArray) {
1995 QMetaEnum en = metaEnumFromType(t: toType);
1996 if (en.isValid()) {
1997 QByteArray keys = (fromTypeId == QMetaType::QString)
1998 ? static_cast<const QString *>(from)->toUtf8()
1999 : *static_cast<const QByteArray *>(from);
2000 value = en.keysToValue(keys: keys.constData(), ok: &ok);
2001 }
2002 }
2003#endif
2004 if (!ok) {
2005 if (fromTypeId == QMetaType::LongLong) {
2006 value = *static_cast<const qlonglong *>(from);
2007 ok = true;
2008 } else {
2009 ok = QMetaType::convert(fromType, from, toType: QMetaType::fromType<qlonglong>(), to: &value);
2010 }
2011 }
2012
2013 if (!ok)
2014 return false;
2015
2016 switch (toType.sizeOf()) {
2017 case 1:
2018 *static_cast<signed char *>(to) = value;
2019 return true;
2020 case 2:
2021 *static_cast<qint16 *>(to) = value;
2022 return true;
2023 case 4:
2024 *static_cast<qint32 *>(to) = value;
2025 return true;
2026 case 8:
2027 *static_cast<qint64 *>(to) = value;
2028 return true;
2029 default:
2030 Q_UNREACHABLE_RETURN(false);
2031 }
2032}
2033
2034#ifndef QT_BOOTSTRAPPED
2035static bool convertIterableToVariantList(QMetaType fromType, const void *from, void *to)
2036{
2037 QSequentialIterable list;
2038 if (!QMetaType::convert(fromType, from, toType: QMetaType::fromType<QSequentialIterable>(), to: &list))
2039 return false;
2040
2041 QVariantList &l = *static_cast<QVariantList *>(to);
2042 l.clear();
2043 l.reserve(asize: list.size());
2044 auto end = list.end();
2045 for (auto it = list.begin(); it != end; ++it)
2046 l << *it;
2047 return true;
2048}
2049
2050static bool convertIterableToVariantMap(QMetaType fromType, const void *from, void *to)
2051{
2052 QAssociativeIterable map;
2053 if (!QMetaType::convert(fromType, from, toType: QMetaType::fromType<QAssociativeIterable>(), to: &map))
2054 return false;
2055
2056 QVariantMap &h = *static_cast<QVariantMap *>(to);
2057 h.clear();
2058 auto end = map.end();
2059 for (auto it = map.begin(); it != end; ++it)
2060 h.insert(key: it.key().toString(), value: it.value());
2061 return true;
2062}
2063
2064static bool convertIterableToVariantHash(QMetaType fromType, const void *from, void *to)
2065{
2066 QAssociativeIterable map;
2067 if (!QMetaType::convert(fromType, from, toType: QMetaType::fromType<QAssociativeIterable>(), to: &map))
2068 return false;
2069
2070 QVariantHash &h = *static_cast<QVariantHash *>(to);
2071 h.clear();
2072 h.reserve(size: map.size());
2073 auto end = map.end();
2074 for (auto it = map.begin(); it != end; ++it)
2075 h.insert(key: it.key().toString(), value: it.value());
2076 return true;
2077}
2078#endif
2079
2080static bool convertIterableToVariantPair(QMetaType fromType, const void *from, void *to)
2081{
2082 const QMetaType::ConverterFunction * const f =
2083 customTypesConversionRegistry()->function(k: qMakePair(value1: fromType.id(),
2084 value2: qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>()));
2085 if (!f)
2086 return false;
2087
2088 QtMetaTypePrivate::QPairVariantInterfaceImpl pi;
2089 (*f)(from, &pi);
2090
2091 QVariant v1(pi._metaType_first);
2092 void *dataPtr;
2093 if (pi._metaType_first == QMetaType::fromType<QVariant>())
2094 dataPtr = &v1;
2095 else
2096 dataPtr = v1.data();
2097 pi.first(dataPtr);
2098
2099 QVariant v2(pi._metaType_second);
2100 if (pi._metaType_second == QMetaType::fromType<QVariant>())
2101 dataPtr = &v2;
2102 else
2103 dataPtr = v2.data();
2104 pi.second(dataPtr);
2105
2106 *static_cast<QVariantPair *>(to) = QVariantPair(v1, v2);
2107 return true;
2108}
2109
2110#ifndef QT_BOOTSTRAPPED
2111static bool convertToSequentialIterable(QMetaType fromType, const void *from, void *to)
2112{
2113 using namespace QtMetaTypePrivate;
2114 const int fromTypeId = fromType.id();
2115
2116 QSequentialIterable &i = *static_cast<QSequentialIterable *>(to);
2117 switch (fromTypeId) {
2118 case QMetaType::QVariantList:
2119 i = QSequentialIterable(reinterpret_cast<const QVariantList *>(from));
2120 return true;
2121 case QMetaType::QStringList:
2122 i = QSequentialIterable(reinterpret_cast<const QStringList *>(from));
2123 return true;
2124 case QMetaType::QByteArrayList:
2125 i = QSequentialIterable(reinterpret_cast<const QByteArrayList *>(from));
2126 return true;
2127 case QMetaType::QString:
2128 i = QSequentialIterable(reinterpret_cast<const QString *>(from));
2129 return true;
2130 case QMetaType::QByteArray:
2131 i = QSequentialIterable(reinterpret_cast<const QByteArray *>(from));
2132 return true;
2133 default: {
2134 QSequentialIterable impl;
2135 if (QMetaType::convert(
2136 fromType, from, toType: QMetaType::fromType<QIterable<QMetaSequence>>(), to: &impl)) {
2137 i = std::move(impl);
2138 return true;
2139 }
2140 }
2141 }
2142
2143 return false;
2144}
2145
2146static bool canConvertToSequentialIterable(QMetaType fromType)
2147{
2148 switch (fromType.id()) {
2149 case QMetaType::QVariantList:
2150 case QMetaType::QStringList:
2151 case QMetaType::QByteArrayList:
2152 case QMetaType::QString:
2153 case QMetaType::QByteArray:
2154 return true;
2155 default:
2156 return QMetaType::canConvert(fromType, toType: QMetaType::fromType<QIterable<QMetaSequence>>());
2157 }
2158}
2159
2160static bool canImplicitlyViewAsSequentialIterable(QMetaType fromType)
2161{
2162 switch (fromType.id()) {
2163 case QMetaType::QVariantList:
2164 case QMetaType::QStringList:
2165 case QMetaType::QByteArrayList:
2166 case QMetaType::QString:
2167 case QMetaType::QByteArray:
2168 return true;
2169 default:
2170 return QMetaType::canView(
2171 fromType, toType: QMetaType::fromType<QIterable<QMetaSequence>>());
2172 }
2173}
2174
2175static bool viewAsSequentialIterable(QMetaType fromType, void *from, void *to)
2176{
2177 using namespace QtMetaTypePrivate;
2178 const int fromTypeId = fromType.id();
2179
2180 QSequentialIterable &i = *static_cast<QSequentialIterable *>(to);
2181 switch (fromTypeId) {
2182 case QMetaType::QVariantList:
2183 i = QSequentialIterable(reinterpret_cast<QVariantList *>(from));
2184 return true;
2185 case QMetaType::QStringList:
2186 i = QSequentialIterable(reinterpret_cast<QStringList *>(from));
2187 return true;
2188 case QMetaType::QByteArrayList:
2189 i = QSequentialIterable(reinterpret_cast<QByteArrayList *>(from));
2190 return true;
2191 case QMetaType::QString:
2192 i = QSequentialIterable(reinterpret_cast<QString *>(from));
2193 return true;
2194 case QMetaType::QByteArray:
2195 i = QSequentialIterable(reinterpret_cast<QByteArray *>(from));
2196 return true;
2197 default: {
2198 QIterable<QMetaSequence> j(QMetaSequence(), nullptr);
2199 if (QMetaType::view(
2200 fromType, from, toType: QMetaType::fromType<QIterable<QMetaSequence>>(), to: &j)) {
2201 i = std::move(j);
2202 return true;
2203 }
2204 }
2205 }
2206
2207 return false;
2208}
2209
2210static bool convertToAssociativeIterable(QMetaType fromType, const void *from, void *to)
2211{
2212 using namespace QtMetaTypePrivate;
2213
2214 QAssociativeIterable &i = *static_cast<QAssociativeIterable *>(to);
2215 if (fromType.id() == QMetaType::QVariantMap) {
2216 i = QAssociativeIterable(reinterpret_cast<const QVariantMap *>(from));
2217 return true;
2218 }
2219 if (fromType.id() == QMetaType::QVariantHash) {
2220 i = QAssociativeIterable(reinterpret_cast<const QVariantHash *>(from));
2221 return true;
2222 }
2223
2224 QAssociativeIterable impl;
2225 if (QMetaType::convert(
2226 fromType, from, toType: QMetaType::fromType<QIterable<QMetaAssociation>>(), to: &impl)) {
2227 i = std::move(impl);
2228 return true;
2229 }
2230
2231 return false;
2232}
2233
2234static bool canConvertMetaObject(QMetaType fromType, QMetaType toType)
2235{
2236 if ((fromType.flags() & QMetaType::IsPointer) != (toType.flags() & QMetaType::IsPointer))
2237 return false; // Can not convert between pointer and value
2238
2239 const QMetaObject *f = fromType.metaObject();
2240 const QMetaObject *t = toType.metaObject();
2241 if (f && t) {
2242 return f->inherits(metaObject: t) || (t->inherits(metaObject: f));
2243 }
2244 return false;
2245}
2246
2247static bool canConvertToAssociativeIterable(QMetaType fromType)
2248{
2249 switch (fromType.id()) {
2250 case QMetaType::QVariantMap:
2251 case QMetaType::QVariantHash:
2252 return true;
2253 default:
2254 return QMetaType::canConvert(fromType, toType: QMetaType::fromType<QIterable<QMetaAssociation>>());
2255 }
2256}
2257
2258static bool canImplicitlyViewAsAssociativeIterable(QMetaType fromType)
2259{
2260 switch (fromType.id()) {
2261 case QMetaType::QVariantMap:
2262 case QMetaType::QVariantHash:
2263 return true;
2264 default:
2265 return QMetaType::canView(
2266 fromType, toType: QMetaType::fromType<QIterable<QMetaAssociation>>());
2267 }
2268}
2269
2270static bool viewAsAssociativeIterable(QMetaType fromType, void *from, void *to)
2271{
2272 using namespace QtMetaTypePrivate;
2273 int fromTypeId = fromType.id();
2274
2275 QAssociativeIterable &i = *static_cast<QAssociativeIterable *>(to);
2276 if (fromTypeId == QMetaType::QVariantMap) {
2277 i = QAssociativeIterable(reinterpret_cast<QVariantMap *>(from));
2278 return true;
2279 }
2280 if (fromTypeId == QMetaType::QVariantHash) {
2281 i = QAssociativeIterable(reinterpret_cast<QVariantHash *>(from));
2282 return true;
2283 }
2284
2285 QIterable<QMetaAssociation> j(QMetaAssociation(), nullptr);
2286 if (QMetaType::view(
2287 fromType, from, toType: QMetaType::fromType<QIterable<QMetaAssociation>>(), to: &j)) {
2288 i = std::move(j);
2289 return true;
2290 }
2291
2292 return false;
2293}
2294
2295static bool convertMetaObject(QMetaType fromType, const void *from, QMetaType toType, void *to)
2296{
2297 // handle QObject conversion
2298 if ((fromType.flags() & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
2299 QObject *fromObject = *static_cast<QObject * const *>(from);
2300 // use dynamic metatype of from if possible
2301 if (fromObject && fromObject->metaObject()->inherits(metaObject: toType.metaObject())) {
2302 *static_cast<QObject **>(to) = toType.metaObject()->cast(obj: fromObject);
2303 return true;
2304 } else if (!fromObject && fromType.metaObject()) {
2305 // if fromObject is null, use static fromType to check if conversion works
2306 *static_cast<void **>(to) = nullptr;
2307 return fromType.metaObject()->inherits(metaObject: toType.metaObject());
2308 }
2309 } else if ((fromType.flags() & QMetaType::IsPointer) == (toType.flags() & QMetaType::IsPointer)) {
2310 // fromType and toType are of same 'pointedness'
2311 const QMetaObject *f = fromType.metaObject();
2312 const QMetaObject *t = toType.metaObject();
2313 if (f && t && f->inherits(metaObject: t)) {
2314 toType.destruct(data: to);
2315 toType.construct(where: to, copy: from);
2316 return true;
2317 }
2318 }
2319 return false;
2320}
2321#endif
2322
2323/*!
2324 \fn bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId)
2325 \deprecated
2326
2327 Converts the object at \a from from \a fromTypeId to the preallocated space at \a to
2328 typed \a toTypeId. Returns \c true, if the conversion succeeded, otherwise false.
2329
2330 Both \a from and \a to have to be valid pointers.
2331
2332 \since 5.2
2333*/
2334
2335/*!
2336 Converts the object at \a from from \a fromType to the preallocated space at \a to
2337 typed \a toType. Returns \c true, if the conversion succeeded, otherwise false.
2338
2339 Both \a from and \a to have to be valid pointers.
2340
2341 \since 5.2
2342*/
2343bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType, void *to)
2344{
2345 if (!fromType.isValid() || !toType.isValid())
2346 return false;
2347
2348 if (fromType == toType) {
2349 // just make a copy
2350 fromType.destruct(data: to);
2351 fromType.construct(where: to, copy: from);
2352 return true;
2353 }
2354
2355 int fromTypeId = fromType.id();
2356 int toTypeId = toType.id();
2357
2358 if (auto moduleHelper = qModuleHelperForType(type: qMax(a: fromTypeId, b: toTypeId))) {
2359 if (moduleHelper->convert(from, fromTypeId, to, toTypeId))
2360 return true;
2361 }
2362 const QMetaType::ConverterFunction * const f =
2363 customTypesConversionRegistry()->function(k: qMakePair(value1&: fromTypeId, value2&: toTypeId));
2364 if (f)
2365 return (*f)(from, to);
2366
2367 if (fromType.flags() & QMetaType::IsEnumeration)
2368 return convertFromEnum(fromType, from, toType, to);
2369 if (toType.flags() & QMetaType::IsEnumeration)
2370 return convertToEnum(fromType, from, toType, to);
2371 if (toTypeId == Nullptr) {
2372 *static_cast<std::nullptr_t *>(to) = nullptr;
2373 if (fromType.flags() & QMetaType::IsPointer) {
2374 if (*static_cast<const void * const *>(from) == nullptr)
2375 return true;
2376 }
2377 }
2378
2379 if (toTypeId == QVariantPair && convertIterableToVariantPair(fromType, from, to))
2380 return true;
2381
2382#ifndef QT_BOOTSTRAPPED
2383 // handle iterables
2384 if (toTypeId == QVariantList && convertIterableToVariantList(fromType, from, to))
2385 return true;
2386
2387 if (toTypeId == QVariantMap && convertIterableToVariantMap(fromType, from, to))
2388 return true;
2389
2390 if (toTypeId == QVariantHash && convertIterableToVariantHash(fromType, from, to))
2391 return true;
2392
2393 if (toTypeId == qMetaTypeId<QSequentialIterable>())
2394 return convertToSequentialIterable(fromType, from, to);
2395
2396 if (toTypeId == qMetaTypeId<QAssociativeIterable>())
2397 return convertToAssociativeIterable(fromType, from, to);
2398
2399 return convertMetaObject(fromType, from, toType, to);
2400#else
2401 return false;
2402#endif
2403}
2404
2405/*!
2406 Creates a mutable view on the object at \a from of \a fromType in the preallocated space at
2407 \a to typed \a toType. Returns \c true if the conversion succeeded, otherwise false.
2408 \since 6.0
2409*/
2410bool QMetaType::view(QMetaType fromType, void *from, QMetaType toType, void *to)
2411{
2412 if (!fromType.isValid() || !toType.isValid())
2413 return false;
2414
2415 int fromTypeId = fromType.id();
2416 int toTypeId = toType.id();
2417
2418 const QMetaType::MutableViewFunction * const f =
2419 customTypesMutableViewRegistry()->function(k: qMakePair(value1&: fromTypeId, value2&: toTypeId));
2420 if (f)
2421 return (*f)(from, to);
2422
2423#ifndef QT_BOOTSTRAPPED
2424 if (toTypeId == qMetaTypeId<QSequentialIterable>())
2425 return viewAsSequentialIterable(fromType, from, to);
2426
2427 if (toTypeId == qMetaTypeId<QAssociativeIterable>())
2428 return viewAsAssociativeIterable(fromType, from, to);
2429
2430 return convertMetaObject(fromType, from, toType, to);
2431#else
2432 return false;
2433#endif
2434}
2435
2436/*!
2437 Returns \c true if QMetaType::view can create a mutable view of type \a toType
2438 on type \a fromType.
2439
2440 Converting between pointers of types derived from QObject will return true for this
2441 function if a qobject_cast from the type described by \a fromType to the type described
2442 by \a toType would succeed.
2443
2444 You can create a mutable view of type QSequentialIterable on any container registered with
2445 Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE().
2446
2447 Similarly you can create a mutable view of type QAssociativeIterable on any container
2448 registered with Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE().
2449
2450 \sa convert(), QSequentialIterable, Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(),
2451 QAssociativeIterable, Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE()
2452*/
2453bool QMetaType::canView(QMetaType fromType, QMetaType toType)
2454{
2455 int fromTypeId = fromType.id();
2456 int toTypeId = toType.id();
2457
2458 if (fromTypeId == UnknownType || toTypeId == UnknownType)
2459 return false;
2460
2461 const MutableViewFunction * const f =
2462 customTypesMutableViewRegistry()->function(k: qMakePair(value1&: fromTypeId, value2&: toTypeId));
2463 if (f)
2464 return true;
2465
2466#ifndef QT_BOOTSTRAPPED
2467 if (toTypeId == qMetaTypeId<QSequentialIterable>())
2468 return canImplicitlyViewAsSequentialIterable(fromType);
2469
2470 if (toTypeId == qMetaTypeId<QAssociativeIterable>())
2471 return canImplicitlyViewAsAssociativeIterable(fromType);
2472
2473 if (canConvertMetaObject(fromType, toType))
2474 return true;
2475#endif
2476
2477 return false;
2478}
2479
2480/*!
2481 Returns \c true if QMetaType::convert can convert from \a fromType to
2482 \a toType.
2483
2484 The following conversions are supported by Qt:
2485
2486 \table
2487 \header \li Type \li Automatically Cast To
2488 \row \li \l QMetaType::Bool \li \l QMetaType::QChar, \l QMetaType::Double,
2489 \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
2490 \l QMetaType::UInt, \l QMetaType::ULongLong
2491 \row \li \l QMetaType::QByteArray \li \l QMetaType::Double,
2492 \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
2493 \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
2494 \row \li \l QMetaType::QChar \li \l QMetaType::Bool, \l QMetaType::Int,
2495 \l QMetaType::UInt, \l QMetaType::LongLong, \l QMetaType::ULongLong
2496 \row \li \l QMetaType::QColor \li \l QMetaType::QString
2497 \row \li \l QMetaType::QDate \li \l QMetaType::QDateTime,
2498 \l QMetaType::QString
2499 \row \li \l QMetaType::QDateTime \li \l QMetaType::QDate,
2500 \l QMetaType::QString, \l QMetaType::QTime
2501 \row \li \l QMetaType::Double \li \l QMetaType::Bool, \l QMetaType::Int,
2502 \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt,
2503 \l QMetaType::ULongLong
2504 \row \li \l QMetaType::QFont \li \l QMetaType::QString
2505 \row \li \l QMetaType::Int \li \l QMetaType::Bool, \l QMetaType::QChar,
2506 \l QMetaType::Double, \l QMetaType::LongLong, \l QMetaType::QString,
2507 \l QMetaType::UInt, \l QMetaType::ULongLong
2508 \row \li \l QMetaType::QKeySequence \li \l QMetaType::Int,
2509 \l QMetaType::QString
2510 \row \li \l QMetaType::QVariantList \li \l QMetaType::QStringList (if the
2511 list's items can be converted to QStrings)
2512 \row \li \l QMetaType::LongLong \li \l QMetaType::Bool,
2513 \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::Double,
2514 \l QMetaType::Int, \l QMetaType::QString, \l QMetaType::UInt,
2515 \l QMetaType::ULongLong
2516 \row \li \l QMetaType::QPoint \li QMetaType::QPointF
2517 \row \li \l QMetaType::QRect \li QMetaType::QRectF
2518 \row \li \l QMetaType::QString \li \l QMetaType::Bool,
2519 \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::QColor,
2520 \l QMetaType::QDate, \l QMetaType::QDateTime, \l QMetaType::Double,
2521 \l QMetaType::QFont, \l QMetaType::Int, \l QMetaType::QKeySequence,
2522 \l QMetaType::LongLong, \l QMetaType::QStringList, \l QMetaType::QTime,
2523 \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
2524 \row \li \l QMetaType::QStringList \li \l QMetaType::QVariantList,
2525 \l QMetaType::QString (if the list contains exactly one item)
2526 \row \li \l QMetaType::QTime \li \l QMetaType::QString
2527 \row \li \l QMetaType::UInt \li \l QMetaType::Bool, \l QMetaType::QChar,
2528 \l QMetaType::Double, \l QMetaType::Int, \l QMetaType::LongLong,
2529 \l QMetaType::QString, \l QMetaType::ULongLong
2530 \row \li \l QMetaType::ULongLong \li \l QMetaType::Bool,
2531 \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
2532 \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt
2533 \row \li \l QMetaType::QUuid \li \l QMetaType::QByteArray, \l QMetaType::QString
2534 \endtable
2535
2536 Casting between primitive type (int, float, bool etc.) is supported.
2537
2538 Converting between pointers of types derived from QObject will also return true for this
2539 function if a qobject_cast from the type described by \a fromType to the type described
2540 by \a toType would succeed.
2541
2542 A cast from a sequential container will also return true for this
2543 function if the \a toType is QVariantList.
2544
2545 Similarly, a cast from an associative container will also return true for this
2546 function the \a toType is QVariantHash or QVariantMap.
2547
2548 \sa convert(), QSequentialIterable, Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(), QAssociativeIterable,
2549 Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE()
2550*/
2551bool QMetaType::canConvert(QMetaType fromType, QMetaType toType)
2552{
2553 int fromTypeId = fromType.id();
2554 int toTypeId = toType.id();
2555
2556 if (fromTypeId == UnknownType || toTypeId == UnknownType)
2557 return false;
2558
2559 if (fromTypeId == toTypeId)
2560 return true;
2561
2562 if (auto moduleHelper = qModuleHelperForType(type: qMax(a: fromTypeId, b: toTypeId))) {
2563 if (moduleHelper->convert(nullptr, fromTypeId, nullptr, toTypeId))
2564 return true;
2565 }
2566 const ConverterFunction * const f =
2567 customTypesConversionRegistry()->function(k: std::make_pair(x&: fromTypeId, y&: toTypeId));
2568 if (f)
2569 return true;
2570
2571#ifndef QT_BOOTSTRAPPED
2572 if (toTypeId == qMetaTypeId<QSequentialIterable>())
2573 return canConvertToSequentialIterable(fromType);
2574
2575 if (toTypeId == qMetaTypeId<QAssociativeIterable>())
2576 return canConvertToAssociativeIterable(fromType);
2577
2578 if (toTypeId == QVariantList
2579 && canConvert(fromType, toType: QMetaType::fromType<QSequentialIterable>())) {
2580 return true;
2581 }
2582
2583 if ((toTypeId == QVariantHash || toTypeId == QVariantMap)
2584 && canConvert(fromType, toType: QMetaType::fromType<QAssociativeIterable>())) {
2585 return true;
2586 }
2587#endif
2588
2589 if (toTypeId == QVariantPair && hasRegisteredConverterFunction(
2590 fromType, toType: QMetaType::fromType<QtMetaTypePrivate::QPairVariantInterfaceImpl>()))
2591 return true;
2592
2593 if (fromType.flags() & IsEnumeration) {
2594 if (toTypeId == QString || toTypeId == QByteArray)
2595 return true;
2596 return canConvert(fromType: QMetaType(LongLong), toType);
2597 }
2598 if (toType.flags() & IsEnumeration) {
2599 if (fromTypeId == QString || fromTypeId == QByteArray)
2600 return true;
2601 return canConvert(fromType, toType: QMetaType(LongLong));
2602 }
2603 if (toTypeId == Nullptr && fromType.flags() & IsPointer)
2604 return true;
2605#ifndef QT_BOOTSTRAPPED
2606 if (canConvertMetaObject(fromType, toType))
2607 return true;
2608#endif
2609
2610 return false;
2611}
2612
2613/*!
2614 \fn bool QMetaType::compare(const void *lhs, const void *rhs, int typeId, int* result)
2615 \deprecated Use the non-static compare method instead
2616
2617 Compares the objects at \a lhs and \a rhs. Both objects need to be of type \a typeId.
2618 \a result is set to less than, equal to or greater than zero, if \a lhs is less than, equal to
2619 or greater than \a rhs. Returns \c true, if the comparison succeeded, otherwise \c false.
2620*/
2621
2622/*!
2623 \fn bool QMetaType::hasRegisteredConverterFunction()
2624 Returns \c true, if the meta type system has a registered conversion from type From to type To.
2625 \since 5.2
2626 \overload
2627 */
2628
2629/*!
2630 Returns \c true, if the meta type system has a registered conversion from meta type id \a fromType
2631 to \a toType
2632 \since 5.2
2633*/
2634bool QMetaType::hasRegisteredConverterFunction(QMetaType fromType, QMetaType toType)
2635{
2636 return customTypesConversionRegistry()->contains(k: qMakePair(value1: fromType.id(), value2: toType.id()));
2637}
2638
2639/*!
2640 \fn bool QMetaType::hasRegisteredMutableViewFunction()
2641 Returns \c true, if the meta type system has a registered mutable view on type From of type To.
2642 \since 6.0
2643 \overload
2644*/
2645
2646/*!
2647 Returns \c true, if the meta type system has a registered mutable view on meta type id
2648 \a fromType of meta type id \a toType.
2649 \since 5.2
2650*/
2651bool QMetaType::hasRegisteredMutableViewFunction(QMetaType fromType, QMetaType toType)
2652{
2653 return customTypesMutableViewRegistry()->contains(k: qMakePair(value1: fromType.id(), value2: toType.id()));
2654}
2655
2656/*!
2657 \fn const char *QMetaType::typeName(int typeId)
2658 \deprecated
2659
2660 Returns the type name associated with the given \a typeId, or a null
2661 pointer if no matching type was found. The returned pointer must not be
2662 deleted.
2663
2664 \sa type(), isRegistered(), Type, name()
2665*/
2666
2667/*!
2668 \fn constexpr const char *QMetaType::name() const
2669 \since 5.15
2670
2671 Returns the type name associated with this QMetaType, or a null
2672 pointer if no matching type was found. The returned pointer must not be
2673 deleted.
2674
2675 \sa typeName()
2676*/
2677
2678/*
2679 Similar to QMetaType::type(), but only looks in the static set of types.
2680*/
2681static inline int qMetaTypeStaticType(const char *typeName, int length)
2682{
2683 int i = 0;
2684 while (types[i].typeName && ((length != types[i].typeNameLength)
2685 || memcmp(s1: typeName, s2: types[i].typeName, n: length))) {
2686 ++i;
2687 }
2688 return types[i].type;
2689}
2690
2691/*
2692 Similar to QMetaType::type(), but only looks in the custom set of
2693 types, and doesn't lock the mutex.
2694
2695*/
2696static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
2697{
2698 if (customTypeRegistry.exists()) {
2699 auto reg = &*customTypeRegistry;
2700#if QT_CONFIG(thread)
2701 Q_ASSERT(!reg->lock.tryLockForWrite());
2702#endif
2703 if (auto ti = reg->aliases.value(key: QByteArray::fromRawData(data: typeName, size: length), defaultValue: nullptr)) {
2704 return ti->typeId.loadRelaxed();
2705 }
2706 }
2707 return QMetaType::UnknownType;
2708}
2709
2710/*!
2711 \internal
2712
2713 Registers a user type for marshalling, as an alias of another type (typedef).
2714 Note that normalizedTypeName is not checked for conformance with Qt's normalized format,
2715 so it must already conform.
2716*/
2717void QMetaType::registerNormalizedTypedef(const NS(QByteArray) & normalizedTypeName,
2718 QMetaType metaType)
2719{
2720 if (!metaType.isValid())
2721 return;
2722 if (auto reg = customTypeRegistry()) {
2723 QWriteLocker lock(&reg->lock);
2724 auto &al = reg->aliases[normalizedTypeName];
2725 if (al)
2726 return;
2727 al = metaType.d_ptr;
2728 }
2729}
2730
2731
2732static const QtPrivate::QMetaTypeInterface *interfaceForTypeNoWarning(int typeId)
2733{
2734 const QtPrivate::QMetaTypeInterface *iface = nullptr;
2735 if (typeId >= QMetaType::User) {
2736 if (customTypeRegistry.exists())
2737 iface = customTypeRegistry->getCustomType(id: typeId);
2738 } else {
2739 if (auto moduleHelper = qModuleHelperForType(type: typeId))
2740 iface = moduleHelper->interfaceForType(typeId);
2741 }
2742 return iface;
2743}
2744
2745/*!
2746 Returns \c true if the datatype with ID \a type is registered;
2747 otherwise returns \c false.
2748
2749 \sa type(), typeName(), Type
2750*/
2751bool QMetaType::isRegistered(int type)
2752{
2753 return interfaceForTypeNoWarning(typeId: type) != nullptr;
2754}
2755
2756template <bool tryNormalizedType>
2757static inline int qMetaTypeTypeImpl(const char *typeName, int length)
2758{
2759 if (!length)
2760 return QMetaType::UnknownType;
2761 int type = qMetaTypeStaticType(typeName, length);
2762 if (type == QMetaType::UnknownType) {
2763 QReadLocker locker(&customTypeRegistry()->lock);
2764 type = qMetaTypeCustomType_unlocked(typeName, length);
2765#ifndef QT_NO_QOBJECT
2766 if ((type == QMetaType::UnknownType) && tryNormalizedType) {
2767 const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(type: typeName);
2768 type = qMetaTypeStaticType(typeName: normalizedTypeName.constData(),
2769 length: normalizedTypeName.size());
2770 if (type == QMetaType::UnknownType) {
2771 type = qMetaTypeCustomType_unlocked(typeName: normalizedTypeName.constData(),
2772 length: normalizedTypeName.size());
2773 }
2774 }
2775#endif
2776 }
2777 return type;
2778}
2779
2780/*!
2781 \fn int QMetaType::type(const char *typeName)
2782 \deprecated
2783
2784 Returns a handle to the type called \a typeName, or QMetaType::UnknownType if there is
2785 no such type.
2786
2787 \sa isRegistered(), typeName(), Type
2788*/
2789
2790/*!
2791 \internal
2792
2793 Similar to QMetaType::type(); the only difference is that this function
2794 doesn't attempt to normalize the type name (i.e., the lookup will fail
2795 for type names in non-normalized form).
2796*/
2797Q_CORE_EXPORT int qMetaTypeTypeInternal(const char *typeName)
2798{
2799 return qMetaTypeTypeImpl</*tryNormalizedType=*/false>(typeName, length: int(qstrlen(str: typeName)));
2800}
2801
2802/*!
2803 \fn int QMetaType::type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName)
2804
2805 \since 5.5
2806 \overload
2807 \deprecated
2808
2809 Returns a handle to the type called \a typeName, or 0 if there is
2810 no such type.
2811
2812 \sa isRegistered(), typeName()
2813*/
2814
2815#ifndef QT_NO_DATASTREAM
2816/*!
2817 Writes the object pointed to by \a data to the given \a stream.
2818 Returns \c true if the object is saved successfully; otherwise
2819 returns \c false.
2820
2821 Normally, you should not need to call this function directly.
2822 Instead, use QVariant's \c operator<<(), which relies on save()
2823 to stream custom types.
2824
2825 \sa load()
2826*/
2827bool QMetaType::save(QDataStream &stream, const void *data) const
2828{
2829 if (!data || !isValid())
2830 return false;
2831
2832 // keep compatibility for long/ulong
2833 if (id() == QMetaType::Long) {
2834 stream << qlonglong(*(long *)data);
2835 return true;
2836 } else if (id() == QMetaType::ULong) {
2837 stream << qlonglong(*(unsigned long *)data);
2838 return true;
2839 }
2840
2841 if (!d_ptr->dataStreamOut)
2842 return false;
2843
2844 d_ptr->dataStreamOut(d_ptr, stream, data);
2845 return true;
2846}
2847
2848/*!
2849 \fn bool QMetaType::save(QDataStream &stream, int type, const void *data)
2850 \overload
2851 \deprecated
2852*/
2853
2854/*!
2855 Reads the object of this type from the given \a stream into \a data.
2856 Returns \c true if the object is loaded successfully; otherwise
2857 returns \c false.
2858
2859 Normally, you should not need to call this function directly.
2860 Instead, use QVariant's \c operator>>(), which relies on load()
2861 to stream custom types.
2862
2863 \sa save()
2864*/
2865bool QMetaType::load(QDataStream &stream, void *data) const
2866{
2867 if (!data || !isValid())
2868 return false;
2869
2870 // keep compatibility for long/ulong
2871 if (id() == QMetaType::Long) {
2872 qlonglong ll;
2873 stream >> ll;
2874 *(long *)data = long(ll);
2875 return true;
2876 } else if (id() == QMetaType::ULong) {
2877 qulonglong ull;
2878 stream >> ull;
2879 *(unsigned long *)data = (unsigned long)(ull);
2880 return true;
2881 }
2882 if (!d_ptr->dataStreamIn)
2883 return false;
2884
2885 d_ptr->dataStreamIn(d_ptr, stream, data);
2886 return true;
2887}
2888
2889/*!
2890 \since 6.1
2891
2892 Returns \c true, if the meta type system has registered data stream operators for this
2893 meta type.
2894*/
2895bool QMetaType::hasRegisteredDataStreamOperators() const
2896{
2897 int type = id();
2898 if (type == QMetaType::Long || type == QMetaType::ULong)
2899 return true;
2900 return d_ptr && d_ptr->dataStreamIn != nullptr && d_ptr->dataStreamOut != nullptr;
2901}
2902
2903/*!
2904 \since 6.6
2905
2906 If this metatype represents an enumeration, this method returns a
2907 metatype of a numeric class of the same signedness and size as the
2908 enums underlying type.
2909 If it represents a QFlags type, it returns QMetaType::Int.
2910 In all other cases an invalid QMetaType is returned.
2911 */
2912QMetaType QMetaType::underlyingType() const
2913{
2914 if (!d_ptr || !(flags() & IsEnumeration))
2915 return {};
2916 /* QFlags has enumeration set so that's handled here (qint32
2917 case), as QFlags uses int as the underlying type
2918 Note that we do some approximation here, as we cannot
2919 differentiate between different underlying types of the
2920 same size and signedness (consider char <-> (un)signed char,
2921 int <-> long <-> long long).
2922
2923 ### TODO PENDING: QTBUG-111926 - QFlags supporting >32 bit int
2924 */
2925 if (flags() & IsUnsignedEnumeration) {
2926 switch (sizeOf()) {
2927 case 1:
2928 return QMetaType::fromType<quint8>();
2929 case 2:
2930 return QMetaType::fromType<quint16>();
2931 case 4:
2932 return QMetaType::fromType<quint32>();
2933 case 8:
2934 return QMetaType::fromType<quint64>();
2935 default:
2936 break;
2937 }
2938 } else {
2939 switch (sizeOf()) {
2940 case 1:
2941 return QMetaType::fromType<qint8>();
2942 case 2:
2943 return QMetaType::fromType<qint16>();
2944 case 4:
2945 return QMetaType::fromType<qint32>();
2946 case 8:
2947 return QMetaType::fromType<qint64>();
2948 default:
2949 break;
2950 }
2951 }
2952 // int128 can be handled above once we have qint128
2953 return QMetaType();
2954}
2955
2956/*!
2957 \fn bool QMetaType::load(QDataStream &stream, int type, void *data)
2958 \overload
2959 \deprecated
2960*/
2961#endif // QT_NO_DATASTREAM
2962
2963/*!
2964 Returns a QMetaType matching \a typeName. The returned object is
2965 not valid if the typeName is not known to QMetaType
2966 */
2967QMetaType QMetaType::fromName(QByteArrayView typeName)
2968{
2969 return QMetaType(qMetaTypeTypeImpl</*tryNormalizedType=*/true>(typeName: typeName.data(), length: typeName.size()));
2970}
2971
2972/*!
2973 \fn void *QMetaType::create(int type, const void *copy)
2974 \deprecated
2975
2976 Returns a copy of \a copy, assuming it is of type \a type. If \a
2977 copy is zero, creates a default constructed instance.
2978
2979 \sa destroy(), isRegistered(), Type
2980*/
2981
2982/*!
2983 \fn void QMetaType::destroy(int type, void *data)
2984 \deprecated
2985 Destroys the \a data, assuming it is of the \a type given.
2986
2987 \sa create(), isRegistered(), Type
2988*/
2989
2990/*!
2991 \fn void *QMetaType::construct(int type, void *where, const void *copy)
2992 \since 5.0
2993 \deprecated
2994
2995 Constructs a value of the given \a type in the existing memory
2996 addressed by \a where, that is a copy of \a copy, and returns
2997 \a where. If \a copy is zero, the value is default constructed.
2998
2999 This is a low-level function for explicitly managing the memory
3000 used to store the type. Consider calling create() if you don't
3001 need this level of control (that is, use "new" rather than
3002 "placement new").
3003
3004 You must ensure that \a where points to a location that can store
3005 a value of type \a type, and that \a where is suitably aligned.
3006 The type's size can be queried by calling sizeOf().
3007
3008 The rule of thumb for alignment is that a type is aligned to its
3009 natural boundary, which is the smallest power of 2 that is bigger
3010 than the type, unless that alignment is larger than the maximum
3011 useful alignment for the platform. For practical purposes,
3012 alignment larger than 2 * sizeof(void*) is only necessary for
3013 special hardware instructions (e.g., aligned SSE loads and stores
3014 on x86).
3015
3016 \sa destruct(), sizeOf()
3017*/
3018
3019
3020/*!
3021 \fn void QMetaType::destruct(int type, void *where)
3022 \since 5.0
3023 \deprecated
3024
3025 Destructs the value of the given \a type, located at \a where.
3026
3027 Unlike destroy(), this function only invokes the type's
3028 destructor, it doesn't invoke the delete operator.
3029
3030 \sa construct()
3031*/
3032
3033/*!
3034 \fn int QMetaType::sizeOf(int type)
3035 \since 5.0
3036 \deprecated
3037
3038 Returns the size of the given \a type in bytes (i.e. sizeof(T),
3039 where T is the actual type identified by the \a type argument).
3040
3041 This function is typically used together with construct()
3042 to perform low-level management of the memory used by a type.
3043
3044 \sa construct(), QMetaType::alignOf()
3045*/
3046
3047/*!
3048 \fn QMetaType::TypeFlags QMetaType::typeFlags(int type)
3049 \since 5.0
3050 \deprecated
3051
3052 Returns flags of the given \a type.
3053
3054 \sa QMetaType::TypeFlags
3055*/
3056
3057/*!
3058 \fn const QMetaObject *QMetaType::metaObjectForType(int type)
3059 \since 5.0
3060 \deprecated
3061
3062 returns QMetaType::metaObject for \a type
3063
3064 \sa metaObject()
3065*/
3066
3067/*!
3068 \fn int qRegisterMetaType(const char *typeName)
3069 \relates QMetaType
3070 \obsolete
3071 \threadsafe
3072
3073 Registers the type name \a typeName for the type \c{T}. Returns
3074 the internal ID used by QMetaType. Any class or struct that has a
3075 public default constructor, a public copy constructor and a public
3076 destructor can be registered.
3077
3078 This function requires that \c{T} is a fully defined type at the point
3079 where the function is called. For pointer types, it also requires that the
3080 pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
3081 to register pointers to forward declared types.
3082
3083 After a type has been registered, you can create and destroy
3084 objects of that type dynamically at run-time.
3085
3086 This example registers the class \c{MyClass}:
3087
3088 \snippet code/src_corelib_kernel_qmetatype.cpp 4
3089
3090 This function is useful to register typedefs so they can be used
3091 by QMetaProperty, or in QueuedConnections
3092
3093 \snippet code/src_corelib_kernel_qmetatype.cpp 9
3094
3095 \warning This function is useful only for registering an alias (typedef)
3096 for every other use case Q_DECLARE_METATYPE and qMetaTypeId() should be used instead.
3097
3098 \sa {QMetaType::}{isRegistered()}, Q_DECLARE_METATYPE()
3099*/
3100
3101/*!
3102 \fn int qRegisterMetaType()
3103 \relates QMetaType
3104 \threadsafe
3105 \since 4.2
3106
3107 Call this function to register the type \c T. Returns the meta type Id.
3108
3109 Example:
3110
3111 \snippet code/src_corelib_kernel_qmetatype.cpp 7
3112
3113 This function requires that \c{T} is a fully defined type at the point
3114 where the function is called. For pointer types, it also requires that the
3115 pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
3116 to register pointers to forward declared types.
3117
3118 To use the type \c T in QMetaType, QVariant, or with the
3119 QObject::property() API, registration is not necessary.
3120
3121 To use the type \c T in queued signal and slot connections,
3122 \c{qRegisterMetaType<T>()} must be called before the first connection is
3123 established. That is typically done in the constructor of the class that
3124 uses \c T, or in the \c{main()} function.
3125
3126 After a type has been registered, it can be found by its name using
3127 QMetaType::fromName().
3128
3129 \sa Q_DECLARE_METATYPE()
3130 */
3131
3132/*!
3133 \fn int qRegisterMetaType(QMetaType meta)
3134 \relates QMetaType
3135 \threadsafe
3136 \since 6.5
3137
3138 Registers the meta type \a meta and returns its type Id.
3139
3140 This function requires that \c{T} is a fully defined type at the point
3141 where the function is called. For pointer types, it also requires that the
3142 pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
3143 to register pointers to forward declared types.
3144
3145 To use the type \c T in QMetaType, QVariant, or with the
3146 QObject::property() API, registration is not necessary.
3147
3148 To use the type \c T in queued signal and slot connections,
3149 \c{qRegisterMetaType<T>()} must be called before the first connection is
3150 established. That is typically done in the constructor of the class that
3151 uses \c T, or in the \c{main()} function.
3152
3153 After a type has been registered, it can be found by its name using
3154 QMetaType::fromName().
3155 */
3156
3157/*!
3158 \fn int qMetaTypeId()
3159 \relates QMetaType
3160 \threadsafe
3161 \since 4.1
3162
3163 Returns the meta type id of type \c T at compile time. If the
3164 type was not declared with Q_DECLARE_METATYPE(), compilation will
3165 fail.
3166
3167 Typical usage:
3168
3169 \snippet code/src_corelib_kernel_qmetatype.cpp 8
3170
3171 QMetaType::type() returns the same ID as qMetaTypeId(), but does
3172 a lookup at runtime based on the name of the type.
3173 QMetaType::type() is a bit slower, but compilation succeeds if a
3174 type is not registered.
3175
3176 \sa Q_DECLARE_METATYPE(), QMetaType::type()
3177*/
3178
3179static const QtPrivate::QMetaTypeInterface *interfaceForType(int typeId)
3180{
3181 const QtPrivate::QMetaTypeInterface *iface = interfaceForTypeNoWarning(typeId);
3182 if (!iface && typeId != QMetaType::UnknownType)
3183 qWarning(msg: "Trying to construct an instance of an invalid type, type id: %i", typeId);
3184
3185 return iface;
3186}
3187
3188/*!
3189 \fn QMetaType::QMetaType()
3190 \since 6.0
3191
3192 Constructs a default, invalid, QMetaType object.
3193*/
3194
3195/*!
3196 \fn QMetaType::QMetaType(int typeId)
3197 \since 5.0
3198
3199 Constructs a QMetaType object that contains all information about type \a typeId.
3200*/
3201QMetaType::QMetaType(int typeId) : QMetaType(interfaceForType(typeId)) {}
3202
3203
3204/*! \fn size_t qHash(QMetaType type, size_t seed = 0)
3205 \relates QMetaType
3206 \since 6.4
3207
3208 Returns the hash value for the \a type, using \a seed to seed the calculation.
3209*/
3210
3211namespace QtPrivate {
3212#if !defined(QT_BOOTSTRAPPED) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY)
3213
3214// Explicit instantiation definition
3215#define QT_METATYPE_DECLARE_TEMPLATE_ITER(TypeName, Id, Name) \
3216 template class QMetaTypeForType<Name>; \
3217 template struct QMetaTypeInterfaceWrapper<Name>;
3218QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(QT_METATYPE_DECLARE_TEMPLATE_ITER)
3219QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_DECLARE_TEMPLATE_ITER)
3220QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_DECLARE_TEMPLATE_ITER)
3221QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_DECLARE_TEMPLATE_ITER)
3222QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_DECLARE_TEMPLATE_ITER)
3223
3224#undef QT_METATYPE_DECLARE_TEMPLATE_ITER
3225#endif
3226}
3227
3228QT_END_NAMESPACE
3229

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