summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qmetatype.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qmetatype.cpp')
-rw-r--r--src/corelib/kernel/qmetatype.cpp1041
1 files changed, 674 insertions, 367 deletions
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index a1dcf2d130..9a57f46cbf 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -1,41 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
+// Copyright (C) 2021 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmetatype.h"
#include "qmetatype_p.h"
@@ -43,6 +9,8 @@
#include "qdatetime.h"
#include "qbytearray.h"
#include "qreadwritelock.h"
+#include "qhash.h"
+#include "qmap.h"
#include "qstring.h"
#include "qstringlist.h"
#include "qlist.h"
@@ -52,14 +20,14 @@
#include "qeasingcurve.h"
#endif
#include "quuid.h"
-#include "qvariant.h"
-#include "qdatastream.h"
#if QT_CONFIG(regularexpression)
# include "qregularexpression.h"
#endif
#ifndef QT_BOOTSTRAPPED
+# include "qdatastream.h"
+
# include "qbitarray.h"
# include "qurl.h"
# include "qvariant.h"
@@ -74,6 +42,7 @@
# include "qmetaobject.h"
# include "qsequentialiterable.h"
# include "qassociativeiterable.h"
+# include "qobject.h"
#endif
#if QT_CONFIG(itemmodel)
@@ -87,7 +56,6 @@
# include "qline.h"
#endif
-#include <bitset>
#include <new>
#include <cstring>
@@ -95,37 +63,64 @@ QT_BEGIN_NAMESPACE
#define NS(x) QT_PREPEND_NAMESPACE(x)
+QT_IMPL_METATYPE_EXTERN_TAGGED(QtMetaTypePrivate::QPairVariantInterfaceImpl, QPairVariantInterfaceImpl)
+
+using QtMetaTypePrivate::isInterfaceFor;
namespace {
-struct DefinedTypesFilter {
- template<typename T>
- struct Acceptor {
- static const bool IsAccepted = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable && QModulesPrivate::QTypeModuleInfo<T>::IsCore;
- };
+struct QMetaTypeDeleter
+{
+ const QtPrivate::QMetaTypeInterface *iface;
+ void operator()(void *data)
+ {
+ if (iface->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
+ operator delete(data, std::align_val_t(iface->alignment));
+ } else {
+ operator delete(data);
+ }
+ }
};
struct QMetaTypeCustomRegistry
{
+
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
+ QMetaTypeCustomRegistry()
+ {
+ /* qfloat16 was neither a builtin, nor unconditionally registered
+ in QtCore in Qt <= 6.2.
+ Inserting it as an alias ensures that a QMetaType::id call
+ will get the correct built-in type-id (the interface pointers
+ might still not match, but we already deal with that case.
+ */
+ aliases.insert("qfloat16", QtPrivate::qMetaTypeInterfaceForType<qfloat16>());
+ }
+#endif
+
QReadWriteLock lock;
- QList<QtPrivate::QMetaTypeInterface *> registry;
- QHash<QByteArray, QtPrivate::QMetaTypeInterface *> aliases;
+ QList<const QtPrivate::QMetaTypeInterface *> registry;
+ QHash<QByteArray, const QtPrivate::QMetaTypeInterface *> aliases;
// index of first empty (unregistered) type in registry, if any.
int firstEmpty = 0;
- int registerCustomType(QtPrivate::QMetaTypeInterface *ti)
+ int registerCustomType(const QtPrivate::QMetaTypeInterface *cti)
{
+ // we got here because cti->typeId is 0, so this is a custom meta type
+ // (not read-only)
+ auto ti = const_cast<QtPrivate::QMetaTypeInterface *>(cti);
{
QWriteLocker l(&lock);
- if (ti->typeId)
- return ti->typeId;
+ if (int id = ti->typeId.loadRelaxed())
+ return id;
QByteArray name =
#ifndef QT_NO_QOBJECT
QMetaObject::normalizedType
#endif
(ti->name);
if (auto ti2 = aliases.value(name)) {
- ti->typeId.storeRelaxed(ti2->typeId.loadRelaxed());
- return ti2->typeId;
+ const auto id = ti2->typeId.loadRelaxed();
+ ti->typeId.storeRelaxed(id);
+ return id;
}
aliases[name] = ti;
int size = registry.size();
@@ -138,11 +133,11 @@ struct QMetaTypeCustomRegistry
registry.append(ti);
firstEmpty = registry.size();
}
- ti->typeId = firstEmpty + QMetaType::User;
+ ti->typeId.storeRelaxed(firstEmpty + QMetaType::User);
}
if (ti->legacyRegisterOp)
ti->legacyRegisterOp();
- return ti->typeId;
+ return ti->typeId.loadRelaxed();
};
void unregisterDynamicType(int id)
@@ -155,20 +150,14 @@ struct QMetaTypeCustomRegistry
auto &ti = registry[idx];
// We must unregister all names.
- auto it = aliases.begin();
- while (it != aliases.end()) {
- if (it.value() == ti)
- it = aliases.erase(it);
- else
- ++it;
- }
+ aliases.removeIf([ti] (const auto &kv) { return kv.value() == ti; });
ti = nullptr;
firstEmpty = std::min(firstEmpty, idx);
}
- QtPrivate::QMetaTypeInterface *getCustomType(int id)
+ const QtPrivate::QMetaTypeInterface *getCustomType(int id)
{
QReadLocker l(&lock);
return registry.value(id - QMetaType::User - 1);
@@ -179,6 +168,44 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
} // namespace
+// used by QVariant::save(): returns the name used in the Q_DECLARE_METATYPE
+// macro (one of them, indetermine which one)
+const char *QtMetaTypePrivate::typedefNameForType(const QtPrivate::QMetaTypeInterface *type_d)
+{
+ const char *name = nullptr;
+ if (!customTypeRegistry.exists())
+ return name;
+ QMetaTypeCustomRegistry *r = &*customTypeRegistry;
+
+ QByteArrayView officialName(type_d->name);
+ QReadLocker l(&r->lock);
+ auto it = r->aliases.constBegin();
+ auto end = r->aliases.constEnd();
+ for ( ; it != end; ++it) {
+ if (it.value() != type_d)
+ continue;
+ if (it.key() == officialName)
+ continue; // skip the official name
+ name = it.key().constData();
+ ++it;
+ break;
+ }
+
+#ifndef QT_NO_DEBUG
+ QByteArrayList otherNames;
+ for ( ; it != end; ++it) {
+ if (it.value() == type_d && it.key() != officialName)
+ otherNames << it.key();
+ }
+ l.unlock();
+ if (!otherNames.isEmpty())
+ qWarning("QMetaType: type %s has more than one typedef alias: %s, %s",
+ type_d->name, name, otherNames.join(", ").constData());
+#endif
+
+ return name;
+}
+
/*!
\macro Q_DECLARE_OPAQUE_POINTER(PointerType)
\relates QMetaType
@@ -235,7 +262,7 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
\li Pointers to classes derived from QObject
\li QList<T>, QQueue<T>, QStack<T> or QSet<T>
where T is a registered meta type
- \li QHash<T1, T2>, QMap<T1, T2> or QPair<T1, T2> where T1 and T2 are
+ \li QHash<T1, T2>, QMap<T1, T2> or std::pair<T1, T2> where T1 and T2 are
registered meta types
\li QPointer<T>, QSharedPointer<T>, QWeakPointer<T>, where T is a class that derives from QObject
\li Enumerations registered with Q_ENUM or Q_FLAG
@@ -245,7 +272,8 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
\note This method also registers the stream and debug operators for the type if they
are visible at registration time. As this is done automatically in some places,
it is strongly recommended to declare the stream operators for a type directly
- after the type itself.
+ after the type itself. Because of the argument dependent lookup rules of C++, it is
+ also strongly recommended to declare the operators in the same namespace as the type itself.
The stream operators should have the following signatures:
@@ -324,14 +352,20 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
\value LongLong LongLong
\value Short \c{short}
\value Char \c{char}
+ \value Char16 \c{char16_t}
+ \value Char32 \c{char32_t}
\value ULong \c{unsigned long}
\value ULongLong ULongLong
\value UShort \c{unsigned short}
\value SChar \c{signed char}
\value UChar \c{unsigned char}
\value Float \c float
+ \value Float16 qfloat16
+ \omitvalue Float128
+ \omitvalue BFloat16
+ \omitvalue Int128
+ \omitvalue UInt128
\value QObjectStar QObject *
- \value QVariant QVariant
\value QCursor QCursor
\value QDate QDate
@@ -349,6 +383,7 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
\value QStringList QStringList
\value QVariantMap QVariantMap
\value QVariantHash QVariantHash
+ \value QVariantPair QVariantPair
\value QIcon QIcon
\value QPen QPen
\value QLineF QLineF
@@ -389,13 +424,13 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
\value QPersistentModelIndex QPersistentModelIndex (introduced in Qt 5.5)
\value QUuid QUuid
\value QByteArrayList QByteArrayList
+ \value QVariant QVariant
\value User Base value for user types
\value UnknownType This is an invalid type id. It is returned from QMetaType for types that are not registered
- \omitvalue LastCoreType
- \omitvalue LastGuiType
- Additional types can be registered using Q_DECLARE_METATYPE().
+ Additional types can be registered using qRegisterMetaType() or by calling
+ registerType().
\sa type(), typeName()
*/
@@ -405,17 +440,31 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
The enum describes attributes of a type supported by QMetaType.
- \value NeedsConstruction This type has non-trivial constructors. If the flag is not set instances can be safely initialized with memset to 0.
- \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.
- \value MovableType An instance of a type having this attribute can be safely moved by memcpy.
+ \value NeedsConstruction This type has a default constructor. If the flag is not set, instances can be safely initialized with memset to 0.
+ \value NeedsCopyConstruction (since 6.5) This type has a non-trivial copy constructor. If the flag is not set, instances can be copied with memcpy.
+ \value NeedsMoveConstruction (since 6.5) This type has a non-trivial move constructor. If the flag is not set, instances can be moved with memcpy.
+ \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.
+ \value RelocatableType An instance of a type having this attribute can be safely moved to a different memory location using memcpy.
+ \omitvalue MovableType
\omitvalue SharedPointerToQObject
- \value IsEnumeration This type is an enumeration
- \value If the type is an Enumeration, its underlying type is unsigned
- \value PointerToQObject This type is a pointer to a derived of QObject
+ \value IsEnumeration This type is an enumeration.
+ \value IsUnsignedEnumeration If the type is an Enumeration, its underlying type is unsigned.
+ \value PointerToQObject This type is a pointer to a class derived from QObject.
+ \value IsPointer This type is a pointer to another type.
\omitvalue WeakPointerToQObject
\omitvalue TrackingPointerToQObject
- \omitvalue IsGadget \omit This type is a Q_GADGET and it's corresponding QMetaObject can be accessed with QMetaType::metaObject Since 5.5. \endomit
+ \omitvalue IsGadget \omit (since Qt 5.5) This type is a Q_GADGET and its corresponding QMetaObject can be accessed with QMetaType::metaObject. \endomit
\omitvalue PointerToGadget
+ \omitvalue IsQmlList
+ \value IsConst Indicates that values of this type are immutable; for instance, because they are pointers to const objects.
+
+ \note Before Qt 6.5, both the NeedsConstruction and NeedsDestruction flags
+ were incorrectly set if the either copy construtor or destructor were
+ non-trivial (that is, if the type was not trivial).
+
+ Note that the Needs flags may be set but the meta type may not have a
+ publicly-accessible constructor of the relevant type or a
+ publicly-accessible destructor.
*/
/*!
@@ -425,21 +474,24 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
\ingroup objectmodel
\threadsafe
+ \compares equality
The class is used as a helper to marshall types in QVariant and
in queued signals and slots connections. It associates a type
name to a type so that it can be created and destructed
- dynamically at run-time. Declare new types with Q_DECLARE_METATYPE()
- to make them available to QVariant and other template-based functions.
- Call qRegisterMetaType() to make types available to non-template based
- functions, such as the queued signal and slot connections.
+ dynamically at run-time.
- Any class or struct that has a public default
- constructor, a public copy constructor, and a public destructor
- can be registered.
+ Type names can be registered with QMetaType by using either
+ qRegisterMetaType() or registerType(). Registration is not required for
+ most operations; it's only required for operations that attempt to resolve
+ a type name in string form back to a QMetaType object or the type's ID.
+ Those include some old-style signal-slot connections using
+ QObject::connect(), reading user-types from \l QDataStream to \l QVariant,
+ or binding to other languages and IPC mechanisms, like QML, D-Bus,
+ JavaScript, etc.
- The following code allocates and destructs an instance of
- \c{MyClass}:
+ The following code allocates and destructs an instance of \c{MyClass} by
+ its name, which requires that \c{MyClass} have been previously registered:
\snippet code/src_corelib_kernel_qmetatype.cpp 3
@@ -457,6 +509,8 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
Returns \c true if this QMetaType object contains valid
information about a type, false otherwise.
+
+ \sa isRegistered()
*/
bool QMetaType::isValid() const
{
@@ -467,35 +521,49 @@ bool QMetaType::isValid() const
\fn bool QMetaType::isRegistered() const
\since 5.0
- Returns \c true if this QMetaType object contains valid
- information about a type, false otherwise.
+ Returns \c true if this QMetaType object has been registered with the Qt
+ global metatype registry. Registration allows the type to be found by its
+ name (using QMetaType::fromName()) or by its ID (using the constructor).
+
+ \sa qRegisterMetaType(), isValid()
*/
bool QMetaType::isRegistered() const
{
- return d_ptr;
+ return d_ptr && d_ptr->typeId.loadRelaxed();
}
/*!
\fn int QMetaType::id() const
\since 5.13
- Returns id type hold by this QMetatype instance.
+ Returns id type held by this QMetatype instance.
*/
-int QMetaType::id() const
+
+/*!
+ \fn void QMetaType::registerType() const
+ \since 6.5
+
+ Registers this QMetaType with the type registry so it can be found by name,
+ using QMetaType::fromName().
+
+ \sa qRegisterMetaType()
+ */
+/*!
+ \internal
+ Out-of-line path for registerType() and slow path id().
+ */
+int QMetaType::registerHelper(const QtPrivate::QMetaTypeInterface *iface)
{
- if (d_ptr) {
- if (d_ptr->typeId)
- return d_ptr->typeId;
- auto reg = customTypeRegistry();
- if (reg) {
- return reg->registerCustomType(d_ptr);
- }
+ Q_ASSERT(iface);
+ auto reg = customTypeRegistry();
+ if (reg) {
+ return reg->registerCustomType(iface);
}
return 0;
}
/*!
- \fn bool QMetaType::sizeOf() const
+ \fn constexpr qsizetype QMetaType::sizeOf() const
\since 5.0
Returns the size of the type in bytes (i.e. sizeof(T),
@@ -507,15 +575,9 @@ int QMetaType::id() const
\sa QMetaType::construct(), QMetaType::sizeOf(), QMetaType::alignOf()
*/
-qsizetype QMetaType::sizeOf() const
-{
- if (d_ptr)
- return d_ptr->size;
- return 0;
-}
/*!
- \fn int QMetaType::alignOf() const
+ \fn constexpr int QMetaType::alignOf() const
\since 6.0
Returns the alignment of the type in bytes (i.e. alignof(T),
@@ -528,55 +590,45 @@ qsizetype QMetaType::sizeOf() const
\sa QMetaType::construct(), QMetaType::sizeOf()
*/
-qsizetype QMetaType::alignOf() const
-{
- if (d_ptr)
- return d_ptr->alignment;
- return 0;
-}
/*!
- \fn TypeFlags QMetaType::flags() const
+ \fn constexpr TypeFlags QMetaType::flags() const
\since 5.0
- Returns flags of the type for which this QMetaType instance was constructed.
+ Returns flags of the type for which this QMetaType instance was
+ constructed. To inspect specific type traits, prefer using one of the "is-"
+ functions rather than the flags directly.
- \sa QMetaType::TypeFlags, QMetaType::flags()
+ \sa QMetaType::TypeFlags, QMetaType::flags(), isDefaultConstructible(),
+ isCopyConstructible(), isMoveConstructible(), isDestructible(),
+ isEqualityComparable(), isOrdered()
*/
-QMetaType::TypeFlags QMetaType::flags() const
-{
- if (d_ptr)
- return TypeFlags(d_ptr->flags);
- return {};
-}
/*!
- \fn const QMetaObject *QMetaType::metaObject() const
+ \fn constexpr const QMetaObject *QMetaType::metaObject() const
\since 5.5
- return a QMetaObject relative to this type.
+ Returns a QMetaObject relative to this type.
If the type is a pointer type to a subclass of QObject, flags() contains
- QMetaType::PointerToQObject and this function returns the corresponding QMetaObject. This can
- be used to in combinaison with QMetaObject::construct to create QObject of this type.
+ QMetaType::PointerToQObject and this function returns the corresponding QMetaObject.
+ This can be used in combination with QMetaObject::newInstance() to create QObjects of this type.
- If the type is a Q_GADGET, flags() contains QMetaType::IsGadget, and this function returns its
- QMetaObject. This can be used to retrieve QMetaMethod and QMetaProperty and use them on a
- pointer of this type. (given by QVariant::data for example)
+ If the type is a Q_GADGET, flags() contains QMetaType::IsGadget.
+ If the type is a pointer to a Q_GADGET, flags() contains QMetaType::PointerToGadget.
+ In both cases, this function returns its QMetaObject.
+ This can be used to retrieve QMetaMethod and QMetaProperty and use them on a
+ pointer of this type for example, as given by QVariant::data().
- If the type is an enumeration, flags() contains QMetaType::IsEnumeration, and this function
- returns the QMetaObject of the enclosing object if the enum was registered as a Q_ENUM or
- \nullptr otherwise
+ If the type is an enumeration, flags() contains QMetaType::IsEnumeration.
+ In this case, this function returns the QMetaObject of the enclosing
+ object if the enum was registered as a Q_ENUM or \nullptr otherwise.
\sa QMetaType::flags()
*/
-const QMetaObject *QMetaType::metaObject() const
-{
- return d_ptr ? d_ptr->metaObject : nullptr;
-}
/*!
- \fn void *QMetaType::create(const void *copy = 0) const
+ \fn void *QMetaType::create(const void *copy = nullptr) const
\since 5.0
Returns a copy of \a copy, assuming it is of the type that this
@@ -587,16 +639,17 @@ const QMetaObject *QMetaType::metaObject() const
*/
void *QMetaType::create(const void *copy) const
{
- if (d_ptr) {
- void *where =
-#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
- d_ptr->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__ ?
- operator new(d_ptr->size, std::align_val_t(d_ptr->alignment)) :
-#endif
- operator new(d_ptr->size);
- return construct(where, copy);
- }
- return nullptr;
+ if (copy ? !isCopyConstructible() : !isDefaultConstructible())
+ return nullptr;
+
+ std::unique_ptr<void, QMetaTypeDeleter> where(nullptr, {d_ptr});
+ if (d_ptr->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+ where.reset(operator new(d_ptr->size, std::align_val_t(d_ptr->alignment)));
+ else
+ where.reset(operator new(d_ptr->size));
+
+ QtMetaTypePrivate::construct(d_ptr, where.get(), copy);
+ return where.release();
}
/*!
@@ -610,18 +663,14 @@ void *QMetaType::create(const void *copy) const
*/
void QMetaType::destroy(void *data) const
{
- if (d_ptr && d_ptr->dtor) {
- d_ptr->dtor(d_ptr, data);
- if (d_ptr->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
- operator delete(data, std::align_val_t(d_ptr->alignment));
- } else {
- operator delete(data);
- }
+ if (data && isDestructible()) {
+ QtMetaTypePrivate::destruct(d_ptr, data);
+ QMetaTypeDeleter{d_ptr}(data);
}
}
/*!
- \fn void *QMetaType::construct(void *where, const void *copy = 0) const
+ \fn void *QMetaType::construct(void *where, const void *copy = nullptr) const
\since 5.0
Constructs a value of the type that this QMetaType instance
@@ -650,16 +699,11 @@ void *QMetaType::construct(void *where, const void *copy) const
{
if (!where)
return nullptr;
- if (d_ptr) {
- if (copy && d_ptr->copyCtr) {
- d_ptr->copyCtr(d_ptr, where, copy);
- return where;
- } else if (!copy && d_ptr->defaultCtr) {
- d_ptr->defaultCtr(d_ptr, where);
- return where;
- }
- }
- return nullptr;
+ if (copy ? !isCopyConstructible() : !isDefaultConstructible())
+ return nullptr;
+
+ QtMetaTypePrivate::construct(d_ptr, where, copy);
+ return where;
}
/*!
@@ -675,20 +719,28 @@ void *QMetaType::construct(void *where, const void *copy) const
*/
void QMetaType::destruct(void *data) const
{
- if (!data)
- return;
- if (d_ptr && d_ptr->dtor) {
- d_ptr->dtor(d_ptr, data);
- return;
- }
+ if (data && isDestructible())
+ QtMetaTypePrivate::destruct(d_ptr, data);
+}
+
+static QPartialOrdering threeWayCompare(const void *ptr1, const void *ptr2)
+{
+ std::less<const void *> less;
+ if (less(ptr1, ptr2))
+ return QPartialOrdering::Less;
+ if (less(ptr2, ptr1))
+ return QPartialOrdering::Greater;
+ return QPartialOrdering::Equivalent;
}
/*!
Compares the objects at \a lhs and \a rhs for ordering.
- Returns an empty optional if comparison is not supported or the values are unordered.
- Otherwise, returns -1, 0 or +1 according as \a lhs is less than, equal to or greater
- than \a rhs.
+ Returns QPartialOrdering::Unordered if comparison is not supported
+ or the values are unordered. Otherwise, returns
+ QPartialOrdering::Less, QPartialOrdering::Equivalent or
+ QPartialOrdering::Greater if \a lhs is less than, equivalent
+ to or greater than \a rhs, respectively.
Both objects must be of the type described by this metatype. If either \a lhs
or \a rhs is \nullptr, the values are unordered. Comparison is only supported
@@ -707,24 +759,24 @@ void QMetaType::destruct(void *data) const
\since 6.0
\sa equals(), isOrdered()
*/
-std::optional<int> QMetaType::compare(const void *lhs, const void *rhs) const
+QPartialOrdering QMetaType::compare(const void *lhs, const void *rhs) const
{
if (!lhs || !rhs)
- return std::optional<int>{};
- if (d_ptr->flags & QMetaType::IsPointer)
- return std::less<const void *>()(*reinterpret_cast<const void * const *>(lhs),
- *reinterpret_cast<const void * const *>(rhs));
+ return QPartialOrdering::Unordered;
+ if (d_ptr && d_ptr->flags & QMetaType::IsPointer)
+ return threeWayCompare(*reinterpret_cast<const void * const *>(lhs),
+ *reinterpret_cast<const void * const *>(rhs));
if (d_ptr && d_ptr->lessThan) {
if (d_ptr->equals && d_ptr->equals(d_ptr, lhs, rhs))
- return 0;
+ return QPartialOrdering::Equivalent;
if (d_ptr->lessThan(d_ptr, lhs, rhs))
- return -1;
+ return QPartialOrdering::Less;
if (d_ptr->lessThan(d_ptr, rhs, lhs))
- return 1;
+ return QPartialOrdering::Greater;
if (!d_ptr->equals)
- return 0;
+ return QPartialOrdering::Equivalent;
}
- return std::optional<int>{};
+ return QPartialOrdering::Unordered;
}
/*!
@@ -760,6 +812,68 @@ bool QMetaType::equals(const void *lhs, const void *rhs) const
}
/*!
+ \fn bool QMetaType::isDefaultConstructible() const noexcept
+ \since 6.5
+
+ Returns true if this type can be default-constructed. If it can be, then
+ construct() and create() can be used with a \c{copy} parameter that is
+ null.
+
+ \sa flags(), isCopyConstructible(), isMoveConstructible(), isDestructible()
+ */
+
+/*!
+ \fn bool QMetaType::isCopyConstructible() const noexcept
+ \since 6.5
+
+ Returns true if this type can be copy-constructed. If it can be, then
+ construct() and create() can be used with a \c{copy} parameter that is
+ not null.
+
+ \sa flags(), isDefaultConstructible(), isMoveConstructible(), isDestructible()
+ */
+
+/*!
+ \fn bool QMetaType::isMoveConstructible() const noexcept
+ \since 6.5
+
+ Returns true if this type can be move-constructed. QMetaType currently does
+ not have an API to make use of this trait.
+
+ \sa flags(), isDefaultConstructible(), isCopyConstructible(), isDestructible()
+ */
+
+/*!
+ \fn bool QMetaType::isDestructible() const noexcept
+ \since 6.5
+
+ Returns true if this type can be destroyed. If it can be, then destroy()
+ and destruct() can be called.
+
+ \sa flags(), isDefaultConstructible(), isCopyConstructible(), isMoveConstructible()
+ */
+
+bool QMetaType::isDefaultConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
+{
+ return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isDefaultConstructible(iface);
+}
+
+bool QMetaType::isCopyConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
+{
+ return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isCopyConstructible(iface);
+}
+
+bool QMetaType::isMoveConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
+{
+ return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isMoveConstructible(iface);
+}
+
+bool QMetaType::isDestructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
+{
+ return !isInterfaceFor<void>(iface) && QtMetaTypePrivate::isDestructible(iface);
+}
+
+/*!
Returns \c true if a less than or equality operator for the type described by
this metatype was visible to the metatype declaration, otherwise \c false.
@@ -787,19 +901,23 @@ bool QMetaType::isOrdered() const
*/
void QMetaType::unregisterMetaType(QMetaType type)
{
- if (type.d_ptr && type.d_ptr->typeId.loadRelaxed() >= QMetaType::User) {
- if (auto reg = customTypeRegistry())
- reg->unregisterDynamicType(type.d_ptr->typeId.loadRelaxed());
- type.d_ptr->typeId.storeRelease(0);
- }
-}
+ const QtPrivate::QMetaTypeInterface *d_ptr = type.d_ptr;
+ if (!d_ptr)
+ return;
-/*!
- \fn QMetaType::~QMetaType()
+ const int typeId = d_ptr->typeId.loadRelaxed();
+ if (typeId < QMetaType::User)
+ return;
- Destructs this object.
-*/
+ // this is a custom meta type (not read-only)
+
+ if (auto reg = customTypeRegistry()) {
+ Q_ASSERT(reg->getCustomType(typeId) == d_ptr);
+ reg->unregisterDynamicType(typeId);
+ }
+ const_cast<QtPrivate::QMetaTypeInterface *>(d_ptr)->typeId.storeRelease(0);
+}
/*!
\fn template<typename T> QMetaType QMetaType::fromType()
@@ -808,24 +926,28 @@ void QMetaType::unregisterMetaType(QMetaType type)
Returns the QMetaType corresponding to the type in the template parameter.
*/
-/*! \fn bool operator==(QMetaType a, QMetaType b)
+/*! \fn bool QMetaType::operator==(const QMetaType &lhs, const QMetaType &rhs)
\since 5.15
- \relates QMetaType
\overload
- Returns \c true if the QMetaType \a a represents the same type
- as the QMetaType \a b, otherwise returns \c false.
+ Returns \c true if the QMetaType \a lhs represents the same type
+ as the QMetaType \a rhs, otherwise returns \c false.
*/
-/*! \fn bool operator!=(QMetaType a, QMetaType b)
+/*! \fn bool QMetaType::operator!=(const QMetaType &lhs, const QMetaType &rhs)
\since 5.15
- \relates QMetaType
\overload
- Returns \c true if the QMetaType \a a represents a different type
- than the QMetaType \a b, otherwise returns \c false.
+ Returns \c true if the QMetaType \a lhs represents a different type
+ than the QMetaType \a rhs, otherwise returns \c false.
*/
+/*! \internal */
+bool QMetaTypeModuleHelper::convert(const void *, int, void *, int) const
+{
+ return false;
+}
+
#define QT_ADD_STATIC_METATYPE(MetaTypeName, MetaTypeId, RealName) \
{ #RealName, sizeof(#RealName) - 1, MetaTypeId },
@@ -841,17 +963,18 @@ static const struct { const char * typeName; int typeNameLength; int type; } typ
{nullptr, 0, QMetaType::UnknownType}
};
-static const struct : QMetaTypeModuleHelper
+// NOLINTNEXTLINE(cppcoreguidelines-virtual-class-destructor): this is not a base class
+static constexpr struct : QMetaTypeModuleHelper
{
template<typename T, typename LiteralWrapper =
- std::conditional_t<std::is_same_v<T, QString>, QLatin1String, const char *>>
+ std::conditional_t<std::is_same_v<T, QString>, QLatin1StringView, const char *>>
static inline bool convertToBool(const T &source)
{
T str = source.toLower();
return !(str.isEmpty() || str == LiteralWrapper("0") || str == LiteralWrapper("false"));
}
- QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override {
+ const QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override {
switch (type) {
QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_CONVERT_ID_TO_TYPE)
QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_CONVERT_ID_TO_TYPE)
@@ -867,8 +990,12 @@ static const struct : QMetaTypeModuleHelper
{
Q_ASSERT(fromTypeId != toTypeId);
+ // canConvert calls with two nullptr
bool onlyCheck = (from == nullptr && to == nullptr);
+ // other callers must provide two valid pointers
+ Q_ASSERT(onlyCheck || (bool(from) && bool(to)));
+
using Char = char;
using SChar = signed char;
using UChar = unsigned char;
@@ -884,6 +1011,8 @@ static const struct : QMetaTypeModuleHelper
using Double = double;
using Bool = bool;
using Nullptr = std::nullptr_t;
+ using Char16 = char16_t;
+ using Char32 = char32_t;
#define QMETATYPE_CONVERTER_ASSIGN_DOUBLE(To, From) \
QMETATYPE_CONVERTER(To, From, result = double(source); return true;)
@@ -1038,6 +1167,9 @@ static const struct : QMetaTypeModuleHelper
QMETATYPE_CONVERTER_ASSIGN_QCHAR(ULong);
QMETATYPE_CONVERTER_ASSIGN_QCHAR(UInt);
QMETATYPE_CONVERTER_ASSIGN_QCHAR(ULongLong);
+ QMETATYPE_CONVERTER_ASSIGN_QCHAR(Char16);
+
+ QMETATYPE_CONVERTER(Char16, QChar, result = source.unicode(); return true;)
// conversions to QString
QMETATYPE_CONVERTER_ASSIGN(QString, QChar);
@@ -1075,6 +1207,14 @@ static const struct : QMetaTypeModuleHelper
result = QString::fromLatin1(&s, 1);
return true;
);
+ QMETATYPE_CONVERTER(QString, Char16,
+ result = QChar(source);
+ return true;
+ );
+ QMETATYPE_CONVERTER(QString, Char32,
+ result = QChar::fromUcs4(source).operator QStringView().toString();
+ return true;
+ );
#if QT_CONFIG(datestring)
QMETATYPE_CONVERTER(QString, QDate, result = source.toString(Qt::ISODate); return true;);
QMETATYPE_CONVERTER(QString, QTime, result = source.toString(Qt::ISODateWithMs); return true;);
@@ -1082,7 +1222,7 @@ static const struct : QMetaTypeModuleHelper
#endif
QMETATYPE_CONVERTER(QString, QByteArray, result = QString::fromUtf8(source); return true;);
QMETATYPE_CONVERTER(QString, QStringList,
- return (source.count() == 1) ? (result = source.at(0), true) : false;
+ return (source.size() == 1) ? (result = source.at(0), true) : false;
);
#ifndef QT_BOOTSTRAPPED
QMETATYPE_CONVERTER(QString, QUrl, result = source.toString(); return true;);
@@ -1137,34 +1277,36 @@ static const struct : QMetaTypeModuleHelper
QMETATYPE_CONVERTER_ASSIGN(QRectF, QRect);
QMETATYPE_CONVERTER(QPoint, QPointF, result = source.toPoint(); return true;);
QMETATYPE_CONVERTER_ASSIGN(QPointF, QPoint);
- #endif
+#endif
+
+ QMETATYPE_CONVERTER(QStringList, QString, result = QStringList() << source; return true;);
+#ifndef QT_NO_VARIANT
QMETATYPE_CONVERTER(QByteArrayList, QVariantList,
result.reserve(source.size());
- for (auto v: source)
+ for (const auto &v: source)
result.append(v.toByteArray());
return true;
);
QMETATYPE_CONVERTER(QVariantList, QByteArrayList,
result.reserve(source.size());
- for (auto v: source)
+ for (const auto &v: source)
result.append(QVariant(v));
return true;
);
QMETATYPE_CONVERTER(QStringList, QVariantList,
result.reserve(source.size());
- for (auto v: source)
+ for (const auto &v: source)
result.append(v.toString());
return true;
);
QMETATYPE_CONVERTER(QVariantList, QStringList,
result.reserve(source.size());
- for (auto v: source)
+ for (const auto &v: source)
result.append(QVariant(v));
return true;
);
- QMETATYPE_CONVERTER(QStringList, QString, result = QStringList() << source; return true;);
QMETATYPE_CONVERTER(QVariantHash, QVariantMap,
for (auto it = source.begin(); it != source.end(); ++it)
@@ -1176,7 +1318,7 @@ static const struct : QMetaTypeModuleHelper
result.insert(it.key(), it.value());
return true;
);
-
+#endif // !QT_NO_VARIANT
#ifndef QT_BOOTSTRAPPED
QMETATYPE_CONVERTER_ASSIGN(QCborValue, QString);
QMETATYPE_CONVERTER(QString, QCborValue,
@@ -1515,16 +1657,15 @@ static const struct : QMetaTypeModuleHelper
}
return false;
}
-} metatypeHelper;
+} metatypeHelper = {};
-static const QMetaTypeModuleHelper *qMetaTypeCoreHelper = &metatypeHelper;
-Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeGuiHelper = nullptr;
-Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeWidgetsHelper = nullptr;
+Q_CONSTINIT Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeGuiHelper = nullptr;
+Q_CONSTINIT Q_CORE_EXPORT const QMetaTypeModuleHelper *qMetaTypeWidgetsHelper = nullptr;
static const QMetaTypeModuleHelper *qModuleHelperForType(int type)
{
if (type <= QMetaType::LastCoreType)
- return qMetaTypeCoreHelper;
+ return &metatypeHelper;
if (type >= QMetaType::FirstGuiType && type <= QMetaType::LastGuiType)
return qMetaTypeGuiHelper;
else if (type >= QMetaType::FirstWidgetsType && type <= QMetaType::LastWidgetsType)
@@ -1551,9 +1692,11 @@ public:
bool insertIfNotContains(Key k, const T &f)
{
const QWriteLocker locker(&lock);
- if (map.contains(k))
+ const qsizetype oldSize = map.size();
+ auto &e = map[k];
+ if (map.size() == oldSize) // already present
return false;
- map.insert(k, f);
+ e = f;
return true;
}
@@ -1575,44 +1718,57 @@ private:
QHash<Key, T> map;
};
-typedef QMetaTypeFunctionRegistry<QMetaType::ConverterFunction,QPair<int,int> >
-QMetaTypeConverterRegistry;
+using QMetaTypeConverterRegistry
+ = QMetaTypeFunctionRegistry<QMetaType::ConverterFunction, std::pair<int,int>>;
Q_GLOBAL_STATIC(QMetaTypeConverterRegistry, customTypesConversionRegistry)
using QMetaTypeMutableViewRegistry
- = QMetaTypeFunctionRegistry<QMetaType::MutableViewFunction, QPair<int,int>>;
+ = QMetaTypeFunctionRegistry<QMetaType::MutableViewFunction, std::pair<int,int>>;
Q_GLOBAL_STATIC(QMetaTypeMutableViewRegistry, customTypesMutableViewRegistry)
/*!
- \fn bool QMetaType::registerConverter()
+ \fn template<typename From, typename To> bool QMetaType::registerConverter()
\since 5.2
Registers the possibility of an implicit conversion from type From to type To in the meta
type system. Returns \c true if the registration succeeded, otherwise false.
+
+ \snippet qmetatype/registerConverters.cpp implicit
*/
/*!
- \fn template<typename MemberFunction, int> bool QMetaType::registerConverter(MemberFunction function)
+ \fn template<typename From, typename To> static bool QMetaType::registerConverter(To(From::*function)() const)
\since 5.2
\overload
Registers a method \a function like To From::function() const as converter from type From
to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
+
+ \snippet qmetatype/registerConverters.cpp member
*/
/*!
- \fn template<typename MemberFunctionOk, char> bool QMetaType::registerConverter(MemberFunctionOk function)
+ \fn template<typename From, typename To> static bool QMetaType::registerConverter(To(From::*function)(bool*) const)
\since 5.2
\overload
Registers a method \a function like To From::function(bool *ok) const as converter from type From
to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
+
+ The \c ok pointer can be used by the function to indicate whether the conversion succeeded.
+ \snippet qmetatype/registerConverters.cpp memberOk
+
*/
/*!
- \fn template<typename UnaryFunction> bool QMetaType::registerConverter(UnaryFunction function)
+ \fn template<typename From, typename To, typename UnaryFunction> static bool QMetaType::registerConverter(UnaryFunction function)
\since 5.2
\overload
Registers a unary function object \a function as converter from type From
to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
+
+ \a function must take an instance of type \c From and return an instance of \c To. It can be a function
+ pointer, a lambda or a functor object. Since Qt 6.5, the \a function can also return an instance of
+ \c std::optional<To> to be able to indicate failed conversions.
+ \snippet qmetatype/registerConverters.cpp unaryfunc
*/
/*!
@@ -1624,7 +1780,7 @@ Q_GLOBAL_STATIC(QMetaTypeMutableViewRegistry, customTypesMutableViewRegistry)
*/
bool QMetaType::registerConverterFunction(const ConverterFunction &f, QMetaType from, QMetaType to)
{
- if (!customTypesConversionRegistry()->insertIfNotContains(qMakePair(from.id(), to.id()), f)) {
+ if (!customTypesConversionRegistry()->insertIfNotContains({from.id(), to.id()}, f)) {
qWarning("Type conversion already registered from type %s to type %s",
from.name(), to.name());
return false;
@@ -1633,7 +1789,7 @@ bool QMetaType::registerConverterFunction(const ConverterFunction &f, QMetaType
}
/*!
- \fn template<typename MemberFunction, int> bool QMetaType::registerMutableView(MemberFunction function)
+ \fn template<typename From, typename To> static bool QMetaType::registerMutableView(To(From::*function)())
\since 6.0
\overload
Registers a method \a function like \c {To From::function()} as mutable view of type \c {To} on
@@ -1642,16 +1798,7 @@ bool QMetaType::registerConverterFunction(const ConverterFunction &f, QMetaType
*/
/*!
- \fn template<typename MemberFunctionOk, char> bool QMetaType::registerMutableView(MemberFunctionOk function)
- \since 6.0
- \overload
- Registers a method \a function like To From::function(bool *ok) as mutable view of type To on
- type From in the meta type system. Returns \c true if the registration succeeded, otherwise
- \c false.
-*/
-
-/*!
- \fn template<typename UnaryFunction> bool QMetaType::registerMutableView(UnaryFunction function)
+ \fn template<typename From, typename To, typename UnaryFunction> static bool QMetaType::registerMutableView(UnaryFunction function)
\since 6.0
\overload
Registers a unary function object \a function as mutable view of type To on type From
@@ -1666,7 +1813,7 @@ bool QMetaType::registerConverterFunction(const ConverterFunction &f, QMetaType
*/
bool QMetaType::registerMutableViewFunction(const MutableViewFunction &f, QMetaType from, QMetaType to)
{
- if (!customTypesMutableViewRegistry()->insertIfNotContains(qMakePair(from.id(), to.id()), f)) {
+ if (!customTypesMutableViewRegistry()->insertIfNotContains({from.id(), to.id()}, f)) {
qWarning("Mutable view on type already registered from type %s to type %s",
from.name(), to.name());
return false;
@@ -1699,7 +1846,18 @@ void QMetaType::unregisterConverterFunction(QMetaType from, QMetaType to)
#ifndef QT_NO_DEBUG_STREAM
/*!
- Streams the object at \a rhs of type \a typeId to the debug stream \a dbg. Returns \c true
+ \fn QDebug QMetaType::operator<<(QDebug d, QMetaType m)
+ \since 6.5
+ Writes the QMetaType \a m to the stream \a d, and returns the stream.
+*/
+QDebug operator<<(QDebug d, QMetaType m)
+{
+ const QDebugStateSaver saver(d);
+ return d.nospace() << "QMetaType(" << m.name() << ")";
+}
+
+/*!
+ Streams the object at \a rhs to the debug stream \a dbg. Returns \c true
on success, otherwise false.
\since 5.2
*/
@@ -1719,12 +1877,12 @@ bool QMetaType::debugStream(QDebug& dbg, const void *rhs)
/*!
\fn bool QMetaType::debugStream(QDebug& dbg, const void *rhs, int typeId)
\overload
- \obsolete
+ \deprecated
*/
/*!
- \fn bool QMetaType::hasRegisteredDebugStreamOperator()
- \obsolete
+ \fn template<typename T> bool QMetaType::hasRegisteredDebugStreamOperator()
+ \deprecated
\since 5.2
Returns \c true, if the meta type system has a registered debug stream operator for type T.
@@ -1732,7 +1890,7 @@ bool QMetaType::debugStream(QDebug& dbg, const void *rhs)
/*!
\fn bool QMetaType::hasRegisteredDebugStreamOperator(int typeId)
- \obsolete
+ \deprecated Use QMetaType::hasRegisteredDebugStreamOperator() instead.
Returns \c true, if the meta type system has a registered debug stream operator for type
id \a typeId.
@@ -1740,14 +1898,12 @@ bool QMetaType::debugStream(QDebug& dbg, const void *rhs)
*/
/*!
- \fn bool QMetaType::hasRegisteredDebugStreamOperator(int typeId)
\since 6.0
Returns \c true, if the meta type system has a registered debug stream operator for this
meta type.
*/
bool QMetaType::hasRegisteredDebugStreamOperator() const
-
{
return d_ptr && d_ptr->debugStream != nullptr;
}
@@ -1762,10 +1918,16 @@ static QMetaEnum metaEnumFromType(QMetaType t)
{
if (t.flags() & QMetaType::IsEnumeration) {
if (const QMetaObject *metaObject = t.metaObject()) {
- const QByteArray enumName = t.name();
- const char *lastColon = std::strrchr(enumName, ':');
- return metaObject->enumerator(metaObject->indexOfEnumerator(
- lastColon ? lastColon + 1 : enumName.constData()));
+ QByteArrayView qflagsNamePrefix = "QFlags<";
+ QByteArray enumName = t.name();
+ if (enumName.endsWith('>') && enumName.startsWith(qflagsNamePrefix)) {
+ // extract the template argument
+ enumName.chop(1);
+ enumName = enumName.sliced(qflagsNamePrefix.size());
+ }
+ if (qsizetype lastColon = enumName.lastIndexOf(':'); lastColon != -1)
+ enumName = enumName.sliced(lastColon + 1);
+ return metaObject->enumerator(metaObject->indexOfEnumerator(enumName));
}
}
return QMetaEnum();
@@ -1824,35 +1986,44 @@ static bool convertFromEnum(QMetaType fromType, const void *from, QMetaType toTy
if (toType.id() != QMetaType::QString && toType.id() != QMetaType::QByteArray)
return QMetaType::convert(QMetaType::fromType<qlonglong>(), &ll, toType, to);
}
- Q_ASSERT(toType.id() == QMetaType::QString || toType.id() == QMetaType::QByteArray);
#ifndef QT_NO_QOBJECT
QMetaEnum en = metaEnumFromType(fromType);
if (en.isValid()) {
- const char *key = en.valueToKey(ll);
- if (toType.id() == QMetaType::QString)
- *static_cast<QString *>(to) = QString::fromUtf8(key);
- else
- *static_cast<QByteArray *>(to) = key;
+ if (en.isFlag()) {
+ const QByteArray keys = en.valueToKeys(static_cast<int>(ll));
+ if (toType.id() == QMetaType::QString)
+ *static_cast<QString *>(to) = QString::fromUtf8(keys);
+ else
+ *static_cast<QByteArray *>(to) = keys;
+ } else {
+ const char *key = en.valueToKey(static_cast<int>(ll));
+ if (toType.id() == QMetaType::QString)
+ *static_cast<QString *>(to) = QString::fromUtf8(key);
+ else
+ *static_cast<QByteArray *>(to) = key;
+ }
return true;
}
#endif
+ if (toType.id() == QMetaType::QString || toType.id() == QMetaType::QByteArray)
+ return QMetaType::convert(QMetaType::fromType<qlonglong>(), &ll, toType, to);
return false;
}
static bool convertToEnum(QMetaType fromType, const void *from, QMetaType toType, void *to)
{
int fromTypeId = fromType.id();
- qlonglong value;
+ qlonglong value = -1;
bool ok = false;
#ifndef QT_NO_QOBJECT
if (fromTypeId == QMetaType::QString || fromTypeId == QMetaType::QByteArray) {
QMetaEnum en = metaEnumFromType(toType);
- if (!en.isValid())
- return false;
- QByteArray keys = (fromTypeId == QMetaType::QString)
- ? static_cast<const QString *>(from)->toUtf8()
- : *static_cast<const QByteArray *>(from);
- value = en.keysToValue(keys.constData(), &ok);
+ if (en.isValid()) {
+ QByteArray keys = (fromTypeId == QMetaType::QString)
+ ? static_cast<const QString *>(from)->toUtf8()
+ : *static_cast<const QByteArray *>(from);
+ value = en.keysToValue(keys.constData(), &ok);
+ }
}
#endif
if (!ok) {
@@ -1881,8 +2052,7 @@ static bool convertToEnum(QMetaType fromType, const void *from, QMetaType toType
*static_cast<qint64 *>(to) = value;
return true;
default:
- Q_UNREACHABLE();
- return false;
+ Q_UNREACHABLE_RETURN(false);
}
}
@@ -1930,13 +2100,12 @@ static bool convertIterableToVariantHash(QMetaType fromType, const void *from, v
h.insert(it.key().toString(), it.value());
return true;
}
-#endif
static bool convertIterableToVariantPair(QMetaType fromType, const void *from, void *to)
{
- const QMetaType::ConverterFunction * const f =
- customTypesConversionRegistry()->function(qMakePair(fromType.id(),
- qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>()));
+ const int targetId = qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
+ const auto f = customTypesConversionRegistry()->function({fromType.id(), targetId});
+
if (!f)
return false;
@@ -1962,31 +2131,36 @@ static bool convertIterableToVariantPair(QMetaType fromType, const void *from, v
return true;
}
-#ifndef QT_BOOTSTRAPPED
static bool convertToSequentialIterable(QMetaType fromType, const void *from, void *to)
{
using namespace QtMetaTypePrivate;
- int fromTypeId = fromType.id();
+ const int fromTypeId = fromType.id();
QSequentialIterable &i = *static_cast<QSequentialIterable *>(to);
- if (fromTypeId == QMetaType::QVariantList) {
+ switch (fromTypeId) {
+ case QMetaType::QVariantList:
i = QSequentialIterable(reinterpret_cast<const QVariantList *>(from));
return true;
- }
- if (fromTypeId == QMetaType::QStringList) {
+ case QMetaType::QStringList:
i = QSequentialIterable(reinterpret_cast<const QStringList *>(from));
return true;
- }
- else if (fromTypeId == QMetaType::QByteArrayList) {
+ case QMetaType::QByteArrayList:
i = QSequentialIterable(reinterpret_cast<const QByteArrayList *>(from));
return true;
- }
-
- QSequentialIterable impl;
- if (QMetaType::convert(
- fromType, from, QMetaType::fromType<QIterable<QMetaSequence>>(), &impl)) {
- i = std::move(impl);
+ case QMetaType::QString:
+ i = QSequentialIterable(reinterpret_cast<const QString *>(from));
+ return true;
+ case QMetaType::QByteArray:
+ i = QSequentialIterable(reinterpret_cast<const QByteArray *>(from));
return true;
+ default: {
+ QSequentialIterable impl;
+ if (QMetaType::convert(
+ fromType, from, QMetaType::fromType<QIterable<QMetaSequence>>(), &impl)) {
+ i = std::move(impl);
+ return true;
+ }
+ }
}
return false;
@@ -1998,6 +2172,8 @@ static bool canConvertToSequentialIterable(QMetaType fromType)
case QMetaType::QVariantList:
case QMetaType::QStringList:
case QMetaType::QByteArrayList:
+ case QMetaType::QString:
+ case QMetaType::QByteArray:
return true;
default:
return QMetaType::canConvert(fromType, QMetaType::fromType<QIterable<QMetaSequence>>());
@@ -2010,6 +2186,8 @@ static bool canImplicitlyViewAsSequentialIterable(QMetaType fromType)
case QMetaType::QVariantList:
case QMetaType::QStringList:
case QMetaType::QByteArrayList:
+ case QMetaType::QString:
+ case QMetaType::QByteArray:
return true;
default:
return QMetaType::canView(
@@ -2020,27 +2198,33 @@ static bool canImplicitlyViewAsSequentialIterable(QMetaType fromType)
static bool viewAsSequentialIterable(QMetaType fromType, void *from, void *to)
{
using namespace QtMetaTypePrivate;
- int fromTypeId = fromType.id();
+ const int fromTypeId = fromType.id();
QSequentialIterable &i = *static_cast<QSequentialIterable *>(to);
- if (fromTypeId == QMetaType::QVariantList) {
+ switch (fromTypeId) {
+ case QMetaType::QVariantList:
i = QSequentialIterable(reinterpret_cast<QVariantList *>(from));
return true;
- }
- if (fromTypeId == QMetaType::QStringList) {
+ case QMetaType::QStringList:
i = QSequentialIterable(reinterpret_cast<QStringList *>(from));
return true;
- }
- else if (fromTypeId == QMetaType::QByteArrayList) {
+ case QMetaType::QByteArrayList:
i = QSequentialIterable(reinterpret_cast<QByteArrayList *>(from));
return true;
- }
-
- QIterable<QMetaSequence> j(QMetaSequence(), nullptr);
- if (QMetaType::view(
- fromType, from, QMetaType::fromType<QIterable<QMetaSequence>>(), &j)) {
- i = std::move(j);
+ case QMetaType::QString:
+ i = QSequentialIterable(reinterpret_cast<QString *>(from));
+ return true;
+ case QMetaType::QByteArray:
+ i = QSequentialIterable(reinterpret_cast<QByteArray *>(from));
return true;
+ default: {
+ QIterable<QMetaSequence> j(QMetaSequence(), nullptr);
+ if (QMetaType::view(
+ fromType, from, QMetaType::fromType<QIterable<QMetaSequence>>(), &j)) {
+ i = std::move(j);
+ return true;
+ }
+ }
}
return false;
@@ -2072,6 +2256,9 @@ static bool convertToAssociativeIterable(QMetaType fromType, const void *from, v
static bool canConvertMetaObject(QMetaType fromType, QMetaType toType)
{
+ if ((fromType.flags() & QMetaType::IsPointer) != (toType.flags() & QMetaType::IsPointer))
+ return false; // Can not convert between pointer and value
+
const QMetaObject *f = fromType.metaObject();
const QMetaObject *t = toType.metaObject();
if (f && t) {
@@ -2128,7 +2315,7 @@ static bool viewAsAssociativeIterable(QMetaType fromType, void *from, void *to)
return false;
}
-static bool convertQObject(QMetaType fromType, const void *from, QMetaType toType, void *to)
+static bool convertMetaObject(QMetaType fromType, const void *from, QMetaType toType, void *to)
{
// handle QObject conversion
if ((fromType.flags() & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) {
@@ -2141,26 +2328,39 @@ static bool convertQObject(QMetaType fromType, const void *from, QMetaType toTyp
// if fromObject is null, use static fromType to check if conversion works
*static_cast<void **>(to) = nullptr;
return fromType.metaObject()->inherits(toType.metaObject());
- } else {
- return false;
+ }
+ } else if ((fromType.flags() & QMetaType::IsPointer) == (toType.flags() & QMetaType::IsPointer)) {
+ // fromType and toType are of same 'pointedness'
+ const QMetaObject *f = fromType.metaObject();
+ const QMetaObject *t = toType.metaObject();
+ if (f && t && f->inherits(t)) {
+ toType.destruct(to);
+ toType.construct(to, from);
+ return true;
}
}
return false;
}
-#endif
+#endif // !QT_BOOTSTRAPPED
/*!
\fn bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId)
- \obsolete
+ \deprecated
Converts the object at \a from from \a fromTypeId to the preallocated space at \a to
typed \a toTypeId. Returns \c true, if the conversion succeeded, otherwise false.
+
+ Both \a from and \a to have to be valid pointers.
+
\since 5.2
*/
/*!
Converts the object at \a from from \a fromType to the preallocated space at \a to
typed \a toType. Returns \c true, if the conversion succeeded, otherwise false.
+
+ Both \a from and \a to have to be valid pointers.
+
\since 5.2
*/
bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType, void *to)
@@ -2182,8 +2382,7 @@ bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType,
if (moduleHelper->convert(from, fromTypeId, to, toTypeId))
return true;
}
- const QMetaType::ConverterFunction * const f =
- customTypesConversionRegistry()->function(qMakePair(fromTypeId, toTypeId));
+ const auto f = customTypesConversionRegistry()->function({fromTypeId, toTypeId});
if (f)
return (*f)(from, to);
@@ -2199,10 +2398,11 @@ bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType,
}
}
+#ifndef QT_BOOTSTRAPPED
+# ifndef QT_NO_VARIANT
if (toTypeId == QVariantPair && convertIterableToVariantPair(fromType, from, to))
return true;
-#ifndef QT_BOOTSTRAPPED
// handle iterables
if (toTypeId == QVariantList && convertIterableToVariantList(fromType, from, to))
return true;
@@ -2212,6 +2412,7 @@ bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType,
if (toTypeId == QVariantHash && convertIterableToVariantHash(fromType, from, to))
return true;
+# endif
if (toTypeId == qMetaTypeId<QSequentialIterable>())
return convertToSequentialIterable(fromType, from, to);
@@ -2219,7 +2420,7 @@ bool QMetaType::convert(QMetaType fromType, const void *from, QMetaType toType,
if (toTypeId == qMetaTypeId<QAssociativeIterable>())
return convertToAssociativeIterable(fromType, from, to);
- return convertQObject(fromType, from, toType, to);
+ return convertMetaObject(fromType, from, toType, to);
#else
return false;
#endif
@@ -2238,8 +2439,7 @@ bool QMetaType::view(QMetaType fromType, void *from, QMetaType toType, void *to)
int fromTypeId = fromType.id();
int toTypeId = toType.id();
- const QMetaType::MutableViewFunction * const f =
- customTypesMutableViewRegistry()->function(qMakePair(fromTypeId, toTypeId));
+ const auto f = customTypesMutableViewRegistry()->function({fromTypeId, toTypeId});
if (f)
return (*f)(from, to);
@@ -2250,7 +2450,7 @@ bool QMetaType::view(QMetaType fromType, void *from, QMetaType toType, void *to)
if (toTypeId == qMetaTypeId<QAssociativeIterable>())
return viewAsAssociativeIterable(fromType, from, to);
- return convertQObject(fromType, from, toType, to);
+ return convertMetaObject(fromType, from, toType, to);
#else
return false;
#endif
@@ -2281,8 +2481,7 @@ bool QMetaType::canView(QMetaType fromType, QMetaType toType)
if (fromTypeId == UnknownType || toTypeId == UnknownType)
return false;
- const MutableViewFunction * const f =
- customTypesMutableViewRegistry()->function(qMakePair(fromTypeId, toTypeId));
+ const auto f = customTypesMutableViewRegistry()->function({fromTypeId, toTypeId});
if (f)
return true;
@@ -2387,7 +2586,7 @@ bool QMetaType::canConvert(QMetaType fromType, QMetaType toType)
return true;
}
const ConverterFunction * const f =
- customTypesConversionRegistry()->function(qMakePair(fromTypeId, toTypeId));
+ customTypesConversionRegistry()->function(std::make_pair(fromTypeId, toTypeId));
if (f)
return true;
@@ -2397,7 +2596,8 @@ bool QMetaType::canConvert(QMetaType fromType, QMetaType toType)
if (toTypeId == qMetaTypeId<QAssociativeIterable>())
return canConvertToAssociativeIterable(fromType);
-
+#endif
+#ifndef QT_NO_VARIANT
if (toTypeId == QVariantList
&& canConvert(fromType, QMetaType::fromType<QSequentialIterable>())) {
return true;
@@ -2407,11 +2607,11 @@ bool QMetaType::canConvert(QMetaType fromType, QMetaType toType)
&& canConvert(fromType, QMetaType::fromType<QAssociativeIterable>())) {
return true;
}
-#endif
if (toTypeId == QVariantPair && hasRegisteredConverterFunction(
fromType, QMetaType::fromType<QtMetaTypePrivate::QPairVariantInterfaceImpl>()))
return true;
+#endif
if (fromType.flags() & IsEnumeration) {
if (toTypeId == QString || toTypeId == QByteArray)
@@ -2434,7 +2634,7 @@ bool QMetaType::canConvert(QMetaType fromType, QMetaType toType)
}
/*!
- bool QMetaType::compare(const void *lhs, const void *rhs, int typeId, int* result)
+ \fn bool QMetaType::compare(const void *lhs, const void *rhs, int typeId, int* result)
\deprecated Use the non-static compare method instead
Compares the objects at \a lhs and \a rhs. Both objects need to be of type \a typeId.
@@ -2443,7 +2643,7 @@ bool QMetaType::canConvert(QMetaType fromType, QMetaType toType)
*/
/*!
- \fn bool QMetaType::hasRegisteredConverterFunction()
+ \fn template<typename From, typename To> bool QMetaType::hasRegisteredConverterFunction()
Returns \c true, if the meta type system has a registered conversion from type From to type To.
\since 5.2
\overload
@@ -2456,11 +2656,11 @@ bool QMetaType::canConvert(QMetaType fromType, QMetaType toType)
*/
bool QMetaType::hasRegisteredConverterFunction(QMetaType fromType, QMetaType toType)
{
- return customTypesConversionRegistry()->contains(qMakePair(fromType.id(), toType.id()));
+ return customTypesConversionRegistry()->contains({fromType.id(), toType.id()});
}
/*!
- \fn bool QMetaType::hasRegisteredMutableViewFunction()
+ \fn template<typename From, typename To> bool QMetaType::hasRegisteredMutableViewFunction()
Returns \c true, if the meta type system has a registered mutable view on type From of type To.
\since 6.0
\overload
@@ -2473,7 +2673,7 @@ bool QMetaType::hasRegisteredConverterFunction(QMetaType fromType, QMetaType toT
*/
bool QMetaType::hasRegisteredMutableViewFunction(QMetaType fromType, QMetaType toType)
{
- return customTypesMutableViewRegistry()->contains(qMakePair(fromType.id(), toType.id()));
+ return customTypesMutableViewRegistry()->contains({fromType.id(), toType.id()});
}
/*!
@@ -2488,6 +2688,7 @@ bool QMetaType::hasRegisteredMutableViewFunction(QMetaType fromType, QMetaType t
*/
/*!
+ \fn constexpr const char *QMetaType::name() const
\since 5.15
Returns the type name associated with this QMetaType, or a null
@@ -2496,10 +2697,6 @@ bool QMetaType::hasRegisteredMutableViewFunction(QMetaType fromType, QMetaType t
\sa typeName()
*/
-const char *QMetaType::name() const
-{
- return d_ptr ? d_ptr->name : nullptr;
-}
/*
Similar to QMetaType::type(), but only looks in the static set of types.
@@ -2521,12 +2718,13 @@ static inline int qMetaTypeStaticType(const char *typeName, int length)
*/
static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
{
- if (auto reg = customTypeRegistry()) {
+ if (customTypeRegistry.exists()) {
+ auto reg = &*customTypeRegistry;
#if QT_CONFIG(thread)
Q_ASSERT(!reg->lock.tryLockForWrite());
#endif
- if (auto ti = reg->aliases.value(QByteArray(typeName, length), nullptr)) {
- return ti->typeId;
+ if (auto ti = reg->aliases.value(QByteArray::fromRawData(typeName, length), nullptr)) {
+ return ti->typeId.loadRelaxed();
}
}
return QMetaType::UnknownType;
@@ -2553,6 +2751,20 @@ void QMetaType::registerNormalizedTypedef(const NS(QByteArray) & normalizedTypeN
}
}
+
+static const QtPrivate::QMetaTypeInterface *interfaceForTypeNoWarning(int typeId)
+{
+ const QtPrivate::QMetaTypeInterface *iface = nullptr;
+ if (typeId >= QMetaType::User) {
+ if (customTypeRegistry.exists())
+ iface = customTypeRegistry->getCustomType(typeId);
+ } else {
+ if (auto moduleHelper = qModuleHelperForType(typeId))
+ iface = moduleHelper->interfaceForType(typeId);
+ }
+ return iface;
+}
+
/*!
Returns \c true if the datatype with ID \a type is registered;
otherwise returns \c false.
@@ -2561,7 +2773,7 @@ void QMetaType::registerNormalizedTypedef(const NS(QByteArray) & normalizedTypeN
*/
bool QMetaType::isRegistered(int type)
{
- return QMetaType(type).isRegistered();
+ return interfaceForTypeNoWarning(type) != nullptr;
}
template <bool tryNormalizedType>
@@ -2599,7 +2811,7 @@ static inline int qMetaTypeTypeImpl(const char *typeName, int length)
*/
/*!
- \a internal
+ \internal
Similar to QMetaType::type(); the only difference is that this function
doesn't attempt to normalize the type name (i.e., the lookup will fail
@@ -2611,7 +2823,7 @@ Q_CORE_EXPORT int qMetaTypeTypeInternal(const char *typeName)
}
/*!
- \fn int QMetaType::type(const QByteArray &typeName)
+ \fn int QMetaType::type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName)
\since 5.5
\overload
@@ -2625,12 +2837,9 @@ Q_CORE_EXPORT int qMetaTypeTypeInternal(const char *typeName)
#ifndef QT_NO_DATASTREAM
/*!
- Writes the object pointed to by \a data with the ID \a type to
- the given \a stream. Returns \c true if the object is saved
- successfully; otherwise returns \c false.
-
- The type must have been registered with Q_DECLARE_METATYPE()
- beforehand.
+ Writes the object pointed to by \a data to the given \a stream.
+ Returns \c true if the object is saved successfully; otherwise
+ returns \c false.
Normally, you should not need to call this function directly.
Instead, use QVariant's \c operator<<(), which relies on save()
@@ -2662,16 +2871,13 @@ bool QMetaType::save(QDataStream &stream, const void *data) const
/*!
\fn bool QMetaType::save(QDataStream &stream, int type, const void *data)
\overload
- \obsolete
+ \deprecated
*/
/*!
- Reads the object of the specified \a type from the given \a
- stream into \a data. Returns \c true if the object is loaded
- successfully; otherwise returns \c false.
-
- The type must have been registered with Q_DECLARE_METATYPE()
- beforehand.
+ Reads the object of this type from the given \a stream into \a data.
+ Returns \c true if the object is loaded successfully; otherwise
+ returns \c false.
Normally, you should not need to call this function directly.
Instead, use QVariant's \c operator>>(), which relies on load()
@@ -2704,9 +2910,76 @@ bool QMetaType::load(QDataStream &stream, void *data) const
}
/*!
+ \since 6.1
+
+ Returns \c true, if the meta type system has registered data stream operators for this
+ meta type.
+*/
+bool QMetaType::hasRegisteredDataStreamOperators() const
+{
+ int type = id();
+ if (type == QMetaType::Long || type == QMetaType::ULong)
+ return true;
+ return d_ptr && d_ptr->dataStreamIn != nullptr && d_ptr->dataStreamOut != nullptr;
+}
+
+/*!
+ \since 6.6
+
+ If this metatype represents an enumeration, this method returns a
+ metatype of a numeric class of the same signedness and size as the
+ enums underlying type.
+ If it represents a QFlags type, it returns QMetaType::Int.
+ In all other cases an invalid QMetaType is returned.
+ */
+QMetaType QMetaType::underlyingType() const
+{
+ if (!d_ptr || !(flags() & IsEnumeration))
+ return {};
+ /* QFlags has enumeration set so that's handled here (qint32
+ case), as QFlags uses int as the underlying type
+ Note that we do some approximation here, as we cannot
+ differentiate between different underlying types of the
+ same size and signedness (consider char <-> (un)signed char,
+ int <-> long <-> long long).
+
+ ### TODO PENDING: QTBUG-111926 - QFlags supporting >32 bit int
+ */
+ if (flags() & IsUnsignedEnumeration) {
+ switch (sizeOf()) {
+ case 1:
+ return QMetaType::fromType<quint8>();
+ case 2:
+ return QMetaType::fromType<quint16>();
+ case 4:
+ return QMetaType::fromType<quint32>();
+ case 8:
+ return QMetaType::fromType<quint64>();
+ default:
+ break;
+ }
+ } else {
+ switch (sizeOf()) {
+ case 1:
+ return QMetaType::fromType<qint8>();
+ case 2:
+ return QMetaType::fromType<qint16>();
+ case 4:
+ return QMetaType::fromType<qint32>();
+ case 8:
+ return QMetaType::fromType<qint64>();
+ default:
+ break;
+ }
+ }
+ // int128 can be handled above once we have qint128
+ return QMetaType();
+}
+
+/*!
\fn bool QMetaType::load(QDataStream &stream, int type, void *data)
\overload
- \obsolete
+ \deprecated
*/
#endif // QT_NO_DATASTREAM
@@ -2815,8 +3088,9 @@ QMetaType QMetaType::fromName(QByteArrayView typeName)
*/
/*!
- \fn int qRegisterMetaType(const char *typeName)
+ \fn template <typename T> int qRegisterMetaType(const char *typeName)
\relates QMetaType
+ \obsolete
\threadsafe
Registers the type name \a typeName for the type \c{T}. Returns
@@ -2848,13 +3122,12 @@ QMetaType QMetaType::fromName(QByteArrayView typeName)
*/
/*!
- \fn int qRegisterMetaType()
+ \fn template <typename T> int qRegisterMetaType()
\relates QMetaType
\threadsafe
\since 4.2
- Call this function to register the type \c T. \c T must be declared with
- Q_DECLARE_METATYPE(). Returns the meta type Id.
+ Call this function to register the type \c T. Returns the meta type Id.
Example:
@@ -2865,24 +3138,47 @@ QMetaType QMetaType::fromName(QByteArrayView typeName)
pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
to register pointers to forward declared types.
- After a type has been registered, you can create and destroy
- objects of that type dynamically at run-time.
+ To use the type \c T in QMetaType, QVariant, or with the
+ QObject::property() API, registration is not necessary.
- To use the type \c T in QVariant, using Q_DECLARE_METATYPE() is
- sufficient. To use the type \c T in queued signal and slot connections,
- \c{qRegisterMetaType<T>()} must be called before the first connection
- is established.
+ To use the type \c T in queued signal and slot connections,
+ \c{qRegisterMetaType<T>()} must be called before the first connection is
+ established. That is typically done in the constructor of the class that
+ uses \c T, or in the \c{main()} function.
- Also, to use type \c T with the QObject::property() API,
- \c{qRegisterMetaType<T>()} must be called before it is used, typically
- in the constructor of the class that uses \c T, or in the \c{main()}
- function.
+ After a type has been registered, it can be found by its name using
+ QMetaType::fromName().
\sa Q_DECLARE_METATYPE()
*/
/*!
- \fn int qMetaTypeId()
+ \fn int qRegisterMetaType(QMetaType meta)
+ \relates QMetaType
+ \threadsafe
+ \since 6.5
+
+ Registers the meta type \a meta and returns its type Id.
+
+ This function requires that \c{T} is a fully defined type at the point
+ where the function is called. For pointer types, it also requires that the
+ pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
+ to register pointers to forward declared types.
+
+ To use the type \c T in QMetaType, QVariant, or with the
+ QObject::property() API, registration is not necessary.
+
+ To use the type \c T in queued signal and slot connections,
+ \c{qRegisterMetaType<T>()} must be called before the first connection is
+ established. That is typically done in the constructor of the class that
+ uses \c T, or in the \c{main()} function.
+
+ After a type has been registered, it can be found by its name using
+ QMetaType::fromName().
+ */
+
+/*!
+ \fn template <typename T> int qMetaTypeId()
\relates QMetaType
\threadsafe
\since 4.1
@@ -2903,17 +3199,9 @@ QMetaType QMetaType::fromName(QByteArrayView typeName)
\sa Q_DECLARE_METATYPE(), QMetaType::type()
*/
-static QtPrivate::QMetaTypeInterface *interfaceForType(int typeId)
+static const QtPrivate::QMetaTypeInterface *interfaceForType(int typeId)
{
- QtPrivate::QMetaTypeInterface *iface = nullptr;
- if (typeId >= QMetaType::User) {
- if (auto reg = customTypeRegistry())
- iface = reg->getCustomType(typeId);
- } else {
- if (auto moduleHelper = qModuleHelperForType(typeId))
- iface = moduleHelper->interfaceForType(typeId);
- }
-
+ const QtPrivate::QMetaTypeInterface *iface = interfaceForTypeNoWarning(typeId);
if (!iface && typeId != QMetaType::UnknownType)
qWarning("Trying to construct an instance of an invalid type, type id: %i", typeId);
@@ -2921,6 +3209,13 @@ static QtPrivate::QMetaTypeInterface *interfaceForType(int typeId)
}
/*!
+ \fn QMetaType::QMetaType()
+ \since 6.0
+
+ Constructs a default, invalid, QMetaType object.
+*/
+
+/*!
\fn QMetaType::QMetaType(int typeId)
\since 5.0
@@ -2928,15 +3223,27 @@ static QtPrivate::QMetaTypeInterface *interfaceForType(int typeId)
*/
QMetaType::QMetaType(int typeId) : QMetaType(interfaceForType(typeId)) {}
+
+/*! \fn size_t qHash(QMetaType type, size_t seed = 0)
+ \relates QMetaType
+ \since 6.4
+
+ Returns the hash value for the \a type, using \a seed to seed the calculation.
+*/
+
namespace QtPrivate {
-#ifndef QT_BOOTSTRAPPED
+#if !defined(QT_BOOTSTRAPPED) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY)
+
// Explicit instantiation definition
-#define QT_METATYPE_DECLARE_TEMPLATE_ITER(TypeName, Id, Name) template class QMetaTypeForType<Name>;
-QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_DECLARE_TEMPLATE_ITER)
+#define QT_METATYPE_DECLARE_TEMPLATE_ITER(TypeName, Id, Name) \
+ template class QMetaTypeForType<Name>; \
+ template struct QMetaTypeInterfaceWrapper<Name>;
+QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(QT_METATYPE_DECLARE_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_DECLARE_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_DECLARE_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_DECLARE_TEMPLATE_ITER)
QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_DECLARE_TEMPLATE_ITER)
+
#undef QT_METATYPE_DECLARE_TEMPLATE_ITER
#endif
}