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