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