QMetaType: add registerType() and qRegisterMetaType(QMetaType)
This also rewrites QMetaType::id() on top of the helper, with the benefit of calling a member static function, so QMetaType doesn't need to be spilled onto the stack. In some upcoming changes I need to ensure that QMetaTypes are registered so they can be found by name and I'd like to have a dedicated function name for that, instead of calling .id(). Since I needed to add docs for the new function, I've updated for the old one too. [ChangeLog][QMetaType] Added QMetaType::registerType() and an overload of qRegisterMetaType() taking QMetaType (the two functions do the same thing). These two functions ensure a given QMetaType is registered with the Qt global registry, so they can be found by name later. Using qRegisterMetaType<T>() also accomplishes the same thing, but is slightly better for completely generic code because it will avoid emitting the registration for built-in types. Change-Id: I3859764fed084846bcb0fffd170351d606034c22 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
b1d9331c15
commit
74fac865cf
@ -283,6 +283,14 @@ QT_WARNING_POP
|
|||||||
|
|
||||||
#if QT_CORE_REMOVED_SINCE(6, 5)
|
#if QT_CORE_REMOVED_SINCE(6, 5)
|
||||||
|
|
||||||
|
#include "qmetatype.h"
|
||||||
|
|
||||||
|
int QMetaType::idHelper() const
|
||||||
|
{
|
||||||
|
Q_ASSERT(d_ptr);
|
||||||
|
return registerHelper(d_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
#include "qxmlstream.h"
|
#include "qxmlstream.h"
|
||||||
|
|
||||||
QXmlStreamReader::QXmlStreamReader(const QByteArray &data)
|
QXmlStreamReader::QXmlStreamReader(const QByteArray &data)
|
||||||
|
@ -495,19 +495,28 @@ bool QMetaType::isRegistered() const
|
|||||||
\fn int QMetaType::id() const
|
\fn int QMetaType::id() const
|
||||||
\since 5.13
|
\since 5.13
|
||||||
|
|
||||||
Returns id type hold by this QMetatype instance.
|
Returns id type held by this QMetatype instance.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\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
|
\internal
|
||||||
The slowpath of id(). Precondition: d_ptr != nullptr
|
Out-of-line path for registerType() and slow path id().
|
||||||
*/
|
*/
|
||||||
int QMetaType::idHelper() const
|
int QMetaType::registerHelper(const QtPrivate::QMetaTypeInterface *iface)
|
||||||
{
|
{
|
||||||
Q_ASSERT(d_ptr);
|
Q_ASSERT(iface);
|
||||||
auto reg = customTypeRegistry();
|
auto reg = customTypeRegistry();
|
||||||
if (reg) {
|
if (reg) {
|
||||||
return reg->registerCustomType(d_ptr);
|
return reg->registerCustomType(iface);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2890,6 +2899,7 @@ QMetaType QMetaType::fromName(QByteArrayView typeName)
|
|||||||
/*!
|
/*!
|
||||||
\fn int qRegisterMetaType(const char *typeName)
|
\fn int qRegisterMetaType(const char *typeName)
|
||||||
\relates QMetaType
|
\relates QMetaType
|
||||||
|
\obsolete
|
||||||
\threadsafe
|
\threadsafe
|
||||||
|
|
||||||
Registers the type name \a typeName for the type \c{T}. Returns
|
Registers the type name \a typeName for the type \c{T}. Returns
|
||||||
@ -2926,8 +2936,7 @@ QMetaType QMetaType::fromName(QByteArrayView typeName)
|
|||||||
\threadsafe
|
\threadsafe
|
||||||
\since 4.2
|
\since 4.2
|
||||||
|
|
||||||
Call this function to register the type \c T. \c T must be declared with
|
Call this function to register the type \c T. Returns the meta type Id.
|
||||||
Q_DECLARE_METATYPE(). Returns the meta type Id.
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -2938,22 +2947,45 @@ QMetaType QMetaType::fromName(QByteArrayView typeName)
|
|||||||
pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
|
pointed to type is fully defined. Use Q_DECLARE_OPAQUE_POINTER() to be able
|
||||||
to register pointers to forward declared types.
|
to register pointers to forward declared types.
|
||||||
|
|
||||||
After a type has been registered, you can create and destroy
|
To use the type \c T in QMetaType, QVariant, or with the
|
||||||
objects of that type dynamically at run-time.
|
QObject::property() API, registration is not necessary.
|
||||||
|
|
||||||
To use the type \c T in QVariant, using Q_DECLARE_METATYPE() is
|
To use the type \c T in queued signal and slot connections,
|
||||||
sufficient. To use the type \c T in queued signal and slot connections,
|
\c{qRegisterMetaType<T>()} must be called before the first connection is
|
||||||
\c{qRegisterMetaType<T>()} must be called before the first connection
|
established. That is typically done in the constructor of the class that
|
||||||
is established.
|
uses \c T, or in the \c{main()} function.
|
||||||
|
|
||||||
Also, to use type \c T with the QObject::property() API,
|
After a type has been registered, it can be found by its name using
|
||||||
\c{qRegisterMetaType<T>()} must be called before it is used, typically
|
QMetaType::fromName().
|
||||||
in the constructor of the class that uses \c T, or in the \c{main()}
|
|
||||||
function.
|
|
||||||
|
|
||||||
\sa Q_DECLARE_METATYPE()
|
\sa Q_DECLARE_METATYPE()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\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 int qMetaTypeId()
|
\fn int qMetaTypeId()
|
||||||
\relates QMetaType
|
\relates QMetaType
|
||||||
|
@ -426,6 +426,11 @@ public:
|
|||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
bool isRegistered() const;
|
bool isRegistered() const;
|
||||||
|
void registerType() const
|
||||||
|
{
|
||||||
|
// "register" is a reserved keyword
|
||||||
|
registerHelper();
|
||||||
|
}
|
||||||
#if QT_CORE_REMOVED_SINCE(6, 1) || defined(Q_QDOC)
|
#if QT_CORE_REMOVED_SINCE(6, 1) || defined(Q_QDOC)
|
||||||
int id() const;
|
int id() const;
|
||||||
#else
|
#else
|
||||||
@ -434,12 +439,7 @@ public:
|
|||||||
int id(int = 0) const
|
int id(int = 0) const
|
||||||
{
|
{
|
||||||
// keep in sync with the version in removed_api.cpp
|
// keep in sync with the version in removed_api.cpp
|
||||||
if (d_ptr) {
|
return registerHelper();
|
||||||
if (int id = d_ptr->typeId.loadRelaxed())
|
|
||||||
return id;
|
|
||||||
return idHelper();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
constexpr qsizetype sizeOf() const;
|
constexpr qsizetype sizeOf() const;
|
||||||
@ -722,7 +722,23 @@ public:
|
|||||||
const QtPrivate::QMetaTypeInterface *iface() const { return d_ptr; }
|
const QtPrivate::QMetaTypeInterface *iface() const { return d_ptr; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
#if QT_CORE_REMOVED_SINCE(6, 5)
|
||||||
int idHelper() const;
|
int idHelper() const;
|
||||||
|
#endif
|
||||||
|
static int registerHelper(const QtPrivate::QMetaTypeInterface *iface);
|
||||||
|
int registerHelper() const
|
||||||
|
{
|
||||||
|
// keep in sync with the QMetaType::id() version in removed_api.cpp
|
||||||
|
if (d_ptr) {
|
||||||
|
if (int id = d_ptr->typeId.loadRelaxed())
|
||||||
|
return id;
|
||||||
|
return registerHelper(d_ptr);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend int qRegisterMetaType(QMetaType meta);
|
||||||
|
|
||||||
friend class QVariant;
|
friend class QVariant;
|
||||||
const QtPrivate::QMetaTypeInterface *d_ptr = nullptr;
|
const QtPrivate::QMetaTypeInterface *d_ptr = nullptr;
|
||||||
};
|
};
|
||||||
@ -1285,6 +1301,9 @@ template <typename T>
|
|||||||
inline constexpr int qMetaTypeId()
|
inline constexpr int qMetaTypeId()
|
||||||
{
|
{
|
||||||
if constexpr (bool(QMetaTypeId2<T>::IsBuiltIn)) {
|
if constexpr (bool(QMetaTypeId2<T>::IsBuiltIn)) {
|
||||||
|
// this has the same result as the below code, but avoids asking the
|
||||||
|
// compiler to load a global variable whose value we know at compile
|
||||||
|
// time
|
||||||
return QMetaTypeId2<T>::MetaType;
|
return QMetaTypeId2<T>::MetaType;
|
||||||
} else {
|
} else {
|
||||||
return QMetaType::fromType<T>().id();
|
return QMetaType::fromType<T>().id();
|
||||||
@ -1298,6 +1317,11 @@ inline constexpr int qRegisterMetaType()
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int qRegisterMetaType(QMetaType meta)
|
||||||
|
{
|
||||||
|
return meta.registerHelper();
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_QOBJECT
|
#ifndef QT_NO_QOBJECT
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct QMetaTypeIdQObject<T*, QMetaType::PointerToQObject>
|
struct QMetaTypeIdQObject<T*, QMetaType::PointerToQObject>
|
||||||
|
@ -1424,20 +1424,27 @@ void tst_QMetaType::typedefs()
|
|||||||
QCOMPARE(QMetaType::type("WhityDouble"), ::qMetaTypeId<WhityDouble>());
|
QCOMPARE(QMetaType::type("WhityDouble"), ::qMetaTypeId<WhityDouble>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct RegisterTypeType {};
|
||||||
|
|
||||||
void tst_QMetaType::registerType()
|
void tst_QMetaType::registerType()
|
||||||
{
|
{
|
||||||
// Built-in
|
// Built-in
|
||||||
QCOMPARE(qRegisterMetaType<QString>("QString"), int(QMetaType::QString));
|
QCOMPARE(qRegisterMetaType<QString>("QString"), int(QMetaType::QString));
|
||||||
QCOMPARE(qRegisterMetaType<QString>("QString"), int(QMetaType::QString));
|
QCOMPARE(qRegisterMetaType<QString>("QString"), int(QMetaType::QString));
|
||||||
|
qRegisterMetaType(QMetaType::fromType<QString>());
|
||||||
|
|
||||||
// Custom
|
// Custom
|
||||||
int fooId = qRegisterMetaType<TestSpace::Foo>("TestSpace::Foo");
|
int fooId = qRegisterMetaType<TestSpace::Foo>("TestSpace::Foo");
|
||||||
QVERIFY(fooId >= int(QMetaType::User));
|
QVERIFY(fooId >= int(QMetaType::User));
|
||||||
QCOMPARE(qRegisterMetaType<TestSpace::Foo>("TestSpace::Foo"), fooId);
|
QCOMPARE(qRegisterMetaType<TestSpace::Foo>("TestSpace::Foo"), fooId);
|
||||||
|
qRegisterMetaType(QMetaType::fromType<TestSpace::Foo>());
|
||||||
|
|
||||||
int movableId = qRegisterMetaType<CustomMovable>("CustomMovable");
|
int movableId = qRegisterMetaType<CustomMovable>("CustomMovable");
|
||||||
QVERIFY(movableId >= int(QMetaType::User));
|
QVERIFY(movableId >= int(QMetaType::User));
|
||||||
QCOMPARE(qRegisterMetaType<CustomMovable>("CustomMovable"), movableId);
|
QCOMPARE(qRegisterMetaType<CustomMovable>("CustomMovable"), movableId);
|
||||||
|
qRegisterMetaType(QMetaType::fromType<CustomMovable>());
|
||||||
|
|
||||||
|
// Aliases are deprecated
|
||||||
|
|
||||||
// Alias to built-in
|
// Alias to built-in
|
||||||
typedef QString MyString;
|
typedef QString MyString;
|
||||||
@ -1460,6 +1467,23 @@ void tst_QMetaType::registerType()
|
|||||||
QCOMPARE(qRegisterMetaType<MyFoo>("MyFoo"), fooId);
|
QCOMPARE(qRegisterMetaType<MyFoo>("MyFoo"), fooId);
|
||||||
|
|
||||||
QCOMPARE(QMetaType::type("MyFoo"), fooId);
|
QCOMPARE(QMetaType::type("MyFoo"), fooId);
|
||||||
|
|
||||||
|
// this portion of the test can only be run once
|
||||||
|
static bool typeWasRegistered = false;
|
||||||
|
if (!typeWasRegistered) {
|
||||||
|
QMetaType mt = QMetaType::fromType<RegisterTypeType>();
|
||||||
|
QVERIFY(mt.isValid());
|
||||||
|
QCOMPARE_NE(mt.name(), nullptr);
|
||||||
|
|
||||||
|
QVERIFY(!mt.isRegistered());
|
||||||
|
QVERIFY(!QMetaType::fromName(mt.name()).isValid());
|
||||||
|
|
||||||
|
QCOMPARE_GT(qRegisterMetaType(mt), 0);
|
||||||
|
typeWasRegistered = true;
|
||||||
|
|
||||||
|
QVERIFY(mt.isRegistered());
|
||||||
|
QVERIFY(QMetaType::fromName(mt.name()).isValid());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class IsRegisteredDummyType { };
|
class IsRegisteredDummyType { };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user