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