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