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