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