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

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

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