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 template <typename T> constexpr bool QMetaType::isSameType() const
594 \since 6.12
595
596 Returns \c true if this QMetaType describes type \c{T}.
597
598 This function is slightly faster than comparing id() to
599 \c{qMetaTypeId<T>()}.
600
601 \sa id(), qMetaTypeId(), fromType()
602*/
603
604/*!
605 \fn void QMetaType::registerType() const
606 \since 6.5
607
608 Registers this QMetaType with the type registry so it can be found by name,
609 using QMetaType::fromName().
610
611 \sa qRegisterMetaType()
612 */
613#ifndef QT_BOOTSTRAPPED
614/*!
615 \internal
616 Out-of-line path for registerType() and slow path id().
617 */
618int QMetaType::registerHelper(const QtPrivate::QMetaTypeInterface *iface)
619{
620 Q_ASSERT(iface);
621 auto reg = customTypeRegistry();
622 if (reg) {
623 return reg->registerCustomType(iface);
624 }
625 return 0;
626}
627#endif
628
629/*!
630 \fn constexpr qsizetype QMetaType::sizeOf() const
631 \since 5.0
632
633 Returns the size of the type in bytes (i.e. sizeof(T),
634 where T is the actual type for which this QMetaType instance
635 was constructed for).
636
637 This function is typically used together with construct()
638 to perform low-level management of the memory used by a type.
639
640 \sa QMetaType::construct(), QMetaType::alignOf()
641*/
642
643/*!
644 \fn constexpr int QMetaType::alignOf() const
645 \since 6.0
646
647 Returns the alignment of the type in bytes (i.e. alignof(T),
648 where T is the actual type for which this QMetaType instance
649 was constructed for).
650
651 This function is typically used together with construct()
652 to perform low-level management of the memory used by a type.
653
654 \sa QMetaType::construct(), QMetaType::sizeOf()
655
656 */
657
658/*!
659 \fn constexpr TypeFlags QMetaType::flags() const
660 \since 5.0
661
662 Returns flags of the type for which this QMetaType instance was
663 constructed. To inspect specific type traits, prefer using one of the "is-"
664 functions rather than the flags directly.
665
666 \sa QMetaType::TypeFlags, isDefaultConstructible(),
667 isCopyConstructible(), isMoveConstructible(), isDestructible(),
668 isEqualityComparable(), isOrdered()
669*/
670
671/*!
672 \fn constexpr const QMetaObject *QMetaType::metaObject() const
673 \since 5.5
674
675 Returns a QMetaObject relative to this type.
676
677 If the type is a pointer type to a subclass of QObject, flags() contains
678 QMetaType::PointerToQObject and this function returns the corresponding QMetaObject.
679 This can be used in combination with QMetaObject::newInstance() to create QObjects of this type.
680
681 If the type is a Q_GADGET, flags() contains QMetaType::IsGadget.
682 If the type is a pointer to a Q_GADGET, flags() contains QMetaType::PointerToGadget.
683 In both cases, this function returns its QMetaObject.
684 This can be used to retrieve QMetaMethod and QMetaProperty and use them on a
685 pointer of this type for example, as given by QVariant::data().
686
687 If the type is an enumeration, flags() contains QMetaType::IsEnumeration.
688 In this case, this function returns the QMetaObject of the enclosing
689 object if the enum was registered as a Q_ENUM or \nullptr otherwise.
690
691 \sa QMetaType::flags()
692*/
693
694/*!
695 \fn void *QMetaType::create(const void *copy = nullptr) const
696 \since 5.0
697
698 Returns a copy of \a copy, assuming it is of the type that this
699 QMetaType instance was created for. If \a copy is \nullptr, creates
700 a default constructed instance.
701
702 \sa QMetaType::destroy()
703*/
704void *QMetaType::create(const void *copy) const
705{
706 if (copy ? !isCopyConstructible() : !isDefaultConstructible())
707 return nullptr;
708
709 std::unique_ptr<void, QMetaTypeDeleter> where(nullptr, {d_ptr});
710 if (d_ptr->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
711 where.reset(operator new(d_ptr->size, std::align_val_t(d_ptr->alignment), std::nothrow_t{}));
712 else
713 where.reset(operator new(d_ptr->size, std::nothrow_t{}));
714
715 QtMetaTypePrivate::construct(d_ptr, where.get(), copy);
716 return where.release();
717}
718
719/*!
720 \fn void QMetaType::destroy(void *data) const
721 \since 5.0
722
723 Destroys the \a data, assuming it is of the type that this
724 QMetaType instance was created for.
725
726 \sa QMetaType::create()
727*/
728void QMetaType::destroy(void *data) const
729{
730 if (data && isDestructible()) {
731 QtMetaTypePrivate::destruct(d_ptr, data);
732 QMetaTypeDeleter{d_ptr}(data);
733 }
734}
735
736/*!
737 \fn void *QMetaType::construct(void *where, const void *copy = nullptr) const
738 \since 5.0
739
740 Constructs a value of the type that this QMetaType instance
741 was constructed for in the existing memory addressed by \a where,
742 that is a copy of \a copy, and returns \a where. If \a copy is
743 zero, the value is default constructed.
744
745 This is a low-level function for explicitly managing the memory
746 used to store the type. Consider calling create() if you don't
747 need this level of control (that is, use "new" rather than
748 "placement new").
749
750 You must ensure that \a where points to a location where the new
751 value can be stored and that \a where is suitably aligned.
752 The type's size can be queried by calling sizeOf().
753
754 The rule of thumb for alignment is that a type is aligned to its
755 natural boundary, which is the smallest power of 2 that is bigger
756 than the type, unless that alignment is larger than the maximum
757 useful alignment for the platform. For practical purposes,
758 alignment larger than 2 * sizeof(void*) is only necessary for
759 special hardware instructions (e.g., aligned SSE loads and stores
760 on x86).
761*/
762void *QMetaType::construct(void *where, const void *copy) const
763{
764 if (!where)
765 return nullptr;
766 if (copy ? !isCopyConstructible() : !isDefaultConstructible())
767 return nullptr;
768
769 QtMetaTypePrivate::construct(d_ptr, where, copy);
770 return where;
771}
772
773/*!
774 \fn void QMetaType::destruct(void *data) const
775 \since 5.0
776
777 Destructs the value, located at \a data, assuming that it is
778 of the type for which this QMetaType instance was constructed for.
779
780 Unlike destroy(), this function only invokes the type's
781 destructor, it doesn't invoke the delete operator.
782 \sa QMetaType::construct()
783*/
784void QMetaType::destruct(void *data) const
785{
786 if (data && isDestructible())
787 QtMetaTypePrivate::destruct(d_ptr, data);
788}
789
790static QPartialOrdering threeWayCompare(const void *ptr1, const void *ptr2)
791{
792 std::less<const void *> less;
793 if (less(ptr1, ptr2))
794 return QPartialOrdering::Less;
795 if (less(ptr2, ptr1))
796 return QPartialOrdering::Greater;
797 return QPartialOrdering::Equivalent;
798}
799
800/*!
801 Compares the objects at \a lhs and \a rhs for ordering.
802
803 Returns QPartialOrdering::Unordered if comparison is not supported
804 or the values are unordered. Otherwise, returns
805 QPartialOrdering::Less, QPartialOrdering::Equivalent or
806 QPartialOrdering::Greater if \a lhs is less than, equivalent
807 to or greater than \a rhs, respectively.
808
809 Both objects must be of the type described by this metatype. If either \a lhs
810 or \a rhs is \nullptr, the values are unordered. Comparison is only supported
811 if the type's less than operator was visible to the metatype declaration.
812
813 If the type's equality operator was also visible, values will only compare equal if the
814 equality operator says they are. In the absence of an equality operator, when neither
815 value is less than the other, values are considered equal; if equality is also available
816 and two such values are not equal, they are considered unordered, just as NaN (not a
817 number) values of a floating point type lie outside its ordering.
818
819 \note If no less than operator was visible to the metatype declaration, values are
820 unordered even if an equality operator visible to the declaration considers them equal:
821 \c{compare() == 0} only agrees with equals() if the less than operator was visible.
822
823 \since 6.0
824 \sa equals(), isOrdered()
825*/
826QPartialOrdering QMetaType::compare(const void *lhs, const void *rhs) const
827{
828 if (!lhs || !rhs)
829 return QPartialOrdering::Unordered;
830 if (d_ptr && d_ptr->flags & QMetaType::IsPointer)
831 return threeWayCompare(*reinterpret_cast<const void * const *>(lhs),
832 *reinterpret_cast<const void * const *>(rhs));
833 if (d_ptr && d_ptr->lessThan) {
834 if (d_ptr->equals && d_ptr->equals(d_ptr, lhs, rhs))
835 return QPartialOrdering::Equivalent;
836 if (d_ptr->lessThan(d_ptr, lhs, rhs))
837 return QPartialOrdering::Less;
838 if (d_ptr->lessThan(d_ptr, rhs, lhs))
839 return QPartialOrdering::Greater;
840 if (!d_ptr->equals)
841 return QPartialOrdering::Equivalent;
842 }
843 return QPartialOrdering::Unordered;
844}
845
846/*!
847 Compares the objects at \a lhs and \a rhs for equality.
848
849 Both objects must be of the type described by this metatype. Can only compare the
850 two objects if a less than or equality operator for the type was visible to the
851 metatype declaration. Otherwise, the metatype never considers values equal. When
852 an equality operator was visible to the metatype declaration, it is authoritative;
853 otherwise, if less than is visible, when neither value is less than the other, the
854 two are considered equal. If values are unordered (see compare() for details) they
855 are not equal.
856
857 Returns true if the two objects compare equal, otherwise false.
858
859 \since 6.0
860 \sa isEqualityComparable(), compare()
861*/
862bool QMetaType::equals(const void *lhs, const void *rhs) const
863{
864 if (!lhs || !rhs)
865 return false;
866 if (d_ptr) {
867 if (d_ptr->flags & QMetaType::IsPointer)
868 return *reinterpret_cast<const void * const *>(lhs) == *reinterpret_cast<const void * const *>(rhs);
869
870 if (d_ptr->equals)
871 return d_ptr->equals(d_ptr, lhs, rhs);
872 if (d_ptr->lessThan && !d_ptr->lessThan(d_ptr, lhs, rhs) && !d_ptr->lessThan(d_ptr, rhs, lhs))
873 return true;
874 }
875 return false;
876}
877
878/*!
879 \fn bool QMetaType::isDefaultConstructible() const noexcept
880 \since 6.5
881
882 Returns true if this type can be default-constructed. If it can be, then
883 construct() and create() can be used with a \c{copy} parameter that is
884 null.
885
886 \sa flags(), isCopyConstructible(), isMoveConstructible(), isDestructible()
887 */
888
889/*!
890 \fn bool QMetaType::isCopyConstructible() const noexcept
891 \since 6.5
892
893 Returns true if this type can be copy-constructed. If it can be, then
894 construct() and create() can be used with a \c{copy} parameter that is
895 not null.
896
897 \sa flags(), isDefaultConstructible(), isMoveConstructible(), isDestructible()
898 */
899
900/*!
901 \fn bool QMetaType::isMoveConstructible() const noexcept
902 \since 6.5
903
904 Returns true if this type can be move-constructed. QMetaType currently does
905 not have an API to make use of this trait.
906
907 \sa flags(), isDefaultConstructible(), isCopyConstructible(), isDestructible()
908 */
909
910/*!
911 \fn bool QMetaType::isDestructible() const noexcept
912 \since 6.5
913
914 Returns true if this type can be destroyed. If it can be, then destroy()
915 and destruct() can be called.
916
917 \sa flags(), isDefaultConstructible(), isCopyConstructible(), isMoveConstructible()
918 */
919
920bool QMetaType::isDefaultConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
921{
922 return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isDefaultConstructible(iface);
923}
924
925bool QMetaType::isCopyConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
926{
927 return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isCopyConstructible(iface);
928}
929
930bool QMetaType::isMoveConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
931{
932 return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isMoveConstructible(iface);
933}
934
935bool QMetaType::isDestructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
936{
937 return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isDestructible(iface);
938}
939
940/*!
941 Returns \c true if a less than or equality operator for the type described by
942 this metatype was visible to the metatype declaration, otherwise \c false.
943
944 \sa equals(), isOrdered()
945*/
946bool QMetaType::isEqualityComparable() const
947{
948 return d_ptr && (d_ptr->flags & QMetaType::IsPointer || d_ptr->equals != nullptr || d_ptr->lessThan != nullptr);
949}
950
951/*!
952 Returns \c true if a less than operator for the type described by this metatype
953 was visible to the metatype declaration, otherwise \c false.
954
955 \sa compare(), isEqualityComparable()
956*/
957bool QMetaType::isOrdered() const
958{
959 return d_ptr && (d_ptr->flags & QMetaType::IsPointer || d_ptr->lessThan != nullptr);
960}
961
962#ifndef QT_BOOTSTRAPPED
963/*!
964 \internal
965*/
966void QMetaType::unregisterMetaType(QMetaType type)
967{
968 const QtPrivate::QMetaTypeInterface *d_ptr = type.d_ptr;
969 if (!d_ptr)
970 return;
971
972 const int typeId = d_ptr->typeId.loadRelaxed();
973 if (typeId < QMetaType::User)
974 return;
975
976 // this is a custom meta type (not read-only)
977
978 if (auto reg = customTypeRegistry()) {
979 Q_ASSERT(reg->getCustomType(typeId) == d_ptr);
980 reg->unregisterDynamicType(typeId);
981 }
982
983 const_cast<QtPrivate::QMetaTypeInterface *>(d_ptr)->typeId.storeRelease(0);
984}
985#endif
986
987/*!
988 \fn template<typename T> QMetaType QMetaType::fromType()
989 \since 5.15
990
991 Returns the QMetaType corresponding to the type in the template parameter.
992*/
993
994/*! \fn bool QMetaType::operator==(const QMetaType &lhs, const QMetaType &rhs)
995 \since 5.15
996 \overload
997
998 Returns \c true if the QMetaType \a lhs represents the same type
999 as the QMetaType \a rhs, otherwise returns \c false.
1000*/
1001
1002/*! \fn bool QMetaType::operator!=(const QMetaType &lhs, const QMetaType &rhs)
1003 \since 5.15
1004 \overload
1005
1006 Returns \c true if the QMetaType \a lhs represents a different type
1007 than the QMetaType \a rhs, otherwise returns \c false.
1008*/
1009
1010static constexpr auto createStaticTypeToIdMap()
1011{
1012#define QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, RealName)
1013 #RealName,
1014#define QT_ADD_STATIC_METATYPE_ALIASES_ITER(MetaTypeName, MetaTypeId, AliasingName, RealNameStr)
1015 RealNameStr,
1016 constexpr auto staticTypeNames = qOffsetStringArray(
1017 QT_FOR_EACH_STATIC_TYPE(QT_ADD_STATIC_METATYPE)
1018 QT_FOR_EACH_STATIC_ALIAS_TYPE(QT_ADD_STATIC_METATYPE_ALIASES_ITER)
1019 "qreal"
1020 );
1021 constexpr int Count = staticTypeNames.count();
1022#undef QT_ADD_STATIC_METATYPE
1023#undef QT_ADD_STATIC_METATYPE_ALIASES_ITER
1024
1025#define QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, RealName)
1026 MetaTypeId,
1027#define QT_ADD_STATIC_METATYPE_ALIASES_ITER(MetaTypeName, MetaTypeId, AliasingName, RealNameStr)
1028 QMetaType::MetaTypeName,
1029 std::array<int, Count> typeIds = {
1030 QT_FOR_EACH_STATIC_TYPE(QT_ADD_STATIC_METATYPE)
1031 QT_FOR_EACH_STATIC_ALIAS_TYPE(QT_ADD_STATIC_METATYPE_ALIASES_ITER)
1032 QMetaTypeId2<qreal>::MetaType,
1033 };
1034#undef QT_ADD_STATIC_METATYPE
1035#undef QT_ADD_STATIC_METATYPE_ALIASES_ITER
1036
1037 using Base = std::remove_cv_t<decltype(staticTypeNames)>;
1038 using Array = std::remove_cv_t<decltype(typeIds)>;
1039 struct Map : Base {
1040 constexpr Map(const Base &base, const Array &typeIdMap)
1041 : Base(base), typeIdMap(typeIdMap)
1042 {}
1043 std::array<int, Count> typeIdMap;
1044 };
1045
1046 return Map(staticTypeNames, typeIds);
1047}
1048static constexpr auto types = createStaticTypeToIdMap();
1049
1050template <typename From, typename To>
1051static bool qIntegerConversionFromFPHelper(From from, To *to)
1052{
1053#ifndef Q_CC_GHS
1054 // actually is_floating_point, but include qfloat16:
1055 static_assert(std::numeric_limits<From>::is_iec559);
1056#endif
1057 static_assert(std::is_integral_v<To>);
1058 static_assert(sizeof(From) <= sizeof(double));
1059 const double fromD = static_cast<double>(from);
1060
1061 if (qt_is_nan(fromD)) {
1062 *to = To(0);
1063 return false;
1064 }
1065
1066 qint64 result;
1067 convertDoubleTo(std::round(fromD), &result);
1068 *to = To(result);
1069 return true;
1070}
1071
1072namespace {
1073struct QCoreVariantHelper : QMetaTypeModuleHelper
1074{
1075 template<typename T, typename LiteralWrapper =
1076 std::conditional_t<std::is_same_v<T, QString>, QLatin1StringView, const char *>>
1077 static inline bool convertToBool(const T &source)
1078 {
1079 T str = source.toLower();
1080 return !(str.isEmpty() || str == LiteralWrapper("0") || str == LiteralWrapper("false"));
1081 }
1082
1083 static const QtPrivate::QMetaTypeInterface *interfaceForType(int type)
1084 {
1085 switch (type) {
1086 QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_CONVERT_ID_TO_TYPE)
1087 QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_CONVERT_ID_TO_TYPE)
1088 QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_CONVERT_ID_TO_TYPE)
1089 QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_CONVERT_ID_TO_TYPE)
1090 QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_CONVERT_ID_TO_TYPE)
1091 default:
1092 return nullptr;
1093 }
1094 }
1095
1096 static bool convert(const void *from, int fromTypeId, void *to, int toTypeId)
1097 {
1098 Q_ASSERT(fromTypeId != toTypeId);
1099
1100#ifdef QT_BOOTSTRAPPED
1101 Q_UNUSED(from);
1102 Q_UNUSED(to);
1103#else
1104 // canConvert calls with two nullptr
1105 bool onlyCheck = (from == nullptr && to == nullptr);
1106
1107 // other callers must provide two valid pointers
1108 Q_ASSERT(onlyCheck || (bool(from) && bool(to)));
1109
1110 using Char = char;
1111 using SChar = signed char;
1112 using UChar = unsigned char;
1113 using Short = short;
1114 using UShort = unsigned short;
1115 using Int = int;
1116 using UInt = unsigned int;
1117 using Long = long;
1118 using LongLong = qlonglong;
1119 using ULong = unsigned long;
1120 using ULongLong = qulonglong;
1121 using Float16 = qfloat16;
1122 using Float = float;
1123 using Double = double;
1124 using Bool = bool;
1125 using Nullptr = std::nullptr_t;
1126 using Char16 = char16_t;
1127 using Char32 = char32_t;
1128
1129#define QMETATYPE_CONVERTER_ASSIGN_DOUBLE(To, From)
1130 QMETATYPE_CONVERTER(To, From, result = double(source); return true;)
1131#define QMETATYPE_CONVERTER_ASSIGN_NUMBER(To, From)
1132 QMETATYPE_CONVERTER(To, From, result = To::number(source); return true;)
1133#define CONVERT_CBOR_AND_JSON(To)
1134 QMETATYPE_CONVERTER(To, QCborValue,
1135 if constexpr(std::is_same_v<To, Bool>) {
1136 if (!source.isBool())
1137 return false;
1138 result = source.toBool();
1139 } else {
1140 if (!source.isInteger() && !source.isDouble())
1141 return false;
1142 if constexpr(std::is_integral_v<To>)
1143 result = source.toInteger();
1144 else
1145 result = To(source.toDouble());
1146 }
1147 return true;
1148 );
1149 QMETATYPE_CONVERTER(To, QJsonValue,
1150 if constexpr(std::is_same_v<To, Bool>) {
1151 if (!source.isBool())
1152 return false;
1153 result = source.toBool();
1154 } else {
1155 if (!source.isDouble())
1156 return false;
1157 if constexpr(std::is_integral_v<To>)
1158 result = source.toInteger();
1159 else
1160 result = To(source.toDouble());
1161 }
1162 return true;
1163 )
1164
1165#define INTEGRAL_CONVERTER(To)
1168 QMETATYPE_CONVERTER_ASSIGN(To, UChar);
1169 QMETATYPE_CONVERTER_ASSIGN(To, SChar);
1170 QMETATYPE_CONVERTER_ASSIGN(To, Short);
1171 QMETATYPE_CONVERTER_ASSIGN(To, UShort);
1175 QMETATYPE_CONVERTER_ASSIGN(To, ULong);
1176 QMETATYPE_CONVERTER_ASSIGN(To, LongLong);
1177 QMETATYPE_CONVERTER_ASSIGN(To, ULongLong);
1178 QMETATYPE_CONVERTER(To, Float16, return qIntegerConversionFromFPHelper(source, &result););
1179 QMETATYPE_CONVERTER(To, Float, return qIntegerConversionFromFPHelper(source, &result););
1180 QMETATYPE_CONVERTER(To, Double, return qIntegerConversionFromFPHelper(source, &result););
1181 QMETATYPE_CONVERTER(To, QChar, result = source.unicode(); return true;);
1182 QMETATYPE_CONVERTER(To, QString,
1183 bool ok = false;
1184 if constexpr(std::is_same_v<To, bool>)
1185 result = (ok = true, convertToBool(source));
1186 else if constexpr(std::is_signed_v<To>)
1187 result = To(source.toLongLong(&ok));
1188 else
1189 result = To(source.toULongLong(&ok));
1190 return ok;
1191 );
1192 QMETATYPE_CONVERTER(To, QByteArray,
1193 bool ok = false;
1194 if constexpr(std::is_same_v<To, bool>)
1195 result = (ok = true, convertToBool(source));
1196 else if constexpr(std::is_signed_v<To>)
1197 result = To(source.toLongLong(&ok));
1198 else
1199 result = To(source.toULongLong(&ok));
1200 return ok;
1201 );
1203
1204#define FLOAT_CONVERTER(To)
1207 QMETATYPE_CONVERTER_ASSIGN(To, UChar);
1208 QMETATYPE_CONVERTER_ASSIGN(To, SChar);
1209 QMETATYPE_CONVERTER_ASSIGN(To, Short);
1210 QMETATYPE_CONVERTER_ASSIGN(To, UShort);
1214 QMETATYPE_CONVERTER_ASSIGN(To, ULong);
1215 QMETATYPE_CONVERTER_ASSIGN(To, LongLong);
1216 QMETATYPE_CONVERTER_ASSIGN(To, ULongLong);
1217 QMETATYPE_CONVERTER_ASSIGN(To, Float16);
1218 QMETATYPE_CONVERTER_ASSIGN(To, Float);
1219 QMETATYPE_CONVERTER_ASSIGN(To, Double);
1220 QMETATYPE_CONVERTER(To, QString,
1221 bool ok = false;
1222 result = To(source.toDouble(&ok));
1223 return ok;
1224 );
1225 QMETATYPE_CONVERTER(To, QByteArray,
1226 bool ok = false;
1227 result = To(source.toDouble(&ok));
1228 return ok;
1229 );
1231
1232 switch (makePair(toTypeId, fromTypeId)) {
1233QT_WARNING_PUSH
1234QT_WARNING_DISABLE_CLANG("-Wtautological-compare")
1235 // integral conversions
1236 INTEGRAL_CONVERTER(Bool);
1237 INTEGRAL_CONVERTER(Char);
1238 INTEGRAL_CONVERTER(UChar);
1239 INTEGRAL_CONVERTER(SChar);
1240 INTEGRAL_CONVERTER(Short);
1241 INTEGRAL_CONVERTER(UShort);
1242 INTEGRAL_CONVERTER(Int);
1243 INTEGRAL_CONVERTER(UInt);
1244 INTEGRAL_CONVERTER(Long);
1245 INTEGRAL_CONVERTER(ULong);
1246 INTEGRAL_CONVERTER(LongLong);
1247 INTEGRAL_CONVERTER(ULongLong);
1248 FLOAT_CONVERTER(Float16);
1249 FLOAT_CONVERTER(Float);
1250 FLOAT_CONVERTER(Double);
1251
1252 QMETATYPE_CONVERTER_ASSIGN(QUrl, QString);
1253 QMETATYPE_CONVERTER(QUrl, QCborValue,
1254 if (source.isUrl()) {
1255 result = source.toUrl();
1256 return true;
1257 }
1258 return false;
1259 );
1260#if QT_CONFIG(itemmodel)
1261 QMETATYPE_CONVERTER_ASSIGN(QModelIndex, QPersistentModelIndex);
1262 QMETATYPE_CONVERTER_ASSIGN(QPersistentModelIndex, QModelIndex);
1263#endif // QT_CONFIG(itemmodel)
1264
1265 // QChar methods
1266#define QMETATYPE_CONVERTER_ASSIGN_QCHAR(From)
1267 QMETATYPE_CONVERTER(QChar, From, result = QChar::fromUcs2(source); return true;)
1281
1282 QMETATYPE_CONVERTER(Char16, QChar, result = source.unicode(); return true;)
1283
1284 // conversions to QString
1285 QMETATYPE_CONVERTER_ASSIGN(QString, QChar);
1286 QMETATYPE_CONVERTER(QString, Bool,
1287 result = source ? QStringLiteral("true") : QStringLiteral("false");
1288 return true;
1289 );
1290 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, Short);
1291 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, Long);
1293 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, LongLong);
1294 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, UShort);
1295 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, ULong);
1296 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, UInt);
1297 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, ULongLong);
1298 QMETATYPE_CONVERTER(QString, Float16,
1299 result = QString::number(source, 'g', QLocale::FloatingPointShortest);
1300 return true;
1301 );
1302 QMETATYPE_CONVERTER(QString, Float,
1303 result = QString::number(source, 'g', QLocale::FloatingPointShortest);
1304 return true;
1305 );
1306 QMETATYPE_CONVERTER(QString, Double,
1307 result = QString::number(source, 'g', QLocale::FloatingPointShortest);
1308 return true;
1309 );
1310 QMETATYPE_CONVERTER(QString, Char,
1311 result = QString::fromLatin1(&source, 1);
1312 return true;
1313 );
1314 QMETATYPE_CONVERTER(QString, SChar,
1315 char s = source;
1316 result = QString::fromLatin1(&s, 1);
1317 return true;
1318 );
1319 QMETATYPE_CONVERTER(QString, UChar,
1320 char s = source;
1321 result = QString::fromLatin1(&s, 1);
1322 return true;
1323 );
1324 QMETATYPE_CONVERTER(QString, Char16,
1325 result = QChar(source);
1326 return true;
1327 );
1328 QMETATYPE_CONVERTER(QString, Char32,
1329 result = QStringView(QChar::fromUcs4(source)).toString();
1330 return true;
1331 );
1332#if QT_CONFIG(datestring)
1333 QMETATYPE_CONVERTER(QString, QDate, result = source.toString(Qt::ISODate); return true;);
1334 QMETATYPE_CONVERTER(QString, QTime, result = source.toString(Qt::ISODateWithMs); return true;);
1335 QMETATYPE_CONVERTER(QString, QDateTime, result = source.toString(Qt::ISODateWithMs); return true;);
1336#endif
1337 QMETATYPE_CONVERTER(QString, QByteArray, result = QString::fromUtf8(source); return true;);
1338 QMETATYPE_CONVERTER(QString, QStringList,
1339 return (source.size() == 1) ? (result = source.at(0), true) : false;
1340 );
1341 QMETATYPE_CONVERTER(QString, QUrl, result = source.toString(); return true;);
1342 QMETATYPE_CONVERTER(QString, QJsonValue,
1343 if (source.isString() || source.isNull()) {
1344 result = source.toString();
1345 return true;
1346 }
1347 return false;
1348 );
1349 QMETATYPE_CONVERTER(QString, Nullptr, Q_UNUSED(source); result = QString(); return true;);
1350
1351 // QByteArray
1352 QMETATYPE_CONVERTER(QByteArray, QString, result = source.toUtf8(); return true;);
1354 result = source ? "true" : "false";
1355 return true;
1356 );
1357 QMETATYPE_CONVERTER(QByteArray, Char, result = QByteArray(source, 1); return true;);
1358 QMETATYPE_CONVERTER(QByteArray, SChar, result = QByteArray(source, 1); return true;);
1359 QMETATYPE_CONVERTER(QByteArray, UChar, result = QByteArray(source, 1); return true;);
1360 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, Short);
1361 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, Long);
1362 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, Int);
1363 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, LongLong);
1364 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, UShort);
1365 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, ULong);
1366 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, UInt);
1367 QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, ULongLong);
1369 result = QByteArray::number(source, 'g', QLocale::FloatingPointShortest);
1370 return true;
1371 );
1373 result = QByteArray::number(source, 'g', QLocale::FloatingPointShortest);
1374 return true;
1375 );
1377 result = QByteArray::number(source, 'g', QLocale::FloatingPointShortest);
1378 return true;
1379 );
1380 QMETATYPE_CONVERTER(QByteArray, Nullptr, Q_UNUSED(source); result = QByteArray(); return true;);
1381
1382 QMETATYPE_CONVERTER(QString, QUuid, result = source.toString(); return true;);
1383 QMETATYPE_CONVERTER(QUuid, QString, result = QUuid(source); return true;);
1384 QMETATYPE_CONVERTER(QByteArray, QUuid, result = source.toByteArray(); return true;);
1385 QMETATYPE_CONVERTER(QUuid, QByteArray, result = QUuid(source); return true;);
1386
1387 QMETATYPE_CONVERTER(QSize, QSizeF, result = source.toSize(); return true;);
1388 QMETATYPE_CONVERTER_ASSIGN(QSizeF, QSize);
1389 QMETATYPE_CONVERTER(QLine, QLineF, result = source.toLine(); return true;);
1390 QMETATYPE_CONVERTER_ASSIGN(QLineF, QLine);
1391 QMETATYPE_CONVERTER(QRect, QRectF, result = source.toRect(); return true;);
1392 QMETATYPE_CONVERTER_ASSIGN(QRectF, QRect);
1393 QMETATYPE_CONVERTER(QPoint, QPointF, result = source.toPoint(); return true;);
1395
1396 QMETATYPE_CONVERTER(QStringList, QString, result = QStringList() << source; return true;);
1397
1398 QMETATYPE_CONVERTER(QByteArrayList, QVariantList,
1399 result.reserve(source.size());
1400 for (const auto &v: source)
1401 result.append(v.toByteArray());
1402 return true;
1403 );
1404 QMETATYPE_CONVERTER(QVariantList, QByteArrayList,
1405 result.reserve(source.size());
1406 for (const auto &v: source)
1407 result.append(QVariant(v));
1408 return true;
1409 );
1410
1411 QMETATYPE_CONVERTER(QStringList, QVariantList,
1412 result.reserve(source.size());
1413 for (const auto &v: source)
1414 result.append(v.toString());
1415 return true;
1416 );
1417 QMETATYPE_CONVERTER(QVariantList, QStringList,
1418 result.reserve(source.size());
1419 for (const auto &v: source)
1420 result.append(QVariant(v));
1421 return true;
1422 );
1423
1424 QMETATYPE_CONVERTER(QVariantHash, QVariantMap,
1425 result.reserve(source.size());
1426 for (auto it = source.begin(); it != source.end(); ++it)
1427 result.insert(it.key(), it.value());
1428 return true;
1429 );
1430 QMETATYPE_CONVERTER(QVariantMap, QVariantHash,
1431 for (auto it = source.begin(); it != source.end(); ++it)
1432 result.insert(it.key(), it.value());
1433 return true;
1434 );
1435 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QString);
1436 QMETATYPE_CONVERTER(QString, QCborValue,
1437 if (source.isContainer() || source.isTag())
1438 return false;
1439 result = source.toVariant().toString();
1440 return true;
1441 );
1443 QMETATYPE_CONVERTER(QByteArray, QCborValue,
1444 if (source.isByteArray()) {
1445 result = source.toByteArray();
1446 return true;
1447 }
1448 return false;
1449 );
1450 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QUuid);
1451 QMETATYPE_CONVERTER(QUuid, QCborValue,
1452 if (!source.isUuid())
1453 return false;
1454 result = source.toUuid();
1455 return true;
1456 );
1457 QMETATYPE_CONVERTER(QCborValue, QVariantList, result = QCborArray::fromVariantList(source); return true;);
1459 if (!source.isArray())
1460 return false;
1461 result = source.toArray().toVariantList();
1462 return true;
1463 );
1464 QMETATYPE_CONVERTER(QCborValue, QVariantMap, result = QCborMap::fromVariantMap(source); return true;);
1465 QMETATYPE_CONVERTER(QVariantMap, QCborValue,
1466 if (!source.isMap())
1467 return false;
1468 result = source.toMap().toVariantMap();
1469 return true;
1470 );
1471 QMETATYPE_CONVERTER(QCborValue, QVariantHash, result = QCborMap::fromVariantHash(source); return true;);
1472 QMETATYPE_CONVERTER(QVariantHash, QCborValue,
1473 if (!source.isMap())
1474 return false;
1475 result = source.toMap().toVariantHash();
1476 return true;
1477 );
1478#if QT_CONFIG(regularexpression)
1479 QMETATYPE_CONVERTER(QCborValue, QRegularExpression, result = QCborValue(source); return true;);
1480 QMETATYPE_CONVERTER(QRegularExpression, QCborValue,
1481 if (!source.isRegularExpression())
1482 return false;
1483 result = source.toRegularExpression();
1484 return true;
1485 );
1486#endif
1487
1488 QMETATYPE_CONVERTER(QCborValue, Nullptr,
1489 Q_UNUSED(source);
1490 result = QCborValue(QCborValue::Null);
1491 return true;
1492 );
1493 QMETATYPE_CONVERTER(Nullptr, QCborValue,
1494 result = nullptr;
1495 return source.isNull();
1496 );
1497 QMETATYPE_CONVERTER_ASSIGN(QCborValue, Bool);
1498 QMETATYPE_CONVERTER_ASSIGN(QCborValue, Int);
1499 QMETATYPE_CONVERTER_ASSIGN(QCborValue, UInt);
1500 QMETATYPE_CONVERTER(QCborValue, ULong, result = qlonglong(source); return true;);
1501 QMETATYPE_CONVERTER(QCborValue, Long, result = qlonglong(source); return true;);
1502 QMETATYPE_CONVERTER_ASSIGN(QCborValue, LongLong);
1503 QMETATYPE_CONVERTER(QCborValue, ULongLong, result = qlonglong(source); return true;);
1504 QMETATYPE_CONVERTER_ASSIGN(QCborValue, UShort);
1505 QMETATYPE_CONVERTER_ASSIGN(QCborValue, UChar);
1506 QMETATYPE_CONVERTER_ASSIGN(QCborValue, Char);
1507 QMETATYPE_CONVERTER_ASSIGN(QCborValue, SChar);
1508 QMETATYPE_CONVERTER_ASSIGN(QCborValue, Short);
1509 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QCborValue, Double);
1510 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QCborValue, Float);
1511 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QCborValue, Float16);
1512 QMETATYPE_CONVERTER(QCborValue, QStringList,
1513 result = QCborArray::fromStringList(source);
1514 return true;
1515 );
1516#if QT_CONFIG(datestring)
1517 QMETATYPE_CONVERTER(QCborValue, QDate,
1518 result = QCborValue(source.startOfDay());
1519 return true;
1520 );
1521#endif
1522 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QUrl);
1523 QMETATYPE_CONVERTER(QCborValue, QJsonValue,
1524 result = QCborValue::fromJsonValue(source);
1525 return true;
1526 );
1527 QMETATYPE_CONVERTER(QCborValue, QJsonObject,
1528 result = QCborMap::fromJsonObject(source);
1529 return true;
1530 );
1531 QMETATYPE_CONVERTER(QCborValue, QJsonArray,
1532 result = QCborArray::fromJsonArray(source);
1533 return true;
1534 );
1535 QMETATYPE_CONVERTER(QCborValue, QJsonDocument,
1536 QJsonDocument doc = source;
1537 if (doc.isArray())
1538 result = QCborArray::fromJsonArray(doc.array());
1539 else
1540 result = QCborMap::fromJsonObject(doc.object());
1541 return true;
1542 );
1543 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QCborMap);
1544 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QCborArray);
1545
1546#if QT_CONFIG(datestring)
1547 QMETATYPE_CONVERTER_ASSIGN(QCborValue, QDateTime);
1548 QMETATYPE_CONVERTER(QDateTime, QCborValue,
1549 if (source.isDateTime()) {
1550 result = source.toDateTime();
1551 return true;
1552 }
1553 return false;
1554 );
1555#endif
1556
1559 if (source.isSimpleType()) {
1560 result = source.toSimpleType();
1561 return true;
1562 }
1563 return false;
1564 );
1565
1566 QMETATYPE_CONVERTER(QCborArray, QVariantList, result = QCborArray::fromVariantList(source); return true;);
1567 QMETATYPE_CONVERTER(QVariantList, QCborArray, result = source.toVariantList(); return true;);
1568 QMETATYPE_CONVERTER(QCborArray, QStringList, result = QCborArray::fromStringList(source); return true;);
1569 QMETATYPE_CONVERTER(QCborMap, QVariantMap, result = QCborMap::fromVariantMap(source); return true;);
1570 QMETATYPE_CONVERTER(QVariantMap, QCborMap, result = source.toVariantMap(); return true;);
1571 QMETATYPE_CONVERTER(QCborMap, QVariantHash, result = QCborMap::fromVariantHash(source); return true;);
1572 QMETATYPE_CONVERTER(QVariantHash, QCborMap, result = source.toVariantHash(); return true;);
1573
1574 QMETATYPE_CONVERTER(QCborArray, QCborValue,
1575 if (!source.isArray())
1576 return false;
1577 result = source.toArray();
1578 return true;
1579 );
1580 QMETATYPE_CONVERTER(QCborArray, QJsonDocument,
1581 if (!source.isArray())
1582 return false;
1583 result = QCborArray::fromJsonArray(source.array());
1584 return true;
1585 );
1586 QMETATYPE_CONVERTER(QCborArray, QJsonValue,
1587 if (!source.isArray())
1588 return false;
1589 result = QCborArray::fromJsonArray(source.toArray());
1590 return true;
1591 );
1592 QMETATYPE_CONVERTER(QCborArray, QJsonArray,
1593 result = QCborArray::fromJsonArray(source);
1594 return true;
1595 );
1596 QMETATYPE_CONVERTER(QCborMap, QCborValue,
1597 if (!source.isMap())
1598 return false;
1599 result = source.toMap();
1600 return true;
1601 );
1602 QMETATYPE_CONVERTER(QCborMap, QJsonDocument,
1603 if (source.isArray())
1604 return false;
1605 result = QCborMap::fromJsonObject(source.object());
1606 return true;
1607 );
1608 QMETATYPE_CONVERTER(QCborMap, QJsonValue,
1609 if (!source.isObject())
1610 return false;
1611 result = QCborMap::fromJsonObject(source.toObject());
1612 return true;
1613 );
1614 QMETATYPE_CONVERTER(QCborMap, QJsonObject,
1615 result = QCborMap::fromJsonObject(source);
1616 return true;
1617 );
1618
1619
1621 if (!source.isArray())
1622 return false;
1623 result = source.toArray().toVariantList();
1624 return true;
1625 );
1626 QMETATYPE_CONVERTER(QVariantList, QJsonArray, result = source.toVariantList(); return true;);
1627 QMETATYPE_CONVERTER(QVariantMap, QJsonValue,
1628 if (!source.isObject())
1629 return false;
1630 result = source.toObject().toVariantMap();
1631 return true;
1632 );
1633 QMETATYPE_CONVERTER(QVariantMap, QJsonObject, result = source.toVariantMap(); return true;);
1634 QMETATYPE_CONVERTER(QVariantHash, QJsonValue,
1635 if (!source.isObject())
1636 return false;
1637 result = source.toObject().toVariantHash();
1638 return true;
1639 );
1640 QMETATYPE_CONVERTER(QVariantHash, QJsonObject, result = source.toVariantHash(); return true;);
1641
1642
1643 QMETATYPE_CONVERTER(QJsonArray, QStringList, result = QJsonArray::fromStringList(source); return true;);
1644 QMETATYPE_CONVERTER(QJsonArray, QVariantList, result = QJsonArray::fromVariantList(source); return true;);
1645 QMETATYPE_CONVERTER(QJsonArray, QJsonValue,
1646 if (!source.isArray())
1647 return false;
1648 result = source.toArray();
1649 return true;
1650 );
1651 QMETATYPE_CONVERTER(QJsonArray, QJsonDocument,
1652 if (!source.isArray())
1653 return false;
1654 result = source.array();
1655 return true;
1656 );
1657 QMETATYPE_CONVERTER(QJsonArray, QCborValue,
1658 if (!source.isArray())
1659 return false;
1660 result = source.toArray().toJsonArray();
1661 return true;
1662 );
1663 QMETATYPE_CONVERTER(QJsonArray, QCborArray, result = source.toJsonArray(); return true;);
1664 QMETATYPE_CONVERTER(QJsonObject, QVariantMap, result = QJsonObject::fromVariantMap(source); return true;);
1665 QMETATYPE_CONVERTER(QJsonObject, QVariantHash, result = QJsonObject::fromVariantHash(source); return true;);
1666 QMETATYPE_CONVERTER(QJsonObject, QJsonValue,
1667 if (!source.isObject())
1668 return false;
1669 result = source.toObject();
1670 return true;
1671 );
1672 QMETATYPE_CONVERTER(QJsonObject, QJsonDocument,
1673 if (source.isArray())
1674 return false;
1675 result = source.object();
1676 return true;
1677 );
1678 QMETATYPE_CONVERTER(QJsonObject, QCborValue,
1679 if (!source.isMap())
1680 return false;
1681 result = source.toMap().toJsonObject();
1682 return true;
1683 );
1684 QMETATYPE_CONVERTER(QJsonObject, QCborMap, result = source.toJsonObject(); return true; );
1685
1686 QMETATYPE_CONVERTER(QJsonValue, Nullptr,
1687 Q_UNUSED(source);
1688 result = QJsonValue(QJsonValue::Null);
1689 return true;
1690 );
1691 QMETATYPE_CONVERTER(Nullptr, QJsonValue,
1692 result = nullptr;
1693 return source.isNull();
1694 );
1695 QMETATYPE_CONVERTER(QJsonValue, Bool,
1696 result = QJsonValue(source);
1697 return true;);
1698 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Int);
1699 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, UInt);
1700 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Double);
1701 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Float);
1702 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Float16);
1703 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, ULong);
1704 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Long);
1705 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, LongLong);
1706 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, ULongLong);
1707 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, UShort);
1708 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, UChar);
1709 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Char);
1710 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, SChar);
1711 QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Short);
1712 QMETATYPE_CONVERTER_ASSIGN(QJsonValue, QString);
1713 QMETATYPE_CONVERTER(QJsonValue, QStringList,
1714 result = QJsonValue(QJsonArray::fromStringList(source));
1715 return true;
1716 );
1718 result = QJsonValue(QJsonArray::fromVariantList(source));
1719 return true;
1720 );
1721 QMETATYPE_CONVERTER(QJsonValue, QVariantMap,
1722 result = QJsonValue(QJsonObject::fromVariantMap(source));
1723 return true;
1724 );
1725 QMETATYPE_CONVERTER(QJsonValue, QVariantHash,
1726 result = QJsonValue(QJsonObject::fromVariantHash(source));
1727 return true;
1728 );
1729 QMETATYPE_CONVERTER(QJsonValue, QJsonObject,
1730 result = source;
1731 return true;
1732 );
1733 QMETATYPE_CONVERTER(QJsonValue, QJsonArray,
1734 result = source;
1735 return true;
1736 );
1737 QMETATYPE_CONVERTER(QJsonValue, QJsonDocument,
1738 QJsonDocument doc = source;
1739 result = doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object());
1740 return true;
1741 );
1742 QMETATYPE_CONVERTER(QJsonValue, QCborValue,
1743 result = source.toJsonValue();
1744 return true;
1745 );
1746 QMETATYPE_CONVERTER(QJsonValue, QCborMap,
1747 result = source.toJsonObject();
1748 return true;
1749 );
1750 QMETATYPE_CONVERTER(QJsonValue, QCborArray,
1751 result = source.toJsonArray();
1752 return true;
1753 );
1754
1755 QMETATYPE_CONVERTER(QDate, QDateTime, result = source.date(); return true;);
1756 QMETATYPE_CONVERTER(QTime, QDateTime, result = source.time(); return true;);
1757 QMETATYPE_CONVERTER(QDateTime, QDate, result = source.startOfDay(); return true;);
1758#if QT_CONFIG(datestring)
1759 QMETATYPE_CONVERTER(QDate, QString,
1760 result = QDate::fromString(source, Qt::ISODate);
1761 return result.isValid();
1762 );
1763 QMETATYPE_CONVERTER(QTime, QString,
1764 result = QTime::fromString(source, Qt::ISODate);
1765 return result.isValid();
1766 );
1767 QMETATYPE_CONVERTER(QDateTime, QString,
1768 result = QDateTime::fromString(source, Qt::ISODate);
1769 return result.isValid();
1770 );
1771#endif
1772
1773QT_WARNING_POP
1774 }
1775#endif // !QT_BOOTSTRAPPED
1776 return false;
1777 }
1778};
1779} // unnamed namespace
1780
1781Q_CONSTINIT Q_CORE_EXPORT QMetaTypeModuleHelper qMetaTypeGuiHelper = {};
1782Q_CONSTINIT Q_CORE_EXPORT QMetaTypeModuleHelper qMetaTypeWidgetsHelper = {};
1783
1784#ifndef QT_BOOTSTRAPPED
1785static bool tryConvertBuiltinTypes(const void *from, int fromTypeId, void *to, int toTypeId)
1786{
1787 int type = qMax(fromTypeId, toTypeId);
1788 if (type <= QMetaType::LastCoreType)
1789 return QCoreVariantHelper::convert(from, fromTypeId, to, toTypeId);
1790 if (type >= QMetaType::FirstGuiType && type <= QMetaType::LastGuiType)
1791 return qMetaTypeGuiHelper.convert(from, fromTypeId, to, toTypeId);
1792 else if (type >= QMetaType::FirstWidgetsType && type <= QMetaType::LastWidgetsType)
1793 return qMetaTypeWidgetsHelper.convert(from, fromTypeId, to, toTypeId);
1794 return false;
1795}
1796
1797template<typename T, typename Key>
1799{
1800public:
1802 {
1803 const QWriteLocker locker(&lock);
1804 map.clear();
1805 }
1806
1807 bool contains(Key k) const
1808 {
1809 const QReadLocker locker(&lock);
1810 return map.contains(k);
1811 }
1812
1813 bool insertIfNotContains(Key k, const T &f)
1814 {
1815 const QWriteLocker locker(&lock);
1816 auto r = map.tryEmplace(k, f);
1817 return r.inserted;
1818 }
1819
1820 const T *function(Key k) const
1821 {
1822 const QReadLocker locker(&lock);
1823 auto it = map.find(k);
1824 return it == map.end() ? nullptr : std::addressof(*it);
1825 }
1826
1827 void remove(int from, int to)
1828 {
1829 const Key k(from, to);
1830 const QWriteLocker locker(&lock);
1831 map.remove(k);
1832 }
1833private:
1834 mutable QReadWriteLock lock;
1835 QHash<Key, T> map;
1836};
1837
1838using QMetaTypeConverterRegistry
1839 = QMetaTypeFunctionRegistry<QMetaType::ConverterFunction, std::pair<int,int>>;
1840
1841Q_GLOBAL_STATIC(QMetaTypeConverterRegistry, customTypesConversionRegistry)
1843using QMetaTypeMutableViewRegistry
1844 = QMetaTypeFunctionRegistry<QMetaType::MutableViewFunction, std::pair<int,int>>;
1845Q_GLOBAL_STATIC(QMetaTypeMutableViewRegistry, customTypesMutableViewRegistry)
1846
1847/*!
1848 \fn template<typename From, typename To> bool QMetaType::registerConverter()
1849 \since 5.2
1850 Registers the possibility of an implicit conversion from type From to type To in the meta
1851 type system. Returns \c true if the registration succeeded, otherwise false.
1852
1853 \snippet qmetatype/registerConverters.cpp implicit
1854*/
1855
1856/*!
1857 \fn template<typename From, typename To> static bool QMetaType::registerConverter(To(From::*function)() const)
1858 \since 5.2
1859 \overload
1860 Registers a method \a function like To From::function() const as converter from type From
1861 to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
1862
1863 \snippet qmetatype/registerConverters.cpp member
1864*/
1865
1866/*!
1867 \fn template<typename From, typename To> static bool QMetaType::registerConverter(To(From::*function)(bool*) const)
1868 \since 5.2
1869 \overload
1870 Registers a method \a function like To From::function(bool *ok) const 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 The \c ok pointer can be used by the function to indicate whether the conversion succeeded.
1874 \snippet qmetatype/registerConverters.cpp memberOk
1875
1876*/
1877
1878/*!
1879 \fn template<typename From, typename To, typename UnaryFunction> static bool QMetaType::registerConverter(UnaryFunction function)
1880 \since 5.2
1881 \overload
1882 Registers a unary function object \a function as converter from type From
1883 to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
1884
1885 \a function must take an instance of type \c From and return an instance of \c To. It can be a function
1886 pointer, a lambda or a functor object. Since Qt 6.5, the \a function can also return an instance of
1887 \c std::optional<To> to be able to indicate failed conversions.
1888 \snippet qmetatype/registerConverters.cpp unaryfunc
1889*/
1890
1891/*!
1892 Registers function \a f as converter function from type id \a from to \a to.
1893 If there's already a conversion registered, this does nothing but deleting \a f.
1894 Returns \c true if the registration succeeded, otherwise false.
1895 \since 5.2
1896 \internal
1897*/
1898bool QMetaType::registerConverterFunction(const ConverterFunction &f, QMetaType from, QMetaType to)
1899{
1900 if (!customTypesConversionRegistry()->insertIfNotContains({from.id(), to.id()}, f)) {
1901 qWarning("Type conversion already registered from type %s to type %s",
1902 from.name(), to.name());
1903 return false;
1904 }
1905 return true;
1906}
1907
1908/*!
1909 \fn template<typename From, typename To> static bool QMetaType::registerMutableView(To(From::*function)())
1910 \since 6.0
1911 \overload
1912 Registers a method \a function like \c {To From::function()} as mutable view of type \c {To} on
1913 type \c {From} in the meta type system. Returns \c true if the registration succeeded, otherwise
1914 \c false.
1915*/
1916
1917/*!
1918 \fn template<typename From, typename To, typename UnaryFunction> static bool QMetaType::registerMutableView(UnaryFunction function)
1919 \since 6.0
1920 \overload
1921 Registers a unary function object \a function as mutable view of type To on type From
1922 in the meta type system. Returns \c true if the registration succeeded, otherwise \c false.
1923*/
1924
1925/*!
1926 Registers function \a f as mutable view of type id \a to on type id \a from.
1927 Returns \c true if the registration succeeded, otherwise \c false.
1928 \since 6.0
1929 \internal
1930*/
1931bool QMetaType::registerMutableViewFunction(const MutableViewFunction &f, QMetaType from, QMetaType to)
1932{
1933 if (!customTypesMutableViewRegistry()->insertIfNotContains({from.id(), to.id()}, f)) {
1934 qWarning("Mutable view on type already registered from type %s to type %s",
1935 from.name(), to.name());
1936 return false;
1937 }
1938 return true;
1939}
1940
1941/*!
1942 \internal
1943 */
1944void QMetaType::unregisterMutableViewFunction(QMetaType from, QMetaType to)
1945{
1946 if (customTypesMutableViewRegistry.isDestroyed())
1947 return;
1948 customTypesMutableViewRegistry()->remove(from.id(), to.id());
1949}
1950
1951/*!
1952 \internal
1953
1954 Invoked automatically when a converter function object is destroyed.
1955 */
1956void QMetaType::unregisterConverterFunction(QMetaType from, QMetaType to)
1957{
1958 if (customTypesConversionRegistry.isDestroyed())
1959 return;
1960 customTypesConversionRegistry()->remove(from.id(), to.id());
1961}
1962#endif // !QT_BOOTSTRAPPED
1963
1964#ifndef QT_NO_DEBUG_STREAM
1965
1966/*!
1967 \fn QDebug QMetaType::operator<<(QDebug d, QMetaType m)
1968 \since 6.5
1969 Writes the QMetaType \a m to the stream \a d, and returns the stream.
1970*/
1971QDebug operator<<(QDebug d, QMetaType m)
1972{
1973 const QDebugStateSaver saver(d);
1974 return d.nospace() << "QMetaType(" << m.name() << ")";
1975}
1976
1977/*!
1978 Streams the object at \a rhs to the debug stream \a dbg. Returns \c true
1979 on success, otherwise false.
1980 \since 5.2
1981*/
1982bool QMetaType::debugStream(QDebug& dbg, const void *rhs)
1983{
1984 if (d_ptr && d_ptr->flags & QMetaType::IsPointer) {
1985 dbg << *reinterpret_cast<const void * const *>(rhs);
1986 return true;
1987 }
1988 if (d_ptr && d_ptr->debugStream) {
1989 d_ptr->debugStream(d_ptr, dbg, rhs);
1990 return true;
1991 }
1992 return false;
1993}
1994
1995/*!
1996 \fn bool QMetaType::debugStream(QDebug& dbg, const void *rhs, int typeId)
1997 \overload
1998 \deprecated
1999*/
2000
2001/*!
2002 \fn template<typename T> bool QMetaType::hasRegisteredDebugStreamOperator()
2003 \deprecated
2004 \since 5.2
2005
2006 Returns \c true, if the meta type system has a registered debug stream operator for type T.
2007 */
2008
2009/*!
2010 \fn bool QMetaType::hasRegisteredDebugStreamOperator(int typeId)
2011 \deprecated Use QMetaType::hasRegisteredDebugStreamOperator() instead.
2012
2013 Returns \c true, if the meta type system has a registered debug stream operator for type
2014 id \a typeId.
2015 \since 5.2
2016*/
2017
2018/*!
2019 \since 6.0
2020
2021 Returns \c true, if the meta type system has a registered debug stream operator for this
2022 meta type.
2023*/
2024bool QMetaType::hasRegisteredDebugStreamOperator() const
2025{
2026 return d_ptr && d_ptr->debugStream != nullptr;
2027}
2028#endif
2029
2030#ifndef QT_NO_QOBJECT
2031/*!
2032 \internal
2033 returns a QMetaEnum for a given meta tape type id if possible
2034*/
2035static QMetaEnum metaEnumFromType(QMetaType t)
2036{
2037 if (t.flags() & QMetaType::IsEnumeration) {
2038 if (const QMetaObject *metaObject = t.metaObject()) {
2039 QByteArrayView qflagsNamePrefix = "QFlags<";
2040 QByteArray enumName = t.name();
2041 if (enumName.endsWith('>') && enumName.startsWith(qflagsNamePrefix)) {
2042 // extract the template argument
2043 enumName.chop(1);
2044 enumName = enumName.sliced(qflagsNamePrefix.size());
2045 }
2046 if (qsizetype lastColon = enumName.lastIndexOf(':'); lastColon != -1)
2047 enumName = enumName.sliced(lastColon + 1);
2048 return metaObject->enumerator(metaObject->indexOfEnumerator(enumName));
2049 }
2050 }
2051 return QMetaEnum();
2052}
2053#endif
2055#ifndef QT_BOOTSTRAPPED
2056static bool convertFromEnum(QMetaType fromType, const void *from, QMetaType toType, void *to)
2057{
2058 qlonglong ll;
2059 if (fromType.flags() & QMetaType::IsUnsignedEnumeration) {
2060 qulonglong ull;
2061 switch (fromType.sizeOf()) {
2062 case 1:
2063 ull = *static_cast<const unsigned char *>(from);
2064 break;
2065 case 2:
2066 ull = *static_cast<const unsigned short *>(from);
2067 break;
2068 case 4:
2069 ull = *static_cast<const unsigned int *>(from);
2070 break;
2071 case 8:
2072 ull = *static_cast<const quint64 *>(from);
2073 break;
2074 default:
2075 Q_UNREACHABLE();
2076 }
2077 if (toType.id() == QMetaType::ULongLong) {
2078 *static_cast<qulonglong *>(to) = ull;
2079 return true;
2080 }
2081 if (toType.id() != QMetaType::QString && toType.id() != QMetaType::QByteArray)
2082 return QMetaType::convert(QMetaType::fromType<qulonglong>(), &ull, toType, to);
2083 ll = qlonglong(ull);
2084 } else {
2085 switch (fromType.sizeOf()) {
2086 case 1:
2087 ll = *static_cast<const signed char *>(from);
2088 break;
2089 case 2:
2090 ll = *static_cast<const short *>(from);
2091 break;
2092 case 4:
2093 ll = *static_cast<const int *>(from);
2094 break;
2095 case 8:
2096 ll = *static_cast<const qint64 *>(from);
2097 break;
2098 default:
2099 Q_UNREACHABLE();
2100 }
2101 if (toType.id() == QMetaType::LongLong) {
2102 *static_cast<qlonglong *>(to) = ll;
2103 return true;
2104 }
2105 if (toType.id() != QMetaType::QString && toType.id() != QMetaType::QByteArray)
2106 return QMetaType::convert(QMetaType::fromType<qlonglong>(), &ll, toType, to);
2107 }
2108#ifndef QT_NO_QOBJECT
2109 QMetaEnum en = metaEnumFromType(fromType);
2110 if (en.isValid()) {
2111 if (en.isFlag()) {
2112 const QByteArray keys = en.valueToKeys(ll);
2113 if (toType.id() == QMetaType::QString)
2114 *static_cast<QString *>(to) = QString::fromUtf8(keys);
2115 else
2116 *static_cast<QByteArray *>(to) = keys;
2117 } else {
2118 const char *key = en.valueToKey(ll);
2119 if (toType.id() == QMetaType::QString)
2120 *static_cast<QString *>(to) = QString::fromUtf8(key);
2121 else
2122 *static_cast<QByteArray *>(to) = key;
2123 }
2124 return true;
2125 }
2126#endif
2127 if (toType.id() == QMetaType::QString || toType.id() == QMetaType::QByteArray)
2128 return QMetaType::convert(QMetaType::fromType<qlonglong>(), &ll, toType, to);
2129 return false;
2131
2132static bool convertToEnum(QMetaType fromType, const void *from, QMetaType toType, void *to)
2133{
2134 int fromTypeId = fromType.id();
2135 qlonglong value = -1;
2136 bool ok = false;
2137#ifndef QT_NO_QOBJECT
2138 if (fromTypeId == QMetaType::QString || fromTypeId == QMetaType::QByteArray) {
2139 QMetaEnum en = metaEnumFromType(toType);
2140 if (en.isValid()) {
2141 QByteArray keys = (fromTypeId == QMetaType::QString)
2142 ? static_cast<const QString *>(from)->toUtf8()
2143 : *static_cast<const QByteArray *>(from);
2144 if (auto v = en.keysToValue64(keys.constData())) {
2145 ok = true;
2146 value = *v;
2147 }
2148 }
2149 }
2150#endif
2151 if (!ok) {
2152 if (fromTypeId == QMetaType::LongLong) {
2153 value = *static_cast<const qlonglong *>(from);
2154 ok = true;
2155 } else {
2156 ok = QMetaType::convert(fromType, from, QMetaType::fromType<qlonglong>(), &value);
2157 }
2158 }
2159
2160 if (!ok)
2161 return false;
2162
2163 switch (toType.sizeOf()) {
2164 case 1:
2165 *static_cast<signed char *>(to) = value;
2166 return true;
2167 case 2:
2168 *static_cast<qint16 *>(to) = value;
2169 return true;
2170 case 4:
2171 *static_cast<qint32 *>(to) = value;
2172 return true;
2173 case 8:
2174 *static_cast<qint64 *>(to) = value;
2175 return true;
2176 default:
2177 Q_UNREACHABLE_RETURN(false);
2178 }
2179}
2181template<typename Iterable>
2182bool convertIterableToVariantList(QMetaType fromType, const void *from, void *to)
2183{
2184 Iterable list;
2185 if (!QMetaType::convert(fromType, from, QMetaType::fromType<Iterable>(), &list))
2186 return false;
2187
2188 QVariantList &l = *static_cast<QVariantList *>(to);
2189 l.clear();
2190 if (list.metaContainer().hasSize())
2191 l.reserve(list.size());
2192 auto end = list.end();
2193 for (auto it = list.begin(); it != end; ++it)
2194 l << *it;
2195 return true;
2196}
2198template<typename Iterable>
2199bool convertIterableToVariantMap(QMetaType fromType, const void *from, void *to)
2200{
2201 Iterable map;
2202 if (!QMetaType::convert(fromType, from, QMetaType::fromType<Iterable>(), &map))
2203 return false;
2204
2205 QVariantMap &h = *static_cast<QVariantMap *>(to);
2206 h.clear();
2207 auto end = map.end();
2208 for (auto it = map.begin(); it != end; ++it)
2209 h.insert(it.key().toString(), it.value());
2210 return true;
2211}
2213template<typename Iterable>
2214bool convertIterableToVariantHash(QMetaType fromType, const void *from, void *to)
2215{
2216 Iterable map;
2217 if (!QMetaType::convert(fromType, from, QMetaType::fromType<Iterable>(), &map))
2218 return false;
2219
2220 QVariantHash &h = *static_cast<QVariantHash *>(to);
2221 h.clear();
2222 h.reserve(map.size());
2223 auto end = map.end();
2224 for (auto it = map.begin(); it != end; ++it)
2225 h.insert(it.key().toString(), it.value());
2226 return true;
2228
2229static bool convertIterableToVariantPair(QMetaType fromType, const void *from, void *to)
2230{
2231 const int targetId = qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
2232 const auto f = customTypesConversionRegistry()->function({fromType.id(), targetId});
2233
2234 if (!f)
2235 return false;
2236
2238 (*f)(from, &pi);
2239
2240 QVariant v1(pi._metaType_first);
2241 void *dataPtr;
2242 if (pi._metaType_first == QMetaType::fromType<QVariant>())
2243 dataPtr = &v1;
2244 else
2245 dataPtr = v1.data();
2246 pi.first(dataPtr);
2247
2248 QVariant v2(pi._metaType_second);
2249 if (pi._metaType_second == QMetaType::fromType<QVariant>())
2250 dataPtr = &v2;
2251 else
2252 dataPtr = v2.data();
2253 pi.second(dataPtr);
2254
2255 *static_cast<QVariantPair *>(to) = QVariantPair(v1, v2);
2256 return true;
2257}
2259template<typename Iterable>
2260static bool convertToSequentialIterable(QMetaType fromType, const void *from, void *to)
2261{
2262 using namespace QtMetaTypePrivate;
2263 const int fromTypeId = fromType.id();
2264
2265 Iterable &i = *static_cast<Iterable *>(to);
2266 switch (fromTypeId) {
2267 case QMetaType::QVariantList:
2268 i = Iterable(reinterpret_cast<const QVariantList *>(from));
2269 return true;
2270 case QMetaType::QStringList:
2271 i = Iterable(reinterpret_cast<const QStringList *>(from));
2272 return true;
2273 case QMetaType::QByteArrayList:
2274 i = Iterable(reinterpret_cast<const QByteArrayList *>(from));
2275 return true;
2276 case QMetaType::QString:
2277 i = Iterable(reinterpret_cast<const QString *>(from));
2278 return true;
2279 case QMetaType::QByteArray:
2280 i = Iterable(reinterpret_cast<const QByteArray *>(from));
2281 return true;
2282 default: {
2283 QIterable<QMetaSequence> j(QMetaSequence(), nullptr);
2284 if (QMetaType::convert(
2285 fromType, from, QMetaType::fromType<QIterable<QMetaSequence>>(), &j)) {
2286 i = std::move(j);
2287 return true;
2288 }
2289 }
2290 }
2291
2292 return false;
2294
2295static bool canConvertToSequentialIterable(QMetaType fromType)
2296{
2297 switch (fromType.id()) {
2298 case QMetaType::QVariantList:
2299 case QMetaType::QStringList:
2300 case QMetaType::QByteArrayList:
2301 case QMetaType::QString:
2302 case QMetaType::QByteArray:
2303 return true;
2304 default:
2305 return QMetaType::canConvert(fromType, QMetaType::fromType<QIterable<QMetaSequence>>());
2306 }
2308
2309static bool canImplicitlyViewAsSequentialIterable(QMetaType fromType)
2310{
2311 switch (fromType.id()) {
2312 case QMetaType::QVariantList:
2313 case QMetaType::QStringList:
2314 case QMetaType::QByteArrayList:
2315 case QMetaType::QString:
2316 case QMetaType::QByteArray:
2317 return true;
2318 default:
2319 return QMetaType::canView(
2320 fromType, QMetaType::fromType<QIterable<QMetaSequence>>());
2321 }
2322}
2324template<typename Iterable>
2325static bool viewAsSequentialIterable(QMetaType fromType, void *from, void *to)
2326{
2327 using namespace QtMetaTypePrivate;
2328 const int fromTypeId = fromType.id();
2329
2330 Iterable &i = *static_cast<Iterable *>(to);
2331 switch (fromTypeId) {
2332 case QMetaType::QVariantList:
2333 i = Iterable(reinterpret_cast<QVariantList *>(from));
2334 return true;
2335 case QMetaType::QStringList:
2336 i = Iterable(reinterpret_cast<QStringList *>(from));
2337 return true;
2338 case QMetaType::QByteArrayList:
2339 i = Iterable(reinterpret_cast<QByteArrayList *>(from));
2340 return true;
2341 case QMetaType::QString:
2342 i = Iterable(reinterpret_cast<QString *>(from));
2343 return true;
2344 case QMetaType::QByteArray:
2345 i = Iterable(reinterpret_cast<QByteArray *>(from));
2346 return true;
2347 default: {
2348 QIterable<QMetaSequence> j(QMetaSequence(), nullptr);
2349 if (QMetaType::view(
2350 fromType, from, QMetaType::fromType<QIterable<QMetaSequence>>(), &j)) {
2351 i = std::move(j);
2352 return true;
2353 }
2354 }
2355 }
2356
2357 return false;
2358}
2360template<typename Iterable>
2361static bool convertToAssociativeIterable(QMetaType fromType, const void *from, void *to)
2362{
2363 using namespace QtMetaTypePrivate;
2364
2365 Iterable &i = *static_cast<Iterable *>(to);
2366 if (fromType.id() == QMetaType::QVariantMap) {
2367 i = Iterable(reinterpret_cast<const QVariantMap *>(from));
2368 return true;
2369 }
2370 if (fromType.id() == QMetaType::QVariantHash) {
2371 i = Iterable(reinterpret_cast<const QVariantHash *>(from));
2372 return true;
2373 }
2374
2375 QIterable<QMetaAssociation> j(QMetaAssociation(), nullptr);
2376 if (QMetaType::convert(
2377 fromType, from, QMetaType::fromType<QIterable<QMetaAssociation>>(), &j)) {
2378 i = std::move(j);
2379 return true;
2380 }
2381
2382 return false;
2384
2385static bool canConvertMetaObject(QMetaType fromType, QMetaType toType)
2386{
2387 if ((fromType.flags() & QMetaType::IsPointer) != (toType.flags() & QMetaType::IsPointer))
2388 return false; // Can not convert between pointer and value
2389
2390 const QMetaObject *f = fromType.metaObject();
2391 const QMetaObject *t = toType.metaObject();
2392 if (f && t) {
2393 return f->inherits(t) || (t->inherits(f));
2394 }
2395 return false;
2397
2398static bool canConvertToAssociativeIterable(QMetaType fromType)
2399{
2400 switch (fromType.id()) {
2401 case QMetaType::QVariantMap:
2402 case QMetaType::QVariantHash:
2403 return true;
2404 default:
2405 return QMetaType::canConvert(fromType, QMetaType::fromType<QIterable<QMetaAssociation>>());
2406 }
2408
2409static bool canImplicitlyViewAsAssociativeIterable(QMetaType fromType)
2410{
2411 switch (fromType.id()) {
2412 case QMetaType::QVariantMap:
2413 case QMetaType::QVariantHash:
2414 return true;
2415 default:
2416 return QMetaType::canView(
2417 fromType, QMetaType::fromType<QIterable<QMetaAssociation>>());
2418 }
2419}
2421template<typename Iterable>
2422static bool viewAsAssociativeIterable(QMetaType fromType, void *from, void *to)
2423{
2424 using namespace QtMetaTypePrivate;
2425 int fromTypeId = fromType.id();
2426
2427 Iterable &i = *static_cast<Iterable *>(to);
2428 if (fromTypeId == QMetaType::QVariantMap) {
2429 i = Iterable(reinterpret_cast<QVariantMap *>(from));
2430 return true;
2431 }
2432 if (fromTypeId == QMetaType::QVariantHash) {
2433 i = Iterable(reinterpret_cast<QVariantHash *>(from));
2434 return true;
2435 }
2436
2437 QIterable<QMetaAssociation> j(QMetaAssociation(), nullptr);
2438 if (QMetaType::view(
2439 fromType, from, QMetaType::fromType<QIterable<QMetaAssociation>>(), &j)) {
2440 i = std::move(j);
2441 return true;
2442 }
2443
2444 return false;
2446
2447static bool convertMetaObject(QMetaType fromType, const void *from, QMetaType toType, void *to)
2448{
2449 // handle QObject conversion
2450 if ((fromType.flags() & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
2451 QObject *fromObject = *static_cast<QObject * const *>(from);
2452 // use dynamic metatype of from if possible
2453 if (fromObject && fromObject->metaObject()->inherits(toType.metaObject())) {
2454 *static_cast<QObject **>(to) = toType.metaObject()->cast(fromObject);
2455 return true;
2456 } else if (!fromObject && fromType.metaObject()) {
2457 // if fromObject is null, use static fromType to check if conversion works
2458 *static_cast<void **>(to) = nullptr;
2459 return fromType.metaObject()->inherits(toType.metaObject());
2460 }
2461 } else if ((fromType.flags() & QMetaType::IsPointer) == (toType.flags() & QMetaType::IsPointer)) {
2462 // fromType and toType are of same 'pointedness'
2463 const QMetaObject *f = fromType.metaObject();
2464 const QMetaObject *t = toType.metaObject();
2465 if (f && t && f->inherits(t)) {
2466 toType.destruct(to);
2467 toType.construct(to, from);
2468 return true;
2469 }
2470 }
2471 return false;
2472}
2473
2474/*!
2475 \fn bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId)
2476 \deprecated
2477
2478 Converts the object at \a from from \a fromTypeId to the preallocated space at \a to
2479 typed \a toTypeId. Returns \c true, if the conversion succeeded, otherwise false.
2480
2481 Both \a from and \a to have to be valid pointers.
2482
2483 \since 5.2
2484*/
2485
2486/*!
2487 Converts the object at \a from from \a fromType to the preallocated space at \a to
2488 typed \a toType. Returns \c true, if the conversion succeeded, otherwise false.
2489
2490 Both \a from and \a to have to be valid pointers.
2491
2492 \since 5.2
2493*/
2494bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType, void *to)
2495{
2496 if (!fromType.isValid() || !toType.isValid())
2497 return false;
2498
2499 if (fromType == toType) {
2500 // just make a copy
2501 fromType.destruct(to);
2502 fromType.construct(to, from);
2503 return true;
2504 }
2505
2506 int fromTypeId = fromType.id();
2507 int toTypeId = toType.id();
2508
2509 if (tryConvertBuiltinTypes(from, fromTypeId, to, toTypeId))
2510 return true;
2511 const auto f = customTypesConversionRegistry()->function({fromTypeId, toTypeId});
2512 if (f)
2513 return (*f)(from, to);
2514
2515 if (fromType.flags() & QMetaType::IsEnumeration)
2516 return convertFromEnum(fromType, from, toType, to);
2517 if (toType.flags() & QMetaType::IsEnumeration)
2518 return convertToEnum(fromType, from, toType, to);
2519 if (toTypeId == Nullptr) {
2520 *static_cast<std::nullptr_t *>(to) = nullptr;
2521 if (fromType.flags() & QMetaType::IsPointer) {
2522 if (*static_cast<const void * const *>(from) == nullptr)
2523 return true;
2524 }
2525 }
2526
2527 if (toTypeId == QVariantPair && convertIterableToVariantPair(fromType, from, to))
2528 return true;
2529
2530 // handle iterables
2531 if (toTypeId == QVariantList
2532 && convertIterableToVariantList<QMetaSequence::Iterable>(fromType, from, to)) {
2533 return true;
2534 }
2535
2536 if (toTypeId == QVariantMap
2537 && convertIterableToVariantMap<QMetaAssociation::Iterable>(fromType, from, to)) {
2538 return true;
2539 }
2540
2541 if (toTypeId == QVariantHash
2542 && convertIterableToVariantHash<QMetaAssociation::Iterable>(fromType, from, to)) {
2543 return true;
2544 }
2545
2546 if (toTypeId == qMetaTypeId<QMetaSequence::Iterable>())
2547 return convertToSequentialIterable<QMetaSequence::Iterable>(fromType, from, to);
2548
2549 if (toTypeId == qMetaTypeId<QMetaAssociation::Iterable>())
2550 return convertToAssociativeIterable<QMetaAssociation::Iterable>(fromType, from, to);
2551
2552#if QT_DEPRECATED_SINCE(6, 15)
2553 QT_WARNING_PUSH
2554 QT_WARNING_DISABLE_DEPRECATED
2555
2556 if (toTypeId == QVariantList
2557 && convertIterableToVariantList<QSequentialIterable>(fromType, from, to)) {
2558 return true;
2559 }
2560
2561 if (toTypeId == QVariantMap
2562 && convertIterableToVariantMap<QAssociativeIterable>(fromType, from, to)) {
2563 return true;
2564 }
2565
2566 if (toTypeId == QVariantHash
2567 && convertIterableToVariantHash<QAssociativeIterable>(fromType, from, to)) {
2568 return true;
2569 }
2570
2571 if (toTypeId == qMetaTypeId<QSequentialIterable>())
2572 return convertToSequentialIterable<QSequentialIterable>(fromType, from, to);
2573
2574 if (toTypeId == qMetaTypeId<QAssociativeIterable>())
2575 return convertToAssociativeIterable<QAssociativeIterable>(fromType, from, to);
2576
2577 QT_WARNING_POP
2578#endif // QT_DEPRECATED_SINCE(6, 15)
2579
2580 return convertMetaObject(fromType, from, toType, to);
2581}
2582
2583/*!
2584 Creates a mutable view on the object at \a from of \a fromType in the preallocated space at
2585 \a to typed \a toType. Returns \c true if the conversion succeeded, otherwise false.
2586 \since 6.0
2587*/
2588bool QMetaType::view(QMetaType fromType, void *from, QMetaType toType, void *to)
2589{
2590 if (!fromType.isValid() || !toType.isValid())
2591 return false;
2592
2593 int fromTypeId = fromType.id();
2594 int toTypeId = toType.id();
2595
2596 const auto f = customTypesMutableViewRegistry()->function({fromTypeId, toTypeId});
2597 if (f)
2598 return (*f)(from, to);
2599
2600 if (toTypeId == qMetaTypeId<QMetaSequence::Iterable>())
2601 return viewAsSequentialIterable<QMetaSequence::Iterable>(fromType, from, to);
2602
2603 if (toTypeId == qMetaTypeId<QMetaAssociation::Iterable>())
2604 return viewAsAssociativeIterable<QMetaAssociation::Iterable>(fromType, from, to);
2605
2606#if QT_DEPRECATED_SINCE(6, 15)
2607 QT_WARNING_PUSH
2608 QT_WARNING_DISABLE_DEPRECATED
2609
2610 if (toTypeId == qMetaTypeId<QSequentialIterable>())
2611 return viewAsSequentialIterable<QSequentialIterable>(fromType, from, to);
2612
2613 if (toTypeId == qMetaTypeId<QAssociativeIterable>())
2614 return viewAsAssociativeIterable<QAssociativeIterable>(fromType, from, to);
2615
2616 QT_WARNING_POP
2617#endif // QT_DEPRECATED_SINCE(6, 15)
2618
2619 return convertMetaObject(fromType, from, toType, to);
2620}
2621
2622/*!
2623 Returns \c true if QMetaType::view can create a mutable view of type \a toType
2624 on type \a fromType.
2625
2626 Converting between pointers of types derived from QObject will return true for this
2627 function if a qobject_cast from the type described by \a fromType to the type described
2628 by \a toType would succeed.
2629
2630 You can create a mutable view of type QMetaSequence::Iterable on any container registered with
2631 Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE().
2632
2633 Similarly you can create a mutable view of type QMetaAssociation::Iterable on any container
2634 registered with Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE().
2635
2636 \sa convert(), QMetaSequence::Iterable, Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(),
2637 QMetaAssociation::Iterable, Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE()
2638*/
2639bool QMetaType::canView(QMetaType fromType, QMetaType toType)
2640{
2641 int fromTypeId = fromType.id();
2642 int toTypeId = toType.id();
2643
2644 if (fromTypeId == UnknownType || toTypeId == UnknownType)
2645 return false;
2646
2647 const auto f = customTypesMutableViewRegistry()->function({fromTypeId, toTypeId});
2648 if (f)
2649 return true;
2650
2651 if (toTypeId == qMetaTypeId<QMetaSequence::Iterable>())
2652 return canImplicitlyViewAsSequentialIterable(fromType);
2653
2654 if (toTypeId == qMetaTypeId<QMetaAssociation::Iterable>())
2655 return canImplicitlyViewAsAssociativeIterable(fromType);
2656
2657#if QT_DEPRECATED_SINCE(6, 15)
2658 QT_WARNING_PUSH
2659 QT_WARNING_DISABLE_DEPRECATED
2660
2661 if (toTypeId == qMetaTypeId<QSequentialIterable>())
2662 return canImplicitlyViewAsSequentialIterable(fromType);
2663
2664 if (toTypeId == qMetaTypeId<QAssociativeIterable>())
2665 return canImplicitlyViewAsAssociativeIterable(fromType);
2666
2667 QT_WARNING_POP
2668#endif // QT_DEPRECATED_SINCE(6, 15)
2669
2670 if (canConvertMetaObject(fromType, toType))
2671 return true;
2672
2673 return false;
2674}
2675
2676/*!
2677 Returns \c true if QMetaType::convert can convert from \a fromType to
2678 \a toType. Note this is mostly about the ability to execute the conversion,
2679 while the actual conversion may fail when attempted (for example,
2680 converting a floating point value to an integer outside of its range).
2681
2682 The registerConverter() function can be used to register additional
2683 conversions, either between a built-in type and a non-built-in one, or
2684 between two non-built-in types. This function will return \c true if the
2685 conversion path is registered.
2686
2687 The following conversions are supported by Qt:
2688
2689 \table
2690 \header \li Type \li Automatically Cast To
2691 \row \li \l QMetaType::Bool \li \l QMetaType::QChar, \l QMetaType::Double,
2692 \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
2693 \l QMetaType::UInt, \l QMetaType::ULongLong
2694 \row \li \l QMetaType::QByteArray \li \l QMetaType::Double,
2695 \l QMetaType::Int, \l QMetaType::LongLong, \l QMetaType::QString,
2696 \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
2697 \row \li \l QMetaType::QChar \li \l QMetaType::Bool, \l QMetaType::Int,
2698 \l QMetaType::UInt, \l QMetaType::LongLong, \l QMetaType::ULongLong
2699 \row \li \l QMetaType::QColor \li \l QMetaType::QString
2700 \row \li \l QMetaType::QDate \li \l QMetaType::QDateTime,
2701 \l QMetaType::QString
2702 \row \li \l QMetaType::QDateTime \li \l QMetaType::QDate,
2703 \l QMetaType::QString, \l QMetaType::QTime
2704 \row \li \l QMetaType::Double \li \l QMetaType::Bool, \l QMetaType::Int,
2705 \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt,
2706 \l QMetaType::ULongLong
2707 \row \li \l QMetaType::QFont \li \l QMetaType::QString
2708 \row \li \l QMetaType::Int \li \l QMetaType::Bool, \l QMetaType::QChar,
2709 \l QMetaType::Double, \l QMetaType::LongLong, \l QMetaType::QString,
2710 \l QMetaType::UInt, \l QMetaType::ULongLong
2711 \row \li \l QMetaType::QKeySequence \li \l QMetaType::Int,
2712 \l QMetaType::QString
2713 \row \li \l QMetaType::QVariantList \li \l QMetaType::QStringList (if the
2714 list's items can be converted to QStrings)
2715 \row \li \l QMetaType::LongLong \li \l QMetaType::Bool,
2716 \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::Double,
2717 \l QMetaType::Int, \l QMetaType::QString, \l QMetaType::UInt,
2718 \l QMetaType::ULongLong
2719 \row \li \l QMetaType::QPoint \li QMetaType::QPointF
2720 \row \li \l QMetaType::QRect \li QMetaType::QRectF
2721 \row \li \l QMetaType::QString \li \l QMetaType::Bool,
2722 \l QMetaType::QByteArray, \l QMetaType::QChar, \l QMetaType::QColor,
2723 \l QMetaType::QDate, \l QMetaType::QDateTime, \l QMetaType::Double,
2724 \l QMetaType::QFont, \l QMetaType::Int, \l QMetaType::QKeySequence,
2725 \l QMetaType::LongLong, \l QMetaType::QStringList, \l QMetaType::QTime,
2726 \l QMetaType::UInt, \l QMetaType::ULongLong, \l QMetaType::QUuid
2727 \row \li \l QMetaType::QStringList \li \l QMetaType::QVariantList,
2728 \l QMetaType::QString (if the list contains exactly one item)
2729 \row \li \l QMetaType::QTime \li \l QMetaType::QString
2730 \row \li \l QMetaType::UInt \li \l QMetaType::Bool, \l QMetaType::QChar,
2731 \l QMetaType::Double, \l QMetaType::Int, \l QMetaType::LongLong,
2732 \l QMetaType::QString, \l QMetaType::ULongLong
2733 \row \li \l QMetaType::ULongLong \li \l QMetaType::Bool,
2734 \l QMetaType::QChar, \l QMetaType::Double, \l QMetaType::Int,
2735 \l QMetaType::LongLong, \l QMetaType::QString, \l QMetaType::UInt
2736 \row \li \l QMetaType::QUuid \li \l QMetaType::QByteArray, \l QMetaType::QString
2737 \endtable
2738
2739 Other supported conversions include between all primitive types (\c int, \c
2740 float, \c bool, etc., including all enums) and between any pointer type and
2741 \c{std::nullptr_t}. Enumerations can also be converted to QString and
2742 QByteArray.
2743
2744 If both \a fromType and \a toType are types deriving from QObject (or
2745 pointers to them), this function will also return \c true if one of the
2746 types is derived from the other. That is, it returns true if
2747 \c{static_cast<>} from the type described by \a fromType to the type
2748 described by \a toType would compile. The convert() function operates like
2749 qobject_cast() and verifies the dynamic type of the object pointed to by
2750 the QVariant.
2751
2752 A cast from a sequential container will also return true for this
2753 function if the \a toType is QVariantList.
2754
2755 Similarly, a cast from an associative container will also return true for this
2756 function the \a toType is QVariantHash or QVariantMap.
2757
2758 \sa convert(), QMetaSequence::Iterable, Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(),
2759 QMetaAssociation::Iterable, Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE()
2760*/
2761bool QMetaType::canConvert(QMetaType fromType, QMetaType toType)
2762{
2763 int fromTypeId = fromType.id();
2764 int toTypeId = toType.id();
2765
2766 if (fromTypeId == UnknownType || toTypeId == UnknownType)
2767 return false;
2768
2769 if (fromTypeId == toTypeId)
2770 return true;
2771
2772 if (tryConvertBuiltinTypes(nullptr, fromTypeId, nullptr, toTypeId))
2773 return true;
2774
2775 const ConverterFunction * const f =
2776 customTypesConversionRegistry()->function(std::make_pair(fromTypeId, toTypeId));
2777 if (f)
2778 return true;
2779
2780 if (toTypeId == qMetaTypeId<QMetaSequence::Iterable>())
2781 return canConvertToSequentialIterable(fromType);
2782
2783 if (toTypeId == qMetaTypeId<QMetaAssociation::Iterable>())
2784 return canConvertToAssociativeIterable(fromType);
2785
2786 if (toTypeId == QVariantList
2787 && canConvert(fromType, QMetaType::fromType<QMetaSequence::Iterable>())) {
2788 return true;
2789 }
2790
2791 if ((toTypeId == QVariantHash || toTypeId == QVariantMap)
2792 && canConvert(fromType, QMetaType::fromType<QMetaAssociation::Iterable>())) {
2793 return true;
2794 }
2795
2796#if QT_DEPRECATED_SINCE(6, 15)
2797 QT_WARNING_PUSH
2798 QT_WARNING_DISABLE_DEPRECATED
2799
2800 if (toTypeId == qMetaTypeId<QSequentialIterable>())
2801 return canConvertToSequentialIterable(fromType);
2802
2803 if (toTypeId == qMetaTypeId<QAssociativeIterable>())
2804 return canConvertToAssociativeIterable(fromType);
2805
2806 if (toTypeId == QVariantList
2807 && canConvert(fromType, QMetaType::fromType<QSequentialIterable>())) {
2808 return true;
2809 }
2810
2811 if ((toTypeId == QVariantHash || toTypeId == QVariantMap)
2812 && canConvert(fromType, QMetaType::fromType<QAssociativeIterable>())) {
2813 return true;
2814 }
2815
2816 QT_WARNING_POP
2817#endif // QT_DEPRECATED_SINCE(6, 15)
2818
2819 if (toTypeId == QVariantPair && hasRegisteredConverterFunction(
2820 fromType, QMetaType::fromType<QtMetaTypePrivate::QPairVariantInterfaceImpl>()))
2821 return true;
2822
2823 if (fromType.flags() & IsEnumeration) {
2824 if (toTypeId == QString || toTypeId == QByteArray)
2825 return true;
2826 return canConvert(QMetaType(LongLong), toType);
2827 }
2828 if (toType.flags() & IsEnumeration) {
2829 if (fromTypeId == QString || fromTypeId == QByteArray)
2830 return true;
2831 return canConvert(fromType, QMetaType(LongLong));
2832 }
2833 if (toTypeId == Nullptr && fromType.flags() & IsPointer)
2834 return true;
2835 if (canConvertMetaObject(fromType, toType))
2836 return true;
2837
2838 return false;
2839}
2840
2841/*!
2842 \fn bool QMetaType::compare(const void *lhs, const void *rhs, int typeId, int* result)
2843 \deprecated Use the non-static compare method instead
2844
2845 Compares the objects at \a lhs and \a rhs. Both objects need to be of type \a typeId.
2846 \a result is set to less than, equal to or greater than zero, if \a lhs is less than, equal to
2847 or greater than \a rhs. Returns \c true, if the comparison succeeded, otherwise \c false.
2848*/
2849
2850/*!
2851 \fn template<typename From, typename To> bool QMetaType::hasRegisteredConverterFunction()
2852 Returns \c true, if the meta type system has a registered conversion from type From to type To.
2853 \since 5.2
2854 \overload
2855 */
2856
2857/*!
2858 Returns \c true, if the meta type system has a registered conversion from meta type id \a fromType
2859 to \a toType
2860 \since 5.2
2861*/
2862bool QMetaType::hasRegisteredConverterFunction(QMetaType fromType, QMetaType toType)
2863{
2864 return customTypesConversionRegistry()->contains({fromType.id(), toType.id()});
2865}
2866
2867/*!
2868 \internal
2869 Non-template helper ("SCARY") for IsMetaTypePair::registerConverter().
2870*/
2871bool QtPrivate::hasRegisteredConverterFunctionToPairVariantInterface(QMetaType m)
2872{
2873 const QMetaType to = QMetaType::fromType<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
2874 return QMetaType::hasRegisteredConverterFunction(m, to);
2875}
2876
2877/*!
2878 \internal
2879 Non-template helper ("SCARY") for SequentialValueTypeIsMetaType::registerConverter().
2880*/
2881bool QtPrivate::hasRegisteredConverterFunctionToIterableMetaSequence(QMetaType m)
2882{
2883 const QMetaType to = QMetaType::fromType<QIterable<QMetaSequence>>();
2884 return QMetaType::hasRegisteredConverterFunction(m, to);
2885}
2886
2887/*!
2888 \internal
2889 Non-template helper ("SCARY") for AssociativeKeyTypeIsMetaType::registerConverter().
2890*/
2891bool QtPrivate::hasRegisteredConverterFunctionToIterableMetaAssociation(QMetaType m)
2892{
2893 const QMetaType to = QMetaType::fromType<QIterable<QMetaAssociation>>();
2894 return QMetaType::hasRegisteredConverterFunction(m, to);
2895}
2896
2897/*!
2898 \fn template<typename From, typename To> bool QMetaType::hasRegisteredMutableViewFunction()
2899 Returns \c true, if the meta type system has a registered mutable view on type From of type To.
2900 \since 6.0
2901 \overload
2902*/
2903
2904/*!
2905 Returns \c true, if the meta type system has a registered mutable view on meta type id
2906 \a fromType of meta type id \a toType.
2907 \since 5.2
2908*/
2909bool QMetaType::hasRegisteredMutableViewFunction(QMetaType fromType, QMetaType toType)
2910{
2911 return customTypesMutableViewRegistry()->contains({fromType.id(), toType.id()});
2912}
2913
2914/*!
2915 \internal
2916 Non-template helper ("SCARY") for SequentialValueTypeIsMetaType::registerMutableView().
2917*/
2918bool QtPrivate::hasRegisteredMutableViewFunctionToIterableMetaSequence(QMetaType m)
2919{
2920 const QMetaType to = QMetaType::fromType<QIterable<QMetaSequence>>();
2921 return QMetaType::hasRegisteredMutableViewFunction(m, to);
2922}
2923
2924/*!
2925 \internal
2926 Non-template helper ("SCARY") for AssociativeKeyTypeIsMetaType::registerMutableView().
2927*/
2928bool QtPrivate::hasRegisteredMutableViewFunctionToIterableMetaAssociation(QMetaType m)
2929{
2930 const QMetaType to = QMetaType::fromType<QIterable<QMetaAssociation>>();
2931 return QMetaType::hasRegisteredMutableViewFunction(m, to);
2932}
2933#endif // !QT_BOOTSTRAPPED
2934
2935/*!
2936 \fn const char *QMetaType::typeName(int typeId)
2937 \deprecated
2938
2939 Returns the type name associated with the given \a typeId, or a null
2940 pointer if no matching type was found. The returned pointer must not be
2941 deleted.
2942
2943 \sa type(), isRegistered(), Type, name()
2944*/
2945
2946/*!
2947 \fn constexpr const char *QMetaType::name() const
2948 \since 5.15
2949
2950 Returns the type name associated with this QMetaType, or a null
2951 pointer if no matching type was found. The returned pointer must not be
2952 deleted.
2953
2954 \sa typeName()
2955*/
2956
2957/*
2958 Similar to QMetaType::type(), but only looks in the static set of types.
2959*/
2960static inline int qMetaTypeStaticType(QByteArrayView name)
2961{
2962 for (int i = 0; i < types.count(); ++i) {
2963 if (types.viewAt(i) == name)
2964 return types.typeIdMap[i];
2965 }
2966 return QMetaType::UnknownType;
2967}
2968
2969#ifndef QT_BOOTSTRAPPED
2970/*!
2971 \internal
2972
2973 Registers a user type for marshalling, as an alias of another type (typedef).
2974 Note that normalizedTypeName is not checked for conformance with Qt's normalized format,
2975 so it must already conform.
2976*/
2977void QMetaType::registerNormalizedTypedef(const NS(QByteArray) & normalizedTypeName,
2978 QMetaType metaType)
2979{
2980 if (!metaType.isValid())
2981 return;
2982 if (auto reg = customTypeRegistry()) {
2983 QWriteLocker lock(&reg->lock);
2984 auto &al = reg->aliases[normalizedTypeName];
2985 if (al)
2986 return;
2987
2988 al = QMetaTypeCustomRegistry::Alias(
2989 metaType.d_ptr, QMetaTypeCustomRegistry::HasTypedefs::Yes);
2990 reg->aliases[metaType.name()].setTag(QMetaTypeCustomRegistry::HasTypedefs::Yes);
2991 }
2992}
2993#endif // !QT_BOOTSTRAPPED
2994
2995static const QtPrivate::QMetaTypeInterface *interfaceForStaticType(int typeId)
2996{
2997 Q_ASSERT(typeId < QMetaType::User);
2998 if (typeId <= QMetaType::LastCoreType)
2999 return QCoreVariantHelper::interfaceForType(typeId);
3000 if (typeId >= QMetaType::FirstGuiType && typeId <= QMetaType::LastGuiType)
3001 return qMetaTypeGuiHelper.interfaceForType(typeId);
3002 if (typeId >= QMetaType::FirstWidgetsType && typeId <= QMetaType::LastWidgetsType)
3003 return qMetaTypeWidgetsHelper.interfaceForType(typeId);
3004 return nullptr;
3006
3007static const QtPrivate::QMetaTypeInterface *interfaceForTypeNoWarning(int typeId)
3008{
3009 const QtPrivate::QMetaTypeInterface *iface = nullptr;
3010 if (typeId >= QMetaType::User) {
3011#ifndef QT_BOOTSTRAPPED
3012 if (customTypeRegistry.exists())
3013 iface = customTypeRegistry->getCustomType(typeId);
3014#endif
3015 } else {
3016 iface = interfaceForStaticType(typeId);
3017 }
3018 return iface;
3019}
3020
3021/*!
3022 Returns \c true if the datatype with ID \a type is registered;
3023 otherwise returns \c false.
3024
3025 \sa type(), Type
3026*/
3027bool QMetaType::isRegistered(int type)
3028{
3029 return interfaceForTypeNoWarning(type) != nullptr;
3031
3032static const QtPrivate::QMetaTypeInterface *findMetaTypeByName(QByteArrayView name)
3033{
3034 Q_PRE(!name.isEmpty());
3035 int type = qMetaTypeStaticType(name);
3036 if (type != QMetaType::UnknownType) {
3037 return interfaceForStaticType(type);
3038#ifndef QT_BOOTSTRAPPED
3039 } else if (customTypeRegistry.exists()) {
3040 QReadLocker locker(&customTypeRegistry->lock);
3041 auto it = customTypeRegistry->aliases.constFind(name);
3042 if (it != customTypeRegistry->aliases.constEnd())
3043 return it.value().data();
3044#endif
3045 }
3046 return nullptr;
3047}
3048
3049/*!
3050 \fn int QMetaType::type(const char *typeName)
3051 \deprecated
3052
3053 Returns a handle to the type called \a typeName, or QMetaType::UnknownType if there is
3054 no such type.
3055
3056 \sa isRegistered(), typeName(), Type
3057*/
3058
3059/*!
3060 \internal
3061
3062 Similar to QMetaType::type(); the only difference is that this function
3063 doesn't attempt to normalize the type name (i.e., the lookup will fail
3064 for type names in non-normalized form).
3065
3066 Used by only QMetaObject, which means the type is always already normalized.
3067*/
3068int qMetaTypeTypeInternal(QByteArrayView name)
3069{
3070 const QtPrivate::QMetaTypeInterface *iface = nullptr;
3071 if (!name.isEmpty())
3072 iface = findMetaTypeByName(name);
3073 return iface ? iface->typeId.loadRelaxed() : QMetaType::UnknownType;
3074}
3075
3076/*!
3077 \fn int QMetaType::type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName)
3078
3079 \since 5.5
3080 \overload
3081 \deprecated
3082
3083 Returns a handle to the type called \a typeName, or 0 if there is
3084 no such type.
3085
3086 \sa isRegistered(), typeName()
3087*/
3088
3089#ifndef QT_NO_DATASTREAM
3090/*!
3091 Writes the object pointed to by \a data to the given \a stream.
3092 Returns \c true if the object is saved successfully; otherwise
3093 returns \c false.
3094
3095 Normally, you should not need to call this function directly.
3096 Instead, use QVariant's \c operator<<(), which relies on save()
3097 to stream custom types.
3098
3099 \sa load()
3100*/
3101bool QMetaType::save(QDataStream &stream, const void *data) const
3102{
3103 if (!data || !isValid())
3104 return false;
3105
3106 // keep compatibility for long/ulong
3107 if (id() == QMetaType::Long) {
3108 stream << qlonglong(*(long *)data);
3109 return true;
3110 } else if (id() == QMetaType::ULong) {
3111 stream << qlonglong(*(unsigned long *)data);
3112 return true;
3113 }
3114
3115 if (!d_ptr->dataStreamOut)
3116 return false;
3117
3118 d_ptr->dataStreamOut(d_ptr, stream, data);
3119 return true;
3120}
3121
3122/*!
3123 \fn bool QMetaType::save(QDataStream &stream, int type, const void *data)
3124 \overload
3125 \deprecated
3126*/
3127
3128/*!
3129 Reads the object of this type from the given \a stream into \a data.
3130 Returns \c true if the object is loaded successfully; otherwise
3131 returns \c false.
3132
3133 Normally, you should not need to call this function directly.
3134 Instead, use QVariant's \c operator>>(), which relies on load()
3135 to stream custom types.
3136
3137 \sa save()
3138*/
3139bool QMetaType::load(QDataStream &stream, void *data) const
3140{
3141 if (!data || !isValid())
3142 return false;
3143
3144 // keep compatibility for long/ulong
3145 if (id() == QMetaType::Long) {
3146 qlonglong ll;
3147 stream >> ll;
3148 *(long *)data = long(ll);
3149 return true;
3150 } else if (id() == QMetaType::ULong) {
3151 qulonglong ull;
3152 stream >> ull;
3153 *(unsigned long *)data = (unsigned long)(ull);
3154 return true;
3155 }
3156 if (!d_ptr->dataStreamIn)
3157 return false;
3158
3159 d_ptr->dataStreamIn(d_ptr, stream, data);
3160 return true;
3161}
3162
3163/*!
3164 \since 6.1
3165
3166 Returns \c true, if the meta type system has registered data stream operators for this
3167 meta type.
3168*/
3169bool QMetaType::hasRegisteredDataStreamOperators() const
3170{
3171 int type = id();
3172 if (type == QMetaType::Long || type == QMetaType::ULong)
3173 return true;
3174 return d_ptr && d_ptr->dataStreamIn != nullptr && d_ptr->dataStreamOut != nullptr;
3175}
3176
3177/*!
3178 \since 6.6
3179
3180 If this metatype represents an enumeration, this method returns a
3181 metatype of a numeric class of the same signedness and size as the
3182 enums underlying type.
3183 If it represents a QFlags type, it returns QMetaType::Int.
3184 In all other cases an invalid QMetaType is returned.
3185 */
3186QMetaType QMetaType::underlyingType() const
3187{
3188 if (!d_ptr || !(flags() & IsEnumeration))
3189 return {};
3190 /* QFlags has enumeration set so that's handled here (qint32
3191 case), as QFlags uses int as the underlying type
3192 Note that we do some approximation here, as we cannot
3193 differentiate between different underlying types of the
3194 same size and signedness (consider char <-> (un)signed char,
3195 int <-> long <-> long long).
3196 */
3197 if (flags() & IsUnsignedEnumeration) {
3198 switch (sizeOf()) {
3199 case 1:
3200 return QMetaType::fromType<quint8>();
3201 case 2:
3202 return QMetaType::fromType<quint16>();
3203 case 4:
3204 return QMetaType::fromType<quint32>();
3205 case 8:
3206 return QMetaType::fromType<quint64>();
3207 default:
3208 break;
3209 }
3210 } else {
3211 switch (sizeOf()) {
3212 case 1:
3213 return QMetaType::fromType<qint8>();
3214 case 2:
3215 return QMetaType::fromType<qint16>();
3216 case 4:
3217 return QMetaType::fromType<qint32>();
3218 case 8:
3219 return QMetaType::fromType<qint64>();
3220 default:
3221 break;
3222 }
3223 }
3224 // int128 can be handled above once we have qint128
3225 return QMetaType();
3226}
3227
3228/*!
3229 \fn bool QMetaType::load(QDataStream &stream, int type, void *data)
3230 \overload
3231 \deprecated
3232*/
3233#endif // QT_NO_DATASTREAM
3234
3235/*!
3236 Returns a QMetaType matching \a typeName. The returned object is
3237 not valid if the typeName is not known to QMetaType
3238 */
3239QMetaType QMetaType::fromName(QByteArrayView typeName)
3240{
3241 if (typeName.isEmpty())
3242 return QMetaType();
3243
3244 const QtPrivate::QMetaTypeInterface *iface = findMetaTypeByName(typeName);
3245 if (iface)
3246 return QMetaType(iface);
3247
3248#if !defined(QT_NO_QOBJECT)
3249 const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName.constData());
3250 if (normalizedTypeName != typeName)
3251 iface = findMetaTypeByName(normalizedTypeName);
3252#endif
3253
3254 return QMetaType(iface);
3255}
3256
3257/*!
3258 \fn void *QMetaType::create(int type, const void *copy)
3259 \deprecated
3260
3261 Returns a copy of \a copy, assuming it is of type \a type. If \a
3262 copy is zero, creates a default constructed instance.
3263
3264 \sa destroy(), isRegistered(), Type
3265*/
3266
3267/*!
3268 \fn void QMetaType::destroy(int type, void *data)
3269 \deprecated
3270 Destroys the \a data, assuming it is of the \a type given.
3271
3272 \sa create(), isRegistered(), Type
3273*/
3274
3275/*!
3276 \fn void *QMetaType::construct(int type, void *where, const void *copy)
3277 \since 5.0
3278 \deprecated
3279
3280 Constructs a value of the given \a type in the existing memory
3281 addressed by \a where, that is a copy of \a copy, and returns
3282 \a where. If \a copy is zero, the value is default constructed.
3283
3284 This is a low-level function for explicitly managing the memory
3285 used to store the type. Consider calling create() if you don't
3286 need this level of control (that is, use "new" rather than
3287 "placement new").
3288
3289 You must ensure that \a where points to a location that can store
3290 a value of type \a type, and that \a where is suitably aligned.
3291 The type's size can be queried by calling sizeOf().
3292
3293 The rule of thumb for alignment is that a type is aligned to its
3294 natural boundary, which is the smallest power of 2 that is bigger
3295 than the type, unless that alignment is larger than the maximum
3296 useful alignment for the platform. For practical purposes,
3297 alignment larger than 2 * sizeof(void*) is only necessary for
3298 special hardware instructions (e.g., aligned SSE loads and stores
3299 on x86).
3300
3301 \sa destruct(), sizeOf()
3302*/
3303
3304
3305/*!
3306 \fn void QMetaType::destruct(int type, void *where)
3307 \since 5.0
3308 \deprecated
3309
3310 Destructs the value of the given \a type, located at \a where.
3311
3312 Unlike destroy(), this function only invokes the type's
3313 destructor, it doesn't invoke the delete operator.
3314
3315 \sa construct()
3316*/
3317
3318/*!
3319 \fn int QMetaType::sizeOf(int type)
3320 \since 5.0
3321 \deprecated
3322
3323 Returns the size of the given \a type in bytes (i.e. sizeof(T),
3324 where T is the actual type identified by the \a type argument).
3325
3326 This function is typically used together with construct()
3327 to perform low-level management of the memory used by a type.
3328
3329 \sa construct(), QMetaType::alignOf()
3330*/
3331
3332/*!
3333 \fn QMetaType::TypeFlags QMetaType::typeFlags(int type)
3334 \since 5.0
3335 \deprecated
3336
3337 Returns flags of the given \a type.
3338
3339 \sa QMetaType::TypeFlags
3340*/
3341
3342/*!
3343 \fn const QMetaObject *QMetaType::metaObjectForType(int type)
3344 \since 5.0
3345 \deprecated
3346
3347 returns QMetaType::metaObject for \a type
3348
3349 \sa metaObject()
3350*/
3351
3352/*!
3353 \fn template <typename T> int qRegisterMetaType(const char *typeName)
3354 \relates QMetaType
3355 \obsolete
3356 \threadsafe
3357
3358 Registers the type name \a typeName for the type \c{T}. Returns
3359 the internal ID used by QMetaType. Any class or struct that has a
3360 public default constructor, a public copy constructor and a public
3361 destructor can be registered.
3362
3363 This function requires that \c{T} is a fully defined type at the point
3364 where the function is called. For pointer types, it also requires that the
3365 pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
3366 to register pointers to forward declared types.
3367
3368 After a type has been registered, you can create and destroy
3369 objects of that type dynamically at run-time.
3370
3371 This example registers the class \c{MyClass}:
3372
3373 \snippet code/src_corelib_kernel_qmetatype.cpp 4
3374
3375 This function is useful to register typedefs so they can be used
3376 by QMetaProperty, or in QueuedConnections
3377
3378 \snippet code/src_corelib_kernel_qmetatype.cpp 9
3379
3380 \warning This function is useful only for registering an alias (typedef)
3381 for every other use case Q_DECLARE_METATYPE and qMetaTypeId() should be used instead.
3382
3383 \sa {QMetaType::}{isRegistered()}, Q_DECLARE_METATYPE()
3384*/
3385
3386/*!
3387 \fn template <typename T> int qRegisterMetaType()
3388 \relates QMetaType
3389 \threadsafe
3390 \since 4.2
3391
3392 Call this function to register the type \c T. Returns the meta type Id.
3393
3394 Example:
3395
3396 \snippet code/src_corelib_kernel_qmetatype.cpp 7
3397
3398 This function requires that \c{T} is a fully defined type at the point
3399 where the function is called. For pointer types, it also requires that the
3400 pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
3401 to register pointers to forward declared types.
3402
3403 To use the type \c T in QMetaType, QVariant, or with the
3404 QObject::property() API, registration is not necessary.
3405
3406 To use the type \c T in queued signal and slot connections,
3407 \c{qRegisterMetaType<T>()} must be called before the first connection is
3408 established. That is typically done in the constructor of the class that
3409 uses \c T, or in the \c{main()} function.
3410
3411 After a type has been registered, it can be found by its name using
3412 QMetaType::fromName().
3413
3414 \sa Q_DECLARE_METATYPE()
3415 */
3416
3417/*!
3418 \fn int qRegisterMetaType(QMetaType meta)
3419 \relates QMetaType
3420 \threadsafe
3421 \since 6.5
3422
3423 Registers the meta type \a meta and returns its type Id.
3424
3425 To use a type with meta type \a meta in queued signal and slot connections,
3426 \c{qRegisterMetaType(meta)} must be called before the first connection is
3427 established. That is typically done in the constructor of the class that
3428 uses the meta type, or in the \c{main()} function.
3429
3430 After a type has been registered, it can be found by its name using
3431 QMetaType::fromName().
3432 */
3433
3434/*!
3435 \fn template <typename T> int qMetaTypeId()
3436 \relates QMetaType
3437 \threadsafe
3438 \since 4.1
3439
3440 Returns the meta type id of type \c T at compile time. If the
3441 type was not declared with Q_DECLARE_METATYPE(), compilation will
3442 fail.
3443
3444 Typical usage:
3445
3446 \snippet code/src_corelib_kernel_qmetatype.cpp 8
3447
3448 QMetaType::type() returns the same ID as qMetaTypeId(), but does
3449 a lookup at runtime based on the name of the type.
3450 QMetaType::type() is a bit slower, but compilation succeeds if a
3451 type is not registered.
3452
3453 \sa Q_DECLARE_METATYPE(), QMetaType::type()
3455
3456static const QtPrivate::QMetaTypeInterface *interfaceForType(int typeId)
3457{
3458 const QtPrivate::QMetaTypeInterface *iface = interfaceForTypeNoWarning(typeId);
3459 if (!iface && typeId != QMetaType::UnknownType)
3460 qWarning("Trying to construct an instance of an invalid type, type id: %i", typeId);
3461
3462 return iface;
3463}
3464
3465/*!
3466 \fn QMetaType::QMetaType()
3467 \since 6.0
3468
3469 Constructs a default, invalid, QMetaType object.
3470*/
3471
3472/*!
3473 \fn QMetaType::QMetaType(int typeId)
3474 \since 5.0
3475
3476 Constructs a QMetaType object that contains all information about type \a typeId.
3477*/
3478QMetaType::QMetaType(int typeId) : QMetaType(interfaceForType(typeId)) {}
3479
3480
3481/*!
3482 \fn size_t qHash(QMetaType key, size_t seed)
3483 \qhashold{QMetaType}
3484 \since 6.4
3485*/
3486
3487namespace QtPrivate {
3488#if !defined(QT_BOOTSTRAPPED)
3489void QMetaTypeCopyTraits::warnAboutDeprecatedCopy(const char *name)
3490{
3491 qCWarning(lcMetatypeDeprecated, "QMetaType: copy construction of type '%s' is deprecated", name);
3492}
3493#endif
3494
3495#if !defined(QT_BOOTSTRAPPED) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY)
3497// Explicit instantiation definition
3498#define QT_METATYPE_DECLARE_TEMPLATE_ITER(TypeName, Id, Name)
3499 template class QMetaTypeForType<Name>;
3500 template struct QMetaTypeInterfaceWrapper<Name>;
3501QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(QT_METATYPE_DECLARE_TEMPLATE_ITER)
3502QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_DECLARE_TEMPLATE_ITER)
3503QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_DECLARE_TEMPLATE_ITER)
3504QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_DECLARE_TEMPLATE_ITER)
3505QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_DECLARE_TEMPLATE_ITER)
3506
3507#undef QT_METATYPE_DECLARE_TEMPLATE_ITER
3508#endif
3509}
3510
3511QT_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:1391
#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