summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qmetatype.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qmetatype.h')
-rw-r--r--src/corelib/kernel/qmetatype.h873
1 files changed, 607 insertions, 266 deletions
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 7c22ff1693..e956d497e9 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -46,11 +46,13 @@
#include <QtCore/qatomic.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qrefcount.h>
#ifndef QT_NO_QOBJECT
#include <QtCore/qobjectdefs.h>
#endif
-#include <new>
+#include <array>
+#include <new>
#include <vector>
#include <list>
#include <map>
@@ -109,6 +111,13 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
#define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
#endif
+#if QT_CONFIG(regularexpression)
+# define QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F) \
+ F(QRegularExpression, 44, QRegularExpression)
+#else
+# define QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F)
+#endif
+
#define QT_FOR_EACH_STATIC_CORE_CLASS(F)\
F(QChar, 7, QChar) \
F(QString, 10, QString) \
@@ -132,7 +141,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
QT_FOR_EACH_STATIC_EASINGCURVE(F) \
F(QUuid, 30, QUuid) \
F(QVariant, 41, QVariant) \
- F(QRegularExpression, 44, QRegularExpression) \
+ QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F) \
F(QJsonValue, 45, QJsonValue) \
F(QJsonObject, 46, QJsonObject) \
F(QJsonArray, 47, QJsonArray) \
@@ -151,6 +160,13 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QVariantHash, 28, QVariantHash) \
F(QByteArrayList, 49, QByteArrayList) \
+#if QT_CONFIG(shortcut)
+#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)\
+ F(QKeySequence, 75, QKeySequence)
+#else
+#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)
+#endif
+
#define QT_FOR_EACH_STATIC_GUI_CLASS(F)\
F(QFont, 64, QFont) \
F(QPixmap, 65, QPixmap) \
@@ -163,11 +179,10 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QRegion, 72, QRegion) \
F(QBitmap, 73, QBitmap) \
F(QCursor, 74, QCursor) \
- F(QKeySequence, 75, QKeySequence) \
+ QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F) \
F(QPen, 76, QPen) \
F(QTextLength, 77, QTextLength) \
F(QTextFormat, 78, QTextFormat) \
- F(QMatrix, 79, QMatrix) \
F(QTransform, 80, QTransform) \
F(QMatrix4x4, 81, QMatrix4x4) \
F(QVector2D, 82, QVector2D) \
@@ -181,10 +196,6 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
#define QT_FOR_EACH_STATIC_WIDGETS_CLASS(F)\
F(QSizePolicy, 121, QSizePolicy) \
-// ### FIXME kill that set
-#define QT_FOR_EACH_STATIC_HACKS_TYPE(F)\
- F(QMetaTypeId2<qreal>::MetaType, -1, qreal)
-
// F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, AliasingType, "RealType")
#define QT_FOR_EACH_STATIC_ALIAS_TYPE(F)\
F(ULong, -1, ulong, "unsigned long") \
@@ -201,10 +212,11 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(UInt, -1, uint, "quint32") \
F(LongLong, -1, qlonglong, "qint64") \
F(ULongLong, -1, qulonglong, "quint64") \
+ F(QVariantList, -1, QVariantList, "QVector<QVariant>") \
F(QVariantList, -1, QVariantList, "QList<QVariant>") \
F(QVariantMap, -1, QVariantMap, "QMap<QString,QVariant>") \
F(QVariantHash, -1, QVariantHash, "QHash<QString,QVariant>") \
- F(QByteArrayList, -1, QByteArrayList, "QList<QByteArray>") \
+ F(QByteArrayList, -1, QByteArrayList, "QVector<QByteArray>") \
#define QT_FOR_EACH_STATIC_TYPE(F)\
QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
@@ -219,7 +231,6 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
TypeName = Id,
#define QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(F) \
- F(QList) \
F(QVector) \
F(QQueue) \
F(QStack) \
@@ -242,6 +253,9 @@ struct QMetaObject;
namespace QtPrivate
{
+
+class QMetaTypeInterface;
+
/*!
This template is used for implicit conversion from type From to type To.
\internal
@@ -421,13 +435,6 @@ struct ConverterFunctor : public AbstractConverterFunction
}
class Q_CORE_EXPORT QMetaType {
- enum ExtensionFlag { NoExtensionFlags,
- CreateEx = 0x1, DestroyEx = 0x2,
- ConstructEx = 0x4, DestructEx = 0x8,
- NameEx = 0x10, SizeEx = 0x20,
- CtorEx = 0x40, DtorEx = 0x80,
- FlagsEx = 0x100, MetaObjectEx = 0x200
- };
public:
#ifndef Q_CLANG_QDOC
// The code that actually gets compiled.
@@ -472,7 +479,7 @@ public:
QFont = 64, QPixmap = 65, QBrush = 66, QColor = 67, QPalette = 68,
QIcon = 69, QImage = 70, QPolygon = 71, QRegion = 72, QBitmap = 73,
QCursor = 74, QKeySequence = 75, QPen = 76, QTextLength = 77, QTextFormat = 78,
- QMatrix = 79, QTransform = 80, QMatrix4x4 = 81, QVector2D = 82,
+ QTransform = 80, QMatrix4x4 = 81, QVector2D = 82,
QVector3D = 83, QVector4D = 84, QQuaternion = 85, QPolygonF = 86, QColorSpace = 87,
// Widget types
@@ -494,20 +501,11 @@ public:
TrackingPointerToQObject = 0x80,
WasDeclaredAsMetaType = 0x100,
IsGadget = 0x200,
- PointerToGadget = 0x400
+ PointerToGadget = 0x400,
+ IsPointer = 0x800,
};
Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
- typedef void (*Deleter)(void *);
- typedef void *(*Creator)(const void *);
-
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- typedef void (*Destructor)(void *);
- typedef void *(*Constructor)(void *, const void *); // TODO Qt6: remove me
-#endif
- typedef void (*TypedDestructor)(int, void *);
- typedef void *(*TypedConstructor)(int, void *, const void *);
-
typedef void (*SaveOperator)(QDataStream &, const void *);
typedef void (*LoadOperator)(QDataStream &, void *);
#ifndef QT_NO_DATASTREAM
@@ -516,41 +514,8 @@ public:
static void registerStreamOperators(int type, SaveOperator saveOp,
LoadOperator loadOp);
#endif
- static int registerType(const char *typeName, Deleter deleter,
- Creator creator);
- static int registerType(const char *typeName, Deleter deleter,
- Creator creator,
- Destructor destructor,
- Constructor constructor,
- int size,
- QMetaType::TypeFlags flags,
- const QMetaObject *metaObject);
- static int registerType(const char *typeName,
- TypedDestructor destructor,
- TypedConstructor constructor,
- int size,
- QMetaType::TypeFlags flags,
- const QMetaObject *metaObject);
- static bool unregisterType(int type);
- static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, Deleter deleter,
- Creator creator,
- Destructor destructor,
- Constructor constructor,
- int size,
- QMetaType::TypeFlags flags,
- const QMetaObject *metaObject);
- static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, Destructor destructor,
- Constructor constructor,
- int size,
- QMetaType::TypeFlags flags,
- const QMetaObject *metaObject);
- static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, TypedDestructor destructor,
- TypedConstructor constructor,
- int size,
- QMetaType::TypeFlags flags,
- const QMetaObject *metaObject);
- static int registerTypedef(const char *typeName, int aliasId);
- static int registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, int aliasId);
+ static void registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, QMetaType type);
+
static int type(const char *typeName);
static int type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName);
@@ -560,10 +525,6 @@ public:
static const QMetaObject *metaObjectForType(int type);
static bool isRegistered(int type);
static void *create(int type, const void *copy = nullptr);
-#if QT_DEPRECATED_SINCE(5, 0)
- QT_DEPRECATED static void *construct(int type, const void *copy = nullptr)
- { return create(type, copy); }
-#endif
static void destroy(int type, void *data);
static void *construct(int type, void *where, const void *copy);
static void destruct(int type, void *where);
@@ -573,32 +534,37 @@ public:
static bool load(QDataStream &stream, int type, void *data);
#endif
- explicit QMetaType(const int type = QMetaType::UnknownType); // ### Qt6: drop const
- inline ~QMetaType();
+ explicit QMetaType(int type);
+ explicit QMetaType(QtPrivate::QMetaTypeInterface *d);
+ QMetaType();
+ ~QMetaType();
+ QMetaType(const QMetaType &other);
+ QMetaType &operator=(const QMetaType &);
+ QMetaType(QMetaType &&other) : d_ptr(other.d_ptr) { other.d_ptr = nullptr; }
+ QMetaType &operator=(QMetaType &&other)
+ {
+ qSwap(d_ptr, other.d_ptr);
+ return *this;
+ }
- inline bool isValid() const;
- inline bool isRegistered() const;
- inline int id() const;
- inline int sizeOf() const;
- inline TypeFlags flags() const;
- inline const QMetaObject *metaObject() const;
+ bool isValid() const;
+ bool isRegistered() const;
+ int id() const;
+ int sizeOf() const;
+ TypeFlags flags() const;
+ const QMetaObject *metaObject() const;
QT_PREPEND_NAMESPACE(QByteArray) name() const;
- inline void *create(const void *copy = nullptr) const;
- inline void destroy(void *data) const;
- inline void *construct(void *where, const void *copy = nullptr) const;
- inline void destruct(void *data) const;
+ void *create(const void *copy = nullptr) const;
+ void destroy(void *data) const;
+ void *construct(void *where, const void *copy = nullptr) const;
+ void destruct(void *data) const;
template<typename T>
- static QMetaType fromType()
- { return QMetaType(qMetaTypeId<T>()); }
-
- friend bool operator==(const QMetaType &a, const QMetaType &b)
- { return a.m_typeId == b.m_typeId; }
-
- friend bool operator!=(const QMetaType &a, const QMetaType &b)
- { return a.m_typeId != b.m_typeId; }
+ static QMetaType fromType();
+ friend bool operator==(const QMetaType &a, const QMetaType &b) { return a.id() == b.id(); }
+ friend bool operator!=(const QMetaType &a, const QMetaType &b) { return !(a == b); }
public:
template<typename T>
@@ -716,41 +682,11 @@ public:
static bool hasRegisteredConverterFunction(int fromTypeId, int toTypeId);
-private:
- static QMetaType typeInfo(const int type);
- inline QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
- TypedConstructor creator,
- TypedDestructor deleter,
- SaveOperator saveOp,
- LoadOperator loadOp,
- Constructor constructor,
- Destructor destructor,
- uint sizeOf,
- uint theTypeFlags,
- int typeId,
- const QMetaObject *metaObject);
- QMetaType(const QMetaType &other);
- QMetaType &operator =(const QMetaType &);
- inline bool isExtended(const ExtensionFlag flag) const { return m_extensionFlags & flag; }
-
- // Methods used for future binary compatible extensions
- void ctor(const QMetaTypeInterface *info);
- void dtor();
- uint sizeExtended() const;
- QMetaType::TypeFlags flagsExtended() const;
- const QMetaObject *metaObjectExtended() const;
- void *createExtended(const void *copy = nullptr) const;
- void destroyExtended(void *data) const;
- void *constructExtended(void *where, const void *copy = nullptr) const;
- void destructExtended(void *data) const;
-
static bool registerComparatorFunction(const QtPrivate::AbstractComparatorFunction *f, int type);
#ifndef QT_NO_DEBUG_STREAM
static bool registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f, int type);
#endif
-// ### Qt6: FIXME: Remove the special Q_CC_MSVC handling, it was introduced to maintain BC.
-#if !defined(Q_NO_TEMPLATE_FRIENDS) && !defined(Q_CC_MSVC)
#ifndef Q_CLANG_QDOC
template<typename, bool> friend struct QtPrivate::ValueTypeIsMetaType;
template<typename, typename> friend struct QtPrivate::ConverterMemberFunction;
@@ -760,25 +696,11 @@ private:
template<typename, bool> friend struct QtPrivate::IsMetaTypePair;
template<typename, typename> friend struct QtPrivate::MetaTypeSmartPointerHelper;
#endif
-#else
-public:
-#endif
static bool registerConverterFunction(const QtPrivate::AbstractConverterFunction *f, int from, int to);
static void unregisterConverterFunction(int from, int to);
private:
-
- TypedConstructor m_typedConstructor;
- TypedDestructor m_typedDestructor;
- SaveOperator m_saveOp;
- LoadOperator m_loadOp;
- Constructor m_constructor;
- Destructor m_destructor;
- void *m_extension; // space reserved for future use
- uint m_size;
- uint m_typeFlags;
- uint m_extensionFlags;
- int m_typeId;
- const QMetaObject *m_metaObject;
+ friend class QVariant;
+ QtPrivate::QMetaTypeInterface *d_ptr = nullptr;
};
#undef QT_DEFINE_METATYPE_ID
@@ -1052,10 +974,6 @@ struct ContainerAPI : CapabilitiesImpl<T>
};
template<typename T>
-struct ContainerAPI<QList<T> > : CapabilitiesImpl<QList<T> >
-{ static int size(const QList<T> *t) { return t->size(); } };
-
-template<typename T>
struct ContainerAPI<QVector<T> > : CapabilitiesImpl<QVector<T> >
{ static int size(const QVector<T> *t) { return t->size(); } };
@@ -1085,7 +1003,7 @@ public:
// uint _iteratorCapabilities:4;
// uint _revision:3;
// uint _containerCapabilities:4;
- // uint _unused:21;*/
+ // uint _unused:21;
typedef int(*sizeFunc)(const void *p);
typedef const void * (*atFunc)(const void *p, int);
typedef void (*moveIteratorFunc)(const void *p, void **);
@@ -1577,33 +1495,38 @@ namespace QtPrivate
template<typename T, typename Enable = void>
struct MetaObjectForType
{
- static inline const QMetaObject *value() { return nullptr; }
+ static constexpr inline const QMetaObject *value() { return nullptr; }
};
+#ifndef QT_NO_QOBJECT
template<>
struct MetaObjectForType<void>
{
- static inline const QMetaObject *value() { return nullptr; }
+ static constexpr inline const QMetaObject *value() { return nullptr; }
};
template<typename T>
struct MetaObjectForType<T*, typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value>::type>
{
- static inline const QMetaObject *value() { return &T::staticMetaObject; }
+ static constexpr inline const QMetaObject *value() { return &T::staticMetaObject; }
};
template<typename T>
struct MetaObjectForType<T, typename std::enable_if<IsGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
{
- static inline const QMetaObject *value() { return &T::staticMetaObject; }
+ static constexpr inline const QMetaObject *value() { return &T::staticMetaObject; }
};
template<typename T>
struct MetaObjectForType<T, typename std::enable_if<IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
{
- static inline const QMetaObject *value() { return &IsPointerToGadgetHelper<T>::BaseType::staticMetaObject; }
+ static constexpr inline const QMetaObject *value()
+ {
+ return &IsPointerToGadgetHelper<T>::BaseType::staticMetaObject;
+ }
};
template<typename T>
struct MetaObjectForType<T, typename std::enable_if<IsQEnumHelper<T>::Value>::type >
{
- static inline const QMetaObject *value() { return qt_getEnumMetaObject(T()); }
+ static constexpr inline const QMetaObject *value() { return qt_getEnumMetaObject(T()); }
};
+#endif
template<typename T>
struct IsSharedPointerToTypeDerivedFromQObject
@@ -1810,6 +1733,7 @@ namespace QtPrivate {
| (std::is_enum<T>::value ? QMetaType::IsEnumeration : 0)
| (IsGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::IsGadget : 0)
| (IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::PointerToGadget : 0)
+ | (QTypeInfo<T>::isPointer ? QMetaType::IsPointer : 0)
};
};
@@ -1846,31 +1770,20 @@ namespace QtPrivate {
template <typename T>
int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName
#ifndef Q_CLANG_QDOC
- , T * dummy = 0
- , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType defined = QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined
+ , T * = 0
+ , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType = QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined
#endif
)
{
#ifndef QT_NO_QOBJECT
Q_ASSERT_X(normalizedTypeName == QMetaObject::normalizedType(normalizedTypeName.constData()), "qRegisterNormalizedMetaType", "qRegisterNormalizedMetaType was called with a not normalized type name, please call qRegisterMetaType instead.");
#endif
- const int typedefOf = dummy ? -1 : QtPrivate::QMetaTypeIdHelper<T>::qt_metatype_id();
- if (typedefOf != -1)
- return QMetaType::registerNormalizedTypedef(normalizedTypeName, typedefOf);
-
- QMetaType::TypeFlags flags(QtPrivate::QMetaTypeTypeFlags<T>::Flags);
- if (defined)
- flags |= QMetaType::WasDeclaredAsMetaType;
-
- const int id = QMetaType::registerNormalizedType(normalizedTypeName,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Destruct,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Construct,
- int(sizeof(T)),
- flags,
- QtPrivate::MetaObjectForType<T>::value());
+ const QMetaType metaType = QMetaType::fromType<T>();
+ const int id = metaType.id();
if (id > 0) {
+ QMetaType::registerNormalizedTypedef(normalizedTypeName, metaType);
QtPrivate::SequentialContainerConverterHelper<T>::registerConverter(id);
QtPrivate::AssociativeContainerConverterHelper<T>::registerConverter(id);
QtPrivate::MetaTypePairHelper<T>::registerConverter(id);
@@ -1913,8 +1826,11 @@ void qRegisterMetaTypeStreamOperators(const char *typeName
template <typename T>
inline Q_DECL_CONSTEXPR int qMetaTypeId()
{
- Q_STATIC_ASSERT_X(QMetaTypeId2<T>::Defined, "Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system");
- return QMetaTypeId2<T>::qt_metatype_id();
+ if constexpr (bool(QMetaTypeId2<T>::IsBuiltIn)) {
+ return QMetaTypeId2<T>::MetaType;
+ } else {
+ return QMetaType::fromType<T>().id();
+ }
}
template <typename T>
@@ -2080,6 +1996,7 @@ inline int qRegisterMetaTypeStreamOperators()
{ \
enum { Defined = 1, IsBuiltIn = true, MetaType = METATYPEID }; \
static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return METATYPEID; } \
+ static constexpr const char * const name = #NAME; \
}; \
QT_END_NAMESPACE
@@ -2098,7 +2015,7 @@ typedef QHash<QString, QVariant> QVariantHash;
#ifdef Q_CLANG_QDOC
class QByteArrayList;
#else
-typedef QList<QByteArray> QByteArrayList;
+typedef QVector<QByteArray> QByteArrayList;
#endif
#define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE) \
@@ -2121,8 +2038,6 @@ struct QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \
typeName.reserve(int(sizeof(#SINGLE_ARG_TEMPLATE)) + 1 + tNameLen + 1 + 1); \
typeName.append(#SINGLE_ARG_TEMPLATE, int(sizeof(#SINGLE_ARG_TEMPLATE)) - 1) \
.append('<').append(tName, tNameLen); \
- if (typeName.endsWith('>')) \
- typeName.append(' '); \
typeName.append('>'); \
const int newId = qRegisterNormalizedMetaType< SINGLE_ARG_TEMPLATE<T> >( \
typeName, \
@@ -2163,8 +2078,6 @@ struct QMetaTypeId< DOUBLE_ARG_TEMPLATE<T, U> > \
typeName.reserve(int(sizeof(#DOUBLE_ARG_TEMPLATE)) + 1 + tNameLen + 1 + uNameLen + 1 + 1); \
typeName.append(#DOUBLE_ARG_TEMPLATE, int(sizeof(#DOUBLE_ARG_TEMPLATE)) - 1) \
.append('<').append(tName, tNameLen).append(',').append(uName, uNameLen); \
- if (typeName.endsWith('>')) \
- typeName.append(' '); \
typeName.append('>'); \
const int newId = qRegisterNormalizedMetaType< DOUBLE_ARG_TEMPLATE<T, U> >(\
typeName, \
@@ -2298,104 +2211,6 @@ QT_BEGIN_NAMESPACE
#undef Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER
-inline QMetaType::QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
- TypedConstructor creator,
- TypedDestructor deleter,
- SaveOperator saveOp,
- LoadOperator loadOp,
- Constructor constructor,
- Destructor destructor,
- uint size,
- uint theTypeFlags,
- int typeId,
- const QMetaObject *_metaObject)
- : m_typedConstructor(creator)
- , m_typedDestructor(deleter)
- , m_saveOp(saveOp)
- , m_loadOp(loadOp)
- , m_constructor(constructor)
- , m_destructor(destructor)
- , m_extension(nullptr)
- , m_size(size)
- , m_typeFlags(theTypeFlags)
- , m_extensionFlags(extensionFlags)
- , m_typeId(typeId)
- , m_metaObject(_metaObject)
-{
- if (Q_UNLIKELY(isExtended(CtorEx) || typeId == QMetaType::Void))
- ctor(info);
-}
-
-inline QMetaType::~QMetaType()
-{
- if (Q_UNLIKELY(isExtended(DtorEx)))
- dtor();
-}
-
-inline bool QMetaType::isValid() const
-{
- return m_typeId != UnknownType;
-}
-
-inline bool QMetaType::isRegistered() const
-{
- return isValid();
-}
-
-inline int QMetaType::id() const
-{
- return m_typeId;
-}
-
-inline void *QMetaType::create(const void *copy) const
-{
- // ### TODO Qt6 remove the extension
- return createExtended(copy);
-}
-
-inline void QMetaType::destroy(void *data) const
-{
- // ### TODO Qt6 remove the extension
- destroyExtended(data);
-}
-
-inline void *QMetaType::construct(void *where, const void *copy) const
-{
- if (Q_UNLIKELY(isExtended(ConstructEx)))
- return constructExtended(where, copy);
- return m_constructor(where, copy);
-}
-
-inline void QMetaType::destruct(void *data) const
-{
- if (Q_UNLIKELY(isExtended(DestructEx)))
- return destructExtended(data);
- if (Q_UNLIKELY(!data))
- return;
- m_destructor(data);
-}
-
-inline int QMetaType::sizeOf() const
-{
- if (Q_UNLIKELY(isExtended(SizeEx)))
- return sizeExtended();
- return m_size;
-}
-
-inline QMetaType::TypeFlags QMetaType::flags() const
-{
- if (Q_UNLIKELY(isExtended(FlagsEx)))
- return flagsExtended();
- return QMetaType::TypeFlags(m_typeFlags);
-}
-
-inline const QMetaObject *QMetaType::metaObject() const
-{
- if (Q_UNLIKELY(isExtended(MetaObjectEx)))
- return metaObjectExtended();
- return m_metaObject;
-}
-
QT_END_NAMESPACE
@@ -2457,6 +2272,532 @@ namespace QtPrivate {
};
}
+namespace QtPrivate {
+
+class QMetaTypeInterface
+{
+public:
+ uint revision; // 0 in Qt 6.0. Can increase if new field are added
+ uint size;
+ uint alignment;
+ uint flags;
+ const QMetaObject *metaObject;
+ const char *name;
+
+ QBasicAtomicInt typeId;
+ QtPrivate::RefCount ref;
+
+ // Called when the type is unregistered, to delete this
+ using DeleteSelf = void (*)(QMetaTypeInterface *);
+ DeleteSelf deleteSelf;
+
+ using DefaultCtrFn = void (*)(const QMetaTypeInterface *, void *);
+ DefaultCtrFn defaultCtr;
+ using CopyCtrFn = void (*)(const QMetaTypeInterface *, void *, const void *);
+ CopyCtrFn copyCtr;
+ using MoveCtrFn = void (*)(const QMetaTypeInterface *, void *, void *);
+ MoveCtrFn moveCtr;
+ using DtorFn = void (*)(const QMetaTypeInterface *, void *);
+ DtorFn dtor;
+
+ using LegacyRegisterOp = void (*)();
+ LegacyRegisterOp legacyRegisterOp;
+};
+
+struct QTypeNormalizer
+{
+ char *output;
+ int len = 0;
+ char last = 0;
+
+private:
+ static constexpr bool is_ident_char(char s)
+ {
+ return ((s >= 'a' && s <= 'z') || (s >= 'A' && s <= 'Z') || (s >= '0' && s <= '9')
+ || s == '_');
+ }
+ static constexpr bool is_space(char s) { return (s == ' ' || s == '\t' || s == '\n'); }
+ static constexpr bool is_number(char s) { return s >= '0' && s <= '9'; };
+ static constexpr bool starts_with_token(const char *b, const char *e, const char *token,
+ bool msvcKw = false)
+ {
+ while (b != e && *token && *b == *token) {
+ b++;
+ token++;
+ }
+ if (*token)
+ return false;
+#ifdef Q_CC_MSVC
+ /// On MSVC, keywords like class or struct are not separated with spaces in constexpr
+ /// context
+ if (msvcKw)
+ return true;
+#endif
+ Q_UNUSED(msvcKw);
+ return b == e || !is_ident_char(*b);
+ }
+ static constexpr bool skipToken(const char *&x, const char *e, const char *token,
+ bool msvcKw = false)
+ {
+ if (!starts_with_token(x, e, token, msvcKw))
+ return false;
+ while (*token++)
+ x++;
+ while (x != e && is_space(*x))
+ x++;
+ return true;
+ }
+ static constexpr const char *skipString(const char *x, const char *e)
+ {
+ char delim = *x;
+ x++;
+ while (x != e && *x != delim) {
+ if (*x == '\\') {
+ x++;
+ if (x == e)
+ return e;
+ }
+ x++;
+ }
+ if (x != e)
+ x++;
+ return x;
+ };
+ static constexpr const char *skipTemplate(const char *x, const char *e, bool stopAtComa = false)
+ {
+ int scopeDepth = 0;
+ int templateDepth = 0;
+ while (x != e) {
+ switch (*x) {
+ case '<':
+ if (!scopeDepth)
+ templateDepth++;
+ break;
+ case ',':
+ if (stopAtComa && !scopeDepth && !templateDepth)
+ return x;
+ break;
+ case '>':
+ if (!scopeDepth)
+ if (--templateDepth < 0)
+ return x;
+ break;
+ case '(':
+ case '[':
+ case '{':
+ scopeDepth++;
+ break;
+ case '}':
+ case ']':
+ case ')':
+ scopeDepth--;
+ break;
+ case '\'':
+ if (is_number(x[-1]))
+ break;
+ Q_FALLTHROUGH();
+ case '\"':
+ x = skipString(x, e);
+ continue;
+ }
+ x++;
+ }
+ return x;
+ };
+
+ constexpr void append(char x)
+ {
+ last = x;
+ len++;
+ if (output)
+ *output++ = x;
+ }
+
+ constexpr void appendStr(const char *x)
+ {
+ while (*x)
+ append(*x++);
+ };
+
+public:
+ constexpr int normalizeType(const char *begin, const char *end, bool adjustConst = true)
+ {
+ // Trim spaces
+ while (begin != end && is_space(*begin))
+ begin++;
+ while (begin != end && is_space(*(end - 1)))
+ end--;
+
+ // Convert 'char const *' into 'const char *'. Start at index 1,
+ // not 0, because 'const char *' is already OK.
+ const char *cst = begin + 1;
+ if (*begin == '\'' || *begin == '"')
+ cst = skipString(begin, end);
+ bool seenStar = false;
+ bool hasMiddleConst = false;
+ while (cst < end) {
+ if (*cst == '\"' || (*cst == '\'' && !is_number(cst[-1]))) {
+ cst = skipString(cst, end);
+ if (cst == end)
+ break;
+ }
+
+ // We mustn't convert 'char * const *' into 'const char **'
+ // and we must beware of 'Bar<const Bla>'.
+ if (*cst == '&' || *cst == '*' || *cst == '[') {
+ seenStar = *cst != '&' || cst != (end - 1);
+ break;
+ }
+ if (*cst == '<') {
+ cst = skipTemplate(cst + 1, end);
+ if (cst == end)
+ break;
+ }
+ cst++;
+ const char *skipedCst = cst;
+ if (!is_ident_char(*(cst - 1)) && skipToken(skipedCst, end, "const")) {
+ const char *testEnd = end;
+ while (skipedCst < testEnd--) {
+ if (*testEnd == '*' || *testEnd == '['
+ || (*testEnd == '&' && testEnd != (end - 1))) {
+ seenStar = true;
+ break;
+ }
+ if (*testEnd == '>')
+ break;
+ }
+ if (adjustConst && !seenStar) {
+ if (*(end - 1) == '&')
+ end--;
+ } else {
+ appendStr("const ");
+ }
+ normalizeType(begin, cst, false);
+ begin = skipedCst;
+ hasMiddleConst = true;
+ break;
+ }
+ }
+ if (skipToken(begin, end, "const")) {
+ if (adjustConst && !seenStar) {
+ if (*(end - 1) == '&')
+ end--;
+ } else {
+ appendStr("const ");
+ }
+ }
+ if (seenStar && adjustConst) {
+ const char *e = end;
+ if (*(end - 1) == '&' && *(end - 2) != '&')
+ e--;
+ while (begin != e && is_space(*(e - 1)))
+ e--;
+ const char *token = "tsnoc"; // 'const' reverse, to check if it ends with const
+ while (*token && begin != e && *(--e) == *token++)
+ ;
+ if (!*token && begin != e && !is_ident_char(*(e - 1))) {
+ while (begin != e && is_space(*(e - 1)))
+ e--;
+ end = e;
+ }
+ }
+
+ // discard 'struct', 'class', and 'enum'; they are optional
+ // and we don't want them in the normalized signature
+ skipToken(begin, end, "struct", true) || skipToken(begin, end, "class", true)
+ || skipToken(begin, end, "enum", true);
+
+#ifdef QT_NAMESPACE
+ const char *nsbeg = begin;
+ if (skipToken(nsbeg, end, QT_STRINGIFY(QT_NAMESPACE)) && nsbeg + 2 < end && nsbeg[0] == ':'
+ && nsbeg[1] == ':') {
+ begin = nsbeg + 2;
+ while (begin != end && is_space(*begin))
+ begin++;
+ }
+#endif
+
+ if (skipToken(begin, end, "QList")) {
+ // Replace QList by QVector
+ appendStr("QVector");
+ }
+ if (!hasMiddleConst) {
+ // Normalize the integer types
+ int numLong = 0;
+ int numSigned = 0;
+ int numUnsigned = 0;
+ int numInt = 0;
+ int numShort = 0;
+ int numChar = 0;
+ while (begin < end) {
+ if (skipToken(begin, end, "long")) {
+ numLong++;
+ continue;
+ }
+ if (skipToken(begin, end, "int")) {
+ numInt++;
+ continue;
+ }
+ if (skipToken(begin, end, "short")) {
+ numShort++;
+ continue;
+ }
+ if (skipToken(begin, end, "unsigned")) {
+ numUnsigned++;
+ continue;
+ }
+ if (skipToken(begin, end, "signed")) {
+ numSigned++;
+ continue;
+ }
+ if (skipToken(begin, end, "char")) {
+ numChar++;
+ continue;
+ }
+ break;
+ }
+ if (numChar || numShort) {
+ if (numSigned && numChar)
+ appendStr("signed ");
+ if (numUnsigned)
+ appendStr("unsigned ");
+ if (numChar)
+ appendStr("char");
+ else
+ appendStr("short");
+ } else if (numLong) {
+ if (numLong == 1) {
+ if (numUnsigned)
+ append('u');
+ appendStr("long");
+ } else {
+ if (numUnsigned)
+ appendStr("unsigned ");
+ appendStr("long long");
+ }
+ } else if (numUnsigned || numSigned || numInt) {
+ if (numUnsigned)
+ append('u');
+ appendStr("int");
+ }
+ }
+
+ bool spaceSkiped = true;
+ while (begin != end) {
+ char c = *begin++;
+ if (is_space(c)) {
+ spaceSkiped = true;
+ } else if ((c == '\'' && !is_number(last)) || c == '\"') {
+ begin--;
+ auto x = skipString(begin, end);
+ while (begin < x)
+ append(*begin++);
+ } else {
+ if (spaceSkiped && is_ident_char(last) && is_ident_char(c))
+ append(' ');
+ append(c);
+ spaceSkiped = false;
+ if (c == '<') {
+ do {
+ // template recursion
+ const char *tpl = skipTemplate(begin, end, true);
+ normalizeType(begin, tpl, false);
+ if (tpl == end)
+ return len;
+ append(*tpl);
+ begin = tpl;
+ } while (*begin++ == ',');
+ }
+ }
+ }
+ return len;
+ }
+};
+
+// Normalize the type between begin and end, and store the data in the output. Returns the length.
+// The idea is to first run this function with nullptr as output to allocate the output with the
+// size
+constexpr int qNormalizeType(const char *begin, const char *end, char *output)
+{
+ return QTypeNormalizer { output }.normalizeType(begin, end);
+}
+
+template<typename T>
+constexpr auto typenameHelper()
+{
+ constexpr auto prefix = sizeof(
+#ifdef QT_NAMESPACE
+ QT_STRINGIFY(QT_NAMESPACE) "::"
+#endif
+#ifdef Q_CC_MSVC
+ "auto __cdecl QtPrivate::typenameHelper<"
+#elif defined(Q_CC_CLANG)
+ "auto QtPrivate::typenameHelper() [T = "
+#else
+ "constexpr auto QtPrivate::typenameHelper() [with T = "
+#endif
+ ) - 1;
+#ifdef Q_CC_MSVC
+ constexpr int suffix = sizeof(">(void)");
+#else
+ constexpr int suffix = sizeof("]");
+#endif
+
+#if !(defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG))
+ constexpr auto func = Q_FUNC_INFO;
+ constexpr const char *begin = func + prefix;
+ constexpr const char *end = func + sizeof(Q_FUNC_INFO) - suffix;
+ constexpr int len = qNormalizeType(begin, end, nullptr);
+#else // GCC < 8.1 did not have Q_FUNC_INFO as constexpr, and GCC 9 has a precompiled header bug
+ auto func = Q_FUNC_INFO;
+ const char *begin = func + prefix;
+ const char *end = func + sizeof(Q_FUNC_INFO) - suffix;
+ // This is an upper bound of the size since the normalized signature should always be smaller
+ // (Unless there is a QList -> QVector change, but that should not happen)
+ constexpr int len = sizeof(Q_FUNC_INFO) - suffix - prefix;
+#endif
+ std::array<char, len + 1> result {};
+ qNormalizeType(begin, end, result.data());
+ return result;
+}
+
+template<typename T, typename = void>
+struct BuiltinMetaType : std::integral_constant<int, 0>
+{
+};
+template<typename T>
+struct BuiltinMetaType<T, std::enable_if_t<QMetaTypeId2<T>::IsBuiltIn>>
+ : std::integral_constant<int, QMetaTypeId2<T>::MetaType>
+{
+};
+
+template<typename T>
+class QMetaTypeForType
+{
+ static const decltype(typenameHelper<T>()) name;
+
+public:
+ static QMetaTypeInterface metaType;
+};
+
+#ifdef Q_CC_CLANG
+// Workaround for https://bugs.llvm.org/show_bug.cgi?id=44554 : Every lambda used for initializing
+// static members need a different signature for explicit instentiation
+#define QT_METATYPE_CONSTEXPRLAMDA(...) [](std::integral_constant<int, __COUNTER__> = {}) constexpr __VA_ARGS__ ()
+#elif defined(Q_CC_MSVC)
+// Workaround a bug with 'if constexpr' not working in lambda that are not generic in MSVC
+#define QT_METATYPE_CONSTEXPRLAMDA(...) [](auto) constexpr __VA_ARGS__ (0)
+#else
+#define QT_METATYPE_CONSTEXPRLAMDA(...) []() constexpr __VA_ARGS__ ()
+#endif
+
+template<typename T>
+QMetaTypeInterface QMetaTypeForType<T>::metaType = {
+ /*.revision=*/ 0,
+ /*.size=*/ sizeof(T),
+ /*.alignment=*/ alignof(T),
+ /*.flags=*/ QMetaTypeTypeFlags<T>::Flags,
+ /*.metaObject=*/ MetaObjectForType<T>::value(),
+ /*.name=*/ QT_METATYPE_CONSTEXPRLAMDA( -> const char * {
+ if constexpr (bool(QMetaTypeId2<T>::IsBuiltIn)) {
+ return QMetaTypeId2<T>::name;
+ } else {
+ return name.data();
+ }
+ }),
+ /*.typeId=*/ BuiltinMetaType<T>::value,
+ /*.ref=*/ Q_REFCOUNT_INITIALIZE_STATIC,
+ /*.deleteSelf=*/ nullptr,
+ /*.defaultCtr=*/ QT_METATYPE_CONSTEXPRLAMDA( -> QMetaTypeInterface::DefaultCtrFn {
+ if constexpr (std::is_default_constructible_v<T>) {
+ return [](const QMetaTypeInterface *, void *addr) { new (addr) T(); };
+ } else {
+ return nullptr;
+ }
+ }),
+ /*.copyCtr=*/ QT_METATYPE_CONSTEXPRLAMDA( -> QMetaTypeInterface::CopyCtrFn {
+ if constexpr (std::is_copy_constructible_v<T>) {
+ return [](const QMetaTypeInterface *, void *addr, const void *other) {
+ new (addr) T(*reinterpret_cast<const T *>(other));
+ };
+ } else {
+ return nullptr;
+ }
+ }),
+ /*.moveCtr=*/ QT_METATYPE_CONSTEXPRLAMDA( -> QMetaTypeInterface::MoveCtrFn {
+ if constexpr (std::is_move_constructible_v<T>) {
+ return [](const QMetaTypeInterface *, void *addr, void *other) {
+ new (addr) T(std::move(*reinterpret_cast<T *>(other)));
+ };
+ } else {
+ return nullptr;
+ }
+ }),
+ /*.dtor=*/ QT_METATYPE_CONSTEXPRLAMDA( -> QMetaTypeInterface::DtorFn {
+ if constexpr (std::is_destructible_v<T>)
+ return [](const QMetaTypeInterface *, void *addr) { reinterpret_cast<T *>(addr)->~T(); };
+ else
+ return nullptr;
+ }),
+ /*.legacyRegisterOp=*/ QT_METATYPE_CONSTEXPRLAMDA( -> QMetaTypeInterface::LegacyRegisterOp {
+ if constexpr (QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn) {
+ return []() { QMetaTypeId2<T>::qt_metatype_id(); };
+ } else {
+ return nullptr;
+ }
+ })
+};
+#undef QT_METATYPE_CONSTEXPRLAMDA
+
+template<typename T>
+constexpr const decltype(typenameHelper<T>()) QMetaTypeForType<T>::name = typenameHelper<T>();
+
+template<>
+class QMetaTypeForType<void>
+{
+};
+
+#ifndef QT_BOOTSTRAPPED
+#define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name) \
+ extern template class Q_CORE_EXPORT QMetaTypeForType<Name>;
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_MSVC(4910) // '__declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wattributes") // false positive because of QMetaTypeForType<void>
+QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
+QT_WARNING_POP
+QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
+QT_FOR_EACH_STATIC_CORE_CLASS(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
+QT_FOR_EACH_STATIC_CORE_POINTER(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
+QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
+QT_WARNING_POP
+#undef QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER
+#endif
+
+template<typename T>
+constexpr QMetaTypeInterface *qMetaTypeInterfaceForType()
+{
+ using Ty = std::remove_cv_t<std::remove_reference_t<T>>;
+ if constexpr (std::is_same_v<Ty, void>) {
+ return nullptr;
+ } else {
+ return &QMetaTypeForType<Ty>::metaType;
+ }
+}
+
+} // namespace QtPrivate
+
+template<typename T>
+QMetaType QMetaType::fromType()
+{
+ return QMetaType(QtPrivate::qMetaTypeInterfaceForType<T>());
+}
+
+template<typename... T>
+QtPrivate::QMetaTypeInterface *const qt_metaTypeArray[] = {
+ QtPrivate::qMetaTypeInterfaceForType<T>()...
+};
+
QT_END_NAMESPACE
#endif // QMETATYPE_H