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.h2625
1 files changed, 1225 insertions, 1400 deletions
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 88a888c956..e3ef1474da 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
-** 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) 2018 Intel Corporation.
+// Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMETATYPE_H
#define QMETATYPE_H
@@ -45,18 +9,24 @@
#include <QtCore/qglobal.h>
#include <QtCore/qatomic.h>
#include <QtCore/qbytearray.h>
-#include <QtCore/qvarlengtharray.h>
-#include <QtCore/qrefcount.h>
+#include <QtCore/qcompare.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qfloat16.h>
+#include <QtCore/qhashfunctions.h>
+#include <QtCore/qiterable.h>
#ifndef QT_NO_QOBJECT
#include <QtCore/qobjectdefs.h>
#endif
+#include <QtCore/qscopeguard.h>
#include <array>
#include <new>
#include <vector>
#include <list>
#include <map>
+#include <functional>
#include <optional>
+#include <QtCore/q20type_traits.h>
#ifdef Bool
#error qmetatype.h must be included before any header file that defines Bool
@@ -71,12 +41,10 @@ template <typename T>
struct QMetaTypeId2;
template <typename T>
-inline Q_DECL_CONSTEXPR int qMetaTypeId();
+inline constexpr int qMetaTypeId();
// F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, RealType)
-// ### Qt6: reorder the types to match the C++ integral type ranking
-#define QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
- F(Void, 43, void) \
+#define QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(F)\
F(Bool, 1, bool) \
F(Int, 2, int) \
F(UInt, 3, uint) \
@@ -96,7 +64,11 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(Nullptr, 51, std::nullptr_t) \
F(QCborSimpleType, 52, QCborSimpleType) \
-#define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\
+#define QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F) \
+ QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(F) \
+ F(Void, 43, void) \
+
+#define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F) \
F(VoidStar, 31, void*) \
#if QT_CONFIG(easingcurve)
@@ -120,11 +92,16 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
#else
# define QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F)
#endif
+#ifndef QT_NO_VARIANT
+# define QT_FOR_EACH_STATIC_QVARIANT(F) \
+ F(QVariant, 41, QVariant)
+#else
+# define QT_FOR_EACH_STATIC_QVARIANT(F)
+#endif
#define QT_FOR_EACH_STATIC_CORE_CLASS(F)\
F(QChar, 7, QChar) \
F(QString, 10, QString) \
- F(QStringList, 11, QStringList) \
F(QByteArray, 12, QByteArray) \
F(QBitArray, 13, QBitArray) \
F(QDate, 14, QDate) \
@@ -142,7 +119,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QPointF, 26, QPointF) \
QT_FOR_EACH_STATIC_EASINGCURVE(F) \
F(QUuid, 30, QUuid) \
- F(QVariant, 41, QVariant) \
+ QT_FOR_EACH_STATIC_QVARIANT(F) \
QT_FOR_EACH_STATIC_REGULAR_EXPRESSION(F) \
F(QJsonValue, 45, QJsonValue) \
F(QJsonObject, 46, QJsonObject) \
@@ -151,52 +128,62 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QCborValue, 53, QCborValue) \
F(QCborArray, 54, QCborArray) \
F(QCborMap, 55, QCborMap) \
+ F(Float16, 63, qfloat16) \
QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
#define QT_FOR_EACH_STATIC_CORE_POINTER(F)\
F(QObjectStar, 39, QObject*)
-#define QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)\
+#ifndef QT_NO_VARIANT
+# define QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)\
F(QVariantMap, 8, QVariantMap) \
F(QVariantList, 9, QVariantList) \
F(QVariantHash, 28, QVariantHash) \
+ F(QVariantPair, 58, QVariantPair) \
+ F(QByteArrayList, 49, QByteArrayList) \
+ F(QStringList, 11, QStringList) \
+ /**/
+#else
+# define QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)\
F(QByteArrayList, 49, QByteArrayList) \
+ F(QStringList, 11, QStringList)
+#endif
#if QT_CONFIG(shortcut)
#define QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F)\
- F(QKeySequence, 75, QKeySequence)
+ F(QKeySequence, 0x100b, 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) \
- F(QBrush, 66, QBrush) \
- F(QColor, 67, QColor) \
- F(QPalette, 68, QPalette) \
- F(QIcon, 69, QIcon) \
- F(QImage, 70, QImage) \
- F(QPolygon, 71, QPolygon) \
- F(QRegion, 72, QRegion) \
- F(QBitmap, 73, QBitmap) \
- F(QCursor, 74, QCursor) \
+ F(QFont, 0x1000, QFont) \
+ F(QPixmap, 0x1001, QPixmap) \
+ F(QBrush, 0x1002, QBrush) \
+ F(QColor, 0x1003, QColor) \
+ F(QPalette, 0x1004, QPalette) \
+ F(QIcon, 0x1005, QIcon) \
+ F(QImage, 0x1006, QImage) \
+ F(QPolygon, 0x1007, QPolygon) \
+ F(QRegion, 0x1008, QRegion) \
+ F(QBitmap, 0x1009, QBitmap) \
+ F(QCursor, 0x100a, QCursor) \
QT_FOR_EACH_STATIC_KEYSEQUENCE_CLASS(F) \
- F(QPen, 76, QPen) \
- F(QTextLength, 77, QTextLength) \
- F(QTextFormat, 78, QTextFormat) \
- F(QTransform, 80, QTransform) \
- F(QMatrix4x4, 81, QMatrix4x4) \
- F(QVector2D, 82, QVector2D) \
- F(QVector3D, 83, QVector3D) \
- F(QVector4D, 84, QVector4D) \
- F(QQuaternion, 85, QQuaternion) \
- F(QPolygonF, 86, QPolygonF) \
- F(QColorSpace, 87, QColorSpace) \
+ F(QPen, 0x100c, QPen) \
+ F(QTextLength, 0x100d, QTextLength) \
+ F(QTextFormat, 0x100e, QTextFormat) \
+ F(QTransform, 0x1010, QTransform) \
+ F(QMatrix4x4, 0x1011, QMatrix4x4) \
+ F(QVector2D, 0x1012, QVector2D) \
+ F(QVector3D, 0x1013, QVector3D) \
+ F(QVector4D, 0x1014, QVector4D) \
+ F(QQuaternion, 0x1015, QQuaternion) \
+ F(QPolygonF, 0x1016, QPolygonF) \
+ F(QColorSpace, 0x1017, QColorSpace) \
#define QT_FOR_EACH_STATIC_WIDGETS_CLASS(F)\
- F(QSizePolicy, 121, QSizePolicy) \
+ F(QSizePolicy, 0x2000, QSizePolicy) \
// F is a tuple: (QMetaType::TypeName, QMetaType::TypeNameID, AliasingType, "RealType")
#define QT_FOR_EACH_STATIC_ALIAS_TYPE(F)\
@@ -214,10 +201,20 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(UInt, -1, uint, "quint32") \
F(LongLong, -1, qlonglong, "qint64") \
F(ULongLong, -1, qulonglong, "quint64") \
+ F(QByteArrayList, -1, QByteArrayList, "QList<QByteArray>") \
+ F(QStringList, -1, QStringList, "QList<QString>") \
+ QT_FOR_EACH_STATIC_VARIANT_ALIAS_TYPE(F)
+
+#ifndef QT_NO_VARIANT
+#define QT_FOR_EACH_STATIC_VARIANT_ALIAS_TYPE(F) \
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(QVariantPair, -1, QVariantPair, "QPair<QVariant,QVariant>") \
+ /**/
+#else
+#define QT_FOR_EACH_STATIC_VARIANT_ALIAS_TYPE(F)
+#endif
#define QT_FOR_EACH_STATIC_TYPE(F)\
QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(F)\
@@ -248,7 +245,6 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QPointer)
class QDataStream;
-class QMetaTypeInterface;
struct QMetaObject;
namespace QtPrivate
@@ -256,120 +252,75 @@ namespace QtPrivate
class QMetaTypeInterface;
-/*!
- This template is used for implicit conversion from type From to type To.
- \internal
-*/
-template<typename From, typename To>
-To convertImplicit(const From& from)
-{
- return from;
-}
-
-#ifndef QT_NO_DEBUG_STREAM
-struct AbstractDebugStreamFunction
-{
- typedef void (*Stream)(const AbstractDebugStreamFunction *, QDebug&, const void *);
- typedef void (*Destroy)(AbstractDebugStreamFunction *);
- explicit AbstractDebugStreamFunction(Stream s = nullptr, Destroy d = nullptr)
- : stream(s), destroy(d) {}
- Q_DISABLE_COPY(AbstractDebugStreamFunction)
- Stream stream;
- Destroy destroy;
-};
+// MSVC is the only supported compiler that includes the type of a variable in
+// its mangled form, so it's not binary-compatible to drop the const in
+// QMetaTypeInterfaceWrapper::metaType for it, which means we must keep the
+// mutable field until Qt 7.
+#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) || !defined(Q_CC_MSVC)
+# define QMTI_MUTABLE
+using NonConstMetaTypeInterface = QMetaTypeInterface;
+#else
+# define QMTI_MUTABLE mutable
+using NonConstMetaTypeInterface = const QMetaTypeInterface;
+#endif
-template<typename T>
-struct BuiltInDebugStreamFunction : public AbstractDebugStreamFunction
+class QMetaTypeInterface
{
- BuiltInDebugStreamFunction()
- : AbstractDebugStreamFunction(stream, destroy) {}
- static void stream(const AbstractDebugStreamFunction *, QDebug& dbg, const void *r)
- {
- const T *rhs = static_cast<const T *>(r);
- operator<<(dbg, *rhs);
- }
+public:
- static void destroy(AbstractDebugStreamFunction *_this)
- {
- delete static_cast<BuiltInDebugStreamFunction *>(_this);
- }
-};
-#endif
+ /* Revision: Can increase if new field are added, or if semantics changes
+ 0: Initial Revision
+ 1: the meaning of the NeedsDestruction flag changed
+ */
+ static inline constexpr ushort CurrentRevision = 1;
-struct AbstractConverterFunction
-{
- typedef bool (*Converter)(const AbstractConverterFunction *, const void *, void*);
- explicit AbstractConverterFunction(Converter c = nullptr)
- : convert(c) {}
- Q_DISABLE_COPY(AbstractConverterFunction)
- Converter convert;
-};
+ ushort revision;
+ ushort alignment;
+ uint size;
+ uint flags;
+ QMTI_MUTABLE QBasicAtomicInt typeId;
-template<typename From, typename To>
-struct ConverterMemberFunction : public AbstractConverterFunction
-{
- explicit ConverterMemberFunction(To(From::*function)() const)
- : AbstractConverterFunction(convert),
- m_function(function) {}
- ~ConverterMemberFunction();
- static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
- {
- const From *f = static_cast<const From *>(in);
- To *t = static_cast<To *>(out);
- const ConverterMemberFunction *_typedThis =
- static_cast<const ConverterMemberFunction *>(_this);
- *t = (f->*_typedThis->m_function)();
- return true;
- }
+ using MetaObjectFn = const QMetaObject *(*)(const QMetaTypeInterface *);
+ MetaObjectFn metaObjectFn;
- To(From::* const m_function)() const;
-};
+ const char *name;
-template<typename From, typename To>
-struct ConverterMemberFunctionOk : public AbstractConverterFunction
-{
- explicit ConverterMemberFunctionOk(To(From::*function)(bool *) const)
- : AbstractConverterFunction(convert),
- m_function(function) {}
- ~ConverterMemberFunctionOk();
- static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
- {
- const From *f = static_cast<const From *>(in);
- To *t = static_cast<To *>(out);
- bool ok = false;
- const ConverterMemberFunctionOk *_typedThis =
- static_cast<const ConverterMemberFunctionOk *>(_this);
- *t = (f->*_typedThis->m_function)(&ok);
- if (!ok)
- *t = To();
- return ok;
- }
+ 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 EqualsFn = bool (*)(const QMetaTypeInterface *, const void *, const void *);
+ EqualsFn equals;
+ using LessThanFn = bool (*)(const QMetaTypeInterface *, const void *, const void *);
+ LessThanFn lessThan;
+ using DebugStreamFn = void (*)(const QMetaTypeInterface *, QDebug &, const void *);
+ DebugStreamFn debugStream;
+ using DataStreamOutFn = void (*)(const QMetaTypeInterface *, QDataStream &, const void *);
+ DataStreamOutFn dataStreamOut;
+ using DataStreamInFn = void (*)(const QMetaTypeInterface *, QDataStream &, void *);
+ DataStreamInFn dataStreamIn;
- To(From::* const m_function)(bool*) const;
+ using LegacyRegisterOp = void (*)();
+ LegacyRegisterOp legacyRegisterOp;
};
+#undef QMTI_MUTABLE
-template<typename From, typename To, typename UnaryFunction>
-struct ConverterFunctor : public AbstractConverterFunction
+/*!
+ This template is used for implicit conversion from type From to type To.
+ \internal
+*/
+template<typename From, typename To>
+To convertImplicit(const From& from)
{
- explicit ConverterFunctor(UnaryFunction function)
- : AbstractConverterFunction(convert),
- m_function(function) {}
- ~ConverterFunctor();
- static bool convert(const AbstractConverterFunction *_this, const void *in, void *out)
- {
- const From *f = static_cast<const From *>(in);
- To *t = static_cast<To *>(out);
- const ConverterFunctor *_typedThis =
- static_cast<const ConverterFunctor *>(_this);
- *t = _typedThis->m_function(*f);
- return true;
- }
-
- UnaryFunction m_function;
-};
+ return from;
+}
template<typename T, bool>
- struct ValueTypeIsMetaType;
+ struct SequentialValueTypeIsMetaType;
template<typename T, bool>
struct AssociativeValueTypeIsMetaType;
template<typename T, bool>
@@ -389,14 +340,14 @@ struct ConverterFunctor : public AbstractConverterFunction
class Q_CORE_EXPORT QMetaType {
public:
-#ifndef Q_CLANG_QDOC
+#ifndef Q_QDOC
// The code that actually gets compiled.
enum Type {
// these are merged with QVariant
QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID)
FirstCoreType = Bool,
- LastCoreType = Char32,
+ LastCoreType = Float16,
FirstGuiType = QFont,
LastGuiType = QColorSpace,
FirstWidgetsType = QSizePolicy,
@@ -406,7 +357,7 @@ public:
QReal = sizeof(qreal) == sizeof(double) ? Double : Float,
UnknownType = 0,
- User = 1024
+ User = 65536
};
#else
// If we are using QDoc it fakes the Type enum looks like this.
@@ -425,128 +376,189 @@ public:
QByteArrayList = 49, QObjectStar = 39, SChar = 40,
Void = 43,
Nullptr = 51,
- QVariantMap = 8, QVariantList = 9, QVariantHash = 28,
+ QVariantMap = 8, QVariantList = 9, QVariantHash = 28, QVariantPair = 58,
QCborSimpleType = 52, QCborValue = 53, QCborArray = 54, QCborMap = 55,
Char16 = 56, Char32 = 57,
+ Int128 = 59, UInt128 = 60, Float128 = 61, BFloat16 = 62, Float16 = 63,
// Gui types
- 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,
- QTransform = 80, QMatrix4x4 = 81, QVector2D = 82,
- QVector3D = 83, QVector4D = 84, QQuaternion = 85, QPolygonF = 86, QColorSpace = 87,
+ QFont = 0x1000, QPixmap = 0x1001, QBrush = 0x1002, QColor = 0x1003, QPalette = 0x1004,
+ QIcon = 0x1005, QImage = 0x1006, QPolygon = 0x1007, QRegion = 0x1008, QBitmap = 0x1009,
+ QCursor = 0x100a, QKeySequence = 0x100b, QPen = 0x100c, QTextLength = 0x100d, QTextFormat = 0x100e,
+ QTransform = 0x1010, QMatrix4x4 = 0x1011, QVector2D = 0x1012,
+ QVector3D = 0x1013, QVector4D = 0x1014, QQuaternion = 0x1015, QPolygonF = 0x1016, QColorSpace = 0x1017,
// Widget types
- QSizePolicy = 121,
- LastCoreType = QCborMap,
- LastGuiType = QColorSpace,
- User = 1024
+ QSizePolicy = 0x2000,
+
+ // Start-point for client-code types:
+ User = 65536
};
#endif
enum TypeFlag {
NeedsConstruction = 0x1,
NeedsDestruction = 0x2,
- MovableType = 0x4,
+ RelocatableType = 0x4,
+#if QT_DEPRECATED_SINCE(6, 0)
+ MovableType Q_DECL_ENUMERATOR_DEPRECATED_X("Use RelocatableType instead.") = RelocatableType,
+#endif
PointerToQObject = 0x8,
IsEnumeration = 0x10,
SharedPointerToQObject = 0x20,
WeakPointerToQObject = 0x40,
TrackingPointerToQObject = 0x80,
- WasDeclaredAsMetaType = 0x100,
+ IsUnsignedEnumeration = 0x100,
IsGadget = 0x200,
PointerToGadget = 0x400,
IsPointer = 0x800,
+ IsQmlList =0x1000, // used in the QML engine to recognize QQmlListProperty<T> and list<T>
+ IsConst = 0x2000,
+ // since 6.5:
+ NeedsCopyConstruction = 0x4000,
+ NeedsMoveConstruction = 0x8000,
};
Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
- typedef void (*SaveOperator)(QDataStream &, const void *);
- typedef void (*LoadOperator)(QDataStream &, void *);
-#ifndef QT_NO_DATASTREAM
- static void registerStreamOperators(const char *typeName, SaveOperator saveOp,
- LoadOperator loadOp);
- static void registerStreamOperators(int type, SaveOperator saveOp,
- LoadOperator loadOp);
-#endif
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);
- static const char *typeName(int type);
- static int sizeOf(int type);
- static TypeFlags typeFlags(int type);
- static const QMetaObject *metaObjectForType(int type);
- static bool isRegistered(int type);
- static void *create(int type, const void *copy = nullptr);
- static void destroy(int type, void *data);
- static void *construct(int type, void *where, const void *copy);
- static void destruct(int type, void *where);
-
-#ifndef QT_NO_DATASTREAM
- static bool save(QDataStream &stream, int type, const void *data);
- static bool load(QDataStream &stream, int type, void *data);
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_VERSION_6_0
+ static int type(const char *typeName)
+ { return QMetaType::fromName(typeName).id(); }
+ QT_DEPRECATED_VERSION_6_0
+ static int type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName)
+ { return QMetaType::fromName(typeName).id(); }
+ QT_DEPRECATED_VERSION_6_0
+ static const char *typeName(int type)
+ { return QMetaType(type).name(); }
+ QT_DEPRECATED_VERSION_6_0
+ static int sizeOf(int type)
+ { return int(QMetaType(type).sizeOf()); }
+ QT_DEPRECATED_VERSION_6_0
+ static TypeFlags typeFlags(int type)
+ { return QMetaType(type).flags(); }
+ QT_DEPRECATED_VERSION_6_0
+ static const QMetaObject *metaObjectForType(int type)
+ { return QMetaType(type).metaObject(); }
+ QT_DEPRECATED_VERSION_6_0
+ static void *create(int type, const void *copy = nullptr)
+ { return QMetaType(type).create(copy); }
+ QT_DEPRECATED_VERSION_6_0
+ static void destroy(int type, void *data)
+ { return QMetaType(type).destroy(data); }
+ QT_DEPRECATED_VERSION_6_0
+ static void *construct(int type, void *where, const void *copy)
+ { return QMetaType(type).construct(where, copy); }
+ QT_DEPRECATED_VERSION_6_0
+ static void destruct(int type, void *where)
+ { return QMetaType(type).destruct(where); }
#endif
+ static bool isRegistered(int type);
explicit QMetaType(int type);
- explicit QMetaType(QtPrivate::QMetaTypeInterface *d);
- constexpr QMetaType() : d_ptr(nullptr) {}
- ~QMetaType();
- QMetaType(const QMetaType &other) : QMetaType(other.d_ptr) {}
- 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;
- }
+ explicit constexpr QMetaType(const QtPrivate::QMetaTypeInterface *d) : d_ptr(d) {}
+ constexpr QMetaType() = default;
bool isValid() const;
bool isRegistered() const;
+ void registerType() const
+ {
+ // "register" is a reserved keyword
+ registerHelper();
+ }
+#if QT_CORE_REMOVED_SINCE(6, 1) || defined(Q_QDOC)
int id() const;
- int sizeOf() const;
- int alignOf() const;
- TypeFlags flags() const;
- const QMetaObject *metaObject() const;
- QT_PREPEND_NAMESPACE(QByteArray) name() const;
+#else
+ // ### Qt 7: Remove traces of out of line version
+ // unused int parameter is used to avoid ODR violation
+ int id(int = 0) const
+ {
+ // keep in sync with the version in removed_api.cpp
+ return registerHelper();
+ }
+#endif
+ constexpr qsizetype sizeOf() const;
+ constexpr qsizetype alignOf() const;
+ constexpr TypeFlags flags() const;
+ constexpr const QMetaObject *metaObject() const;
+ constexpr const char *name() 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;
- std::optional<int> compare(const void *lhs, const void *rhs) const;
+ QPartialOrdering compare(const void *lhs, const void *rhs) const;
bool equals(const void *lhs, const void *rhs) const;
+ bool isDefaultConstructible() const noexcept { return d_ptr && isDefaultConstructible(d_ptr); }
+ bool isCopyConstructible() const noexcept { return d_ptr && isCopyConstructible(d_ptr); }
+ bool isMoveConstructible() const noexcept { return d_ptr && isMoveConstructible(d_ptr); }
+ bool isDestructible() const noexcept { return d_ptr && isDestructible(d_ptr); }
bool isEqualityComparable() const;
bool isOrdered() const;
- template<typename T>
- static QMetaType fromType();
+#ifndef QT_NO_DATASTREAM
+ bool save(QDataStream &stream, const void *data) const;
+ bool load(QDataStream &stream, void *data) const;
+ bool hasRegisteredDataStreamOperators() const;
- 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); }
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_VERSION_6_0
+ static bool save(QDataStream &stream, int type, const void *data)
+ { return QMetaType(type).save(stream, data); }
+ QT_DEPRECATED_VERSION_6_0
+ static bool load(QDataStream &stream, int type, void *data)
+ { return QMetaType(type).load(stream, data); }
+#endif
+#endif
-public:
+ QMetaType underlyingType() const;
-#ifndef QT_NO_DEBUG_STREAM
template<typename T>
- static bool registerDebugStreamOperator()
- {
- static_assert((!QMetaTypeId2<T>::IsBuiltIn),
- "QMetaType::registerDebugStreamOperator: The type must be a custom type.");
+ constexpr static QMetaType fromType();
+ static QMetaType fromName(QByteArrayView name);
- const int typeId = qMetaTypeId<T>();
- static const QtPrivate::BuiltInDebugStreamFunction<T> f;
- return registerDebugStreamOperatorFunction(&f, typeId);
+ friend bool operator==(QMetaType a, QMetaType b)
+ {
+ if (a.d_ptr == b.d_ptr)
+ return true;
+ if (!a.d_ptr || !b.d_ptr)
+ return false; // one type is undefined, the other is defined
+ // avoid id call if we already have the id
+ const int aId = a.id();
+ const int bId = b.id();
+ return aId == bId;
}
+ friend bool operator!=(QMetaType a, QMetaType b) { return !(a == b); }
+
+#ifndef QT_NO_DEBUG_STREAM
+private:
+ friend Q_CORE_EXPORT QDebug operator<<(QDebug d, QMetaType m);
+public:
+ bool debugStream(QDebug& dbg, const void *rhs);
+ bool hasRegisteredDebugStreamOperator() const;
+
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_VERSION_6_0
+ static bool debugStream(QDebug& dbg, const void *rhs, int typeId)
+ { return QMetaType(typeId).debugStream(dbg, rhs); }
template<typename T>
+ QT_DEPRECATED_VERSION_6_0
static bool hasRegisteredDebugStreamOperator()
- {
- return hasRegisteredDebugStreamOperator(qMetaTypeId<T>());
- }
- static bool hasRegisteredDebugStreamOperator(int typeId);
+ { return QMetaType::fromType<T>().hasRegisteredDebugStreamOperator(); }
+ QT_DEPRECATED_VERSION_6_0
+ static bool hasRegisteredDebugStreamOperator(int typeId)
+ { return QMetaType(typeId).hasRegisteredDebugStreamOperator(); }
+#endif
#endif
+ // type erased converter function
+ using ConverterFunction = std::function<bool(const void *src, void *target)>;
+
+ // type erased mutable view, primarily for containers
+ using MutableViewFunction = std::function<bool(void *src, void *target)>;
+
// implicit conversion supported like double -> float
template<typename From, typename To>
static bool registerConverter()
@@ -554,14 +566,6 @@ public:
return registerConverter<From, To>(QtPrivate::convertImplicit<From, To>);
}
-#ifdef Q_CLANG_QDOC
- template<typename MemberFunction, int>
- static bool registerConverter(MemberFunction function);
- template<typename MemberFunctionOk, char>
- static bool registerConverter(MemberFunctionOk function);
- template<typename UnaryFunction>
- static bool registerConverter(UnaryFunction function);
-#else
// member function as in "QString QFont::toString() const"
template<typename From, typename To>
static bool registerConverter(To(From::*function)() const)
@@ -569,10 +573,33 @@ public:
static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
"QMetaType::registerConverter: At least one of the types must be a custom type.");
- const int fromTypeId = qMetaTypeId<From>();
- const int toTypeId = qMetaTypeId<To>();
- static const QtPrivate::ConverterMemberFunction<From, To> f(function);
- return registerConverterFunction(&f, fromTypeId, toTypeId);
+ const QMetaType fromType = QMetaType::fromType<From>();
+ const QMetaType toType = QMetaType::fromType<To>();
+ auto converter = [function](const void *from, void *to) -> bool {
+ const From *f = static_cast<const From *>(from);
+ To *t = static_cast<To *>(to);
+ *t = (f->*function)();
+ return true;
+ };
+ return registerConverterImpl<From, To>(converter, fromType, toType);
+ }
+
+ // member function
+ template<typename From, typename To>
+ static bool registerMutableView(To(From::*function)())
+ {
+ static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
+ "QMetaType::registerMutableView: At least one of the types must be a custom type.");
+
+ const QMetaType fromType = QMetaType::fromType<From>();
+ const QMetaType toType = QMetaType::fromType<To>();
+ auto view = [function](void *from, void *to) -> bool {
+ From *f = static_cast<From *>(from);
+ To *t = static_cast<To *>(to);
+ *t = (f->*function)();
+ return true;
+ };
+ return registerMutableViewImpl<From, To>(view, fromType, toType);
}
// member function as in "double QString::toDouble(bool *ok = nullptr) const"
@@ -582,10 +609,18 @@ public:
static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
"QMetaType::registerConverter: At least one of the types must be a custom type.");
- const int fromTypeId = qMetaTypeId<From>();
- const int toTypeId = qMetaTypeId<To>();
- static const QtPrivate::ConverterMemberFunctionOk<From, To> f(function);
- return registerConverterFunction(&f, fromTypeId, toTypeId);
+ const QMetaType fromType = QMetaType::fromType<From>();
+ const QMetaType toType = QMetaType::fromType<To>();
+ auto converter = [function](const void *from, void *to) -> bool {
+ const From *f = static_cast<const From *>(from);
+ To *t = static_cast<To *>(to);
+ bool result = true;
+ *t = (f->*function)(&result);
+ if (!result)
+ *t = To();
+ return result;
+ };
+ return registerConverterImpl<From, To>(converter, fromType, toType);
}
// functor or function pointer
@@ -595,26 +630,97 @@ public:
static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
"QMetaType::registerConverter: At least one of the types must be a custom type.");
- const int fromTypeId = qMetaTypeId<From>();
- const int toTypeId = qMetaTypeId<To>();
- static const QtPrivate::ConverterFunctor<From, To, UnaryFunction> f(function);
- return registerConverterFunction(&f, fromTypeId, toTypeId);
+ const QMetaType fromType = QMetaType::fromType<From>();
+ const QMetaType toType = QMetaType::fromType<To>();
+ auto converter = [function = std::move(function)](const void *from, void *to) -> bool {
+ const From *f = static_cast<const From *>(from);
+ To *t = static_cast<To *>(to);
+ auto &&r = function(*f);
+ if constexpr (std::is_same_v<q20::remove_cvref_t<decltype(r)>, std::optional<To>>) {
+ if (!r)
+ return false;
+ *t = *std::forward<decltype(r)>(r);
+ } else {
+ *t = std::forward<decltype(r)>(r);
+ }
+ return true;
+ };
+ return registerConverterImpl<From, To>(std::move(converter), fromType, toType);
+ }
+
+ // functor or function pointer
+ template<typename From, typename To, typename UnaryFunction>
+ static bool registerMutableView(UnaryFunction function)
+ {
+ static_assert((!QMetaTypeId2<To>::IsBuiltIn || !QMetaTypeId2<From>::IsBuiltIn),
+ "QMetaType::registerMutableView: At least one of the types must be a custom type.");
+
+ const QMetaType fromType = QMetaType::fromType<From>();
+ const QMetaType toType = QMetaType::fromType<To>();
+ auto view = [function = std::move(function)](void *from, void *to) -> bool {
+ From *f = static_cast<From *>(from);
+ To *t = static_cast<To *>(to);
+ *t = function(*f);
+ return true;
+ };
+ return registerMutableViewImpl<From, To>(std::move(view), fromType, toType);
}
-#endif
- static bool convert(const void *from, int fromTypeId, void *to, int toTypeId);
+private:
+ template<typename From, typename To>
+ static bool registerConverterImpl(ConverterFunction converter, QMetaType fromType, QMetaType toType)
+ {
+ if (registerConverterFunction(std::move(converter), fromType, toType)) {
+ static const auto unregister = qScopeGuard([=] {
+ unregisterConverterFunction(fromType, toType);
+ });
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ template<typename From, typename To>
+ static bool registerMutableViewImpl(MutableViewFunction view, QMetaType fromType, QMetaType toType)
+ {
+ if (registerMutableViewFunction(std::move(view), fromType, toType)) {
+ static const auto unregister = qScopeGuard([=] {
+ unregisterMutableViewFunction(fromType, toType);
+ });
+ return true;
+ } else {
+ return false;
+ }
+ }
+public:
+
+ static bool convert(QMetaType fromType, const void *from, QMetaType toType, void *to);
+ static bool canConvert(QMetaType fromType, QMetaType toType);
+
+ static bool view(QMetaType fromType, void *from, QMetaType toType, void *to);
+ static bool canView(QMetaType fromType, QMetaType toType);
#if QT_DEPRECATED_SINCE(6, 0)
QT_DEPRECATED_VERSION_6_0
+ static bool convert(const void *from, int fromTypeId, void *to, int toTypeId)
+ { return convert(QMetaType(fromTypeId), from, QMetaType(toTypeId), to); }
+ QT_DEPRECATED_VERSION_6_0
static bool compare(const void *lhs, const void *rhs, int typeId, int *result)
{
QMetaType t(typeId);
auto c = t.compare(lhs, rhs);
- if (!c) {
+ if (c == QPartialOrdering::Unordered) {
*result = 0;
return false;
+ } else if (c == QPartialOrdering::Less) {
+ *result = -1;
+ return true;
+ } else if (c == QPartialOrdering::Equivalent) {
+ *result = 0;
+ return true;
+ } else {
+ *result = 1;
+ return true;
}
- *result = *c;
- return true;
}
QT_DEPRECATED_VERSION_6_0
static bool equals(const void *lhs, const void *rhs, int typeId, int *result)
@@ -627,706 +733,122 @@ public:
}
#endif
- static bool debugStream(QDebug& dbg, const void *rhs, int typeId);
-
template<typename From, typename To>
static bool hasRegisteredConverterFunction()
{
- return hasRegisteredConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
+ return hasRegisteredConverterFunction(
+ QMetaType::fromType<From>(), QMetaType::fromType<To>());
}
- static bool hasRegisteredConverterFunction(int fromTypeId, int toTypeId);
+ static bool hasRegisteredConverterFunction(QMetaType fromType, QMetaType toType);
-#ifndef QT_NO_DEBUG_STREAM
- static bool registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f, int type);
-#endif
+ template<typename From, typename To>
+ static bool hasRegisteredMutableViewFunction()
+ {
+ return hasRegisteredMutableViewFunction(
+ QMetaType::fromType<From>(), QMetaType::fromType<To>());
+ }
+
+ static bool hasRegisteredMutableViewFunction(QMetaType fromType, QMetaType toType);
-#ifndef Q_CLANG_QDOC
- template<typename, bool> friend struct QtPrivate::ValueTypeIsMetaType;
- template<typename, typename> friend struct QtPrivate::ConverterMemberFunction;
- template<typename, typename> friend struct QtPrivate::ConverterMemberFunctionOk;
- template<typename, typename, typename> friend struct QtPrivate::ConverterFunctor;
+#ifndef Q_QDOC
+ template<typename, bool> friend struct QtPrivate::SequentialValueTypeIsMetaType;
template<typename, bool> friend struct QtPrivate::AssociativeValueTypeIsMetaType;
template<typename, bool> friend struct QtPrivate::IsMetaTypePair;
template<typename, typename> friend struct QtPrivate::MetaTypeSmartPointerHelper;
#endif
- static bool registerConverterFunction(const QtPrivate::AbstractConverterFunction *f, int from, int to);
- static void unregisterConverterFunction(int from, int to);
-private:
- friend class QVariant;
- QtPrivate::QMetaTypeInterface *d_ptr = nullptr;
-};
-
-#undef QT_DEFINE_METATYPE_ID
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags)
+ static bool registerConverterFunction(const ConverterFunction &f, QMetaType from, QMetaType to);
+ static void unregisterConverterFunction(QMetaType from, QMetaType to);
-namespace QtPrivate {
+ static bool registerMutableViewFunction(const MutableViewFunction &f, QMetaType from, QMetaType to);
+ static void unregisterMutableViewFunction(QMetaType from, QMetaType to);
-template<typename From, typename To>
-ConverterMemberFunction<From, To>::~ConverterMemberFunction()
-{
- QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
-}
-template<typename From, typename To>
-ConverterMemberFunctionOk<From, To>::~ConverterMemberFunctionOk()
-{
- QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
-}
-template<typename From, typename To, typename UnaryFunction>
-ConverterFunctor<From, To, UnaryFunction>::~ConverterFunctor()
-{
- QMetaType::unregisterConverterFunction(qMetaTypeId<From>(), qMetaTypeId<To>());
-}
-
-}
+ static void unregisterMetaType(QMetaType type);
-#define QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(C, F) \
- } \
- Q_DECLARE_TYPEINFO(QtMetaTypePrivate:: C, (F)); \
- namespace QtMetaTypePrivate {
-
-namespace QtMetaTypePrivate {
-template <typename T, bool Accepted = true>
-struct QMetaTypeFunctionHelper {
- static void Destruct(void *t)
- {
- Q_UNUSED(t); // Silence MSVC that warns for POD types.
- static_cast<T*>(t)->~T();
- }
-
- static void *Construct(void *where, const void *t)
- {
- if (t)
- return new (where) T(*static_cast<const T*>(t));
- return new (where) T;
- }
-#ifndef QT_NO_DATASTREAM
- static void Save(QDataStream &stream, const void *t)
- {
- stream << *static_cast<const T*>(t);
- }
-
- static void Load(QDataStream &stream, void *t)
- {
- stream >> *static_cast<T*>(t);
- }
-#endif // QT_NO_DATASTREAM
-};
-
-template <typename T>
-struct QMetaTypeFunctionHelper<T, /* Accepted */ false> {
- static void Destruct(void *) {}
- static void *Construct(void *, const void *) { return nullptr; }
-#ifndef QT_NO_DATASTREAM
- static void Save(QDataStream &, const void *) {}
- static void Load(QDataStream &, void *) {}
-#endif // QT_NO_DATASTREAM
-};
-template <>
-struct QMetaTypeFunctionHelper<void, /* Accepted */ true>
- : public QMetaTypeFunctionHelper<void, /* Accepted */ false>
-{};
-
-struct VariantData
-{
- VariantData(const int metaTypeId_,
- const void *data_,
- const uint flags_)
- : metaTypeId(metaTypeId_)
- , data(data_)
- , flags(flags_)
- {
- }
- VariantData(const VariantData &other)
- : metaTypeId(other.metaTypeId), data(other.data), flags(other.flags){}
- const int metaTypeId;
- const void *data;
- const uint flags;
-private:
- // copy constructor allowed to be implicit to silence level 4 warning from MSVC
- VariantData &operator=(const VariantData &) = delete;
-};
-
-template<typename const_iterator>
-struct IteratorOwnerCommon
-{
- static void assign(void **ptr, const_iterator iterator)
- {
- *ptr = new const_iterator(iterator);
- }
- static void assign(void **ptr, void * const * src)
- {
- *ptr = new const_iterator(*static_cast<const_iterator*>(*src));
- }
-
- static void advance(void **iterator, int step)
- {
- const_iterator &it = *static_cast<const_iterator*>(*iterator);
- std::advance(it, step);
- }
-
- static void destroy(void **ptr)
- {
- delete static_cast<const_iterator*>(*ptr);
- }
-
- static bool equal(void * const *it, void * const *other)
- {
- return *static_cast<const_iterator*>(*it) == *static_cast<const_iterator*>(*other);
- }
-};
-
-template<typename const_iterator>
-struct IteratorOwner : IteratorOwnerCommon<const_iterator>
-{
- static const void *getData(void * const *iterator)
- {
- return &**static_cast<const_iterator*>(*iterator);
- }
-
- static const void *getData(const_iterator it)
- {
- return &*it;
- }
-};
-
-struct Q_CORE_EXPORT VectorBoolElements
-{
- static const bool true_element;
- static const bool false_element;
-};
-
-template<>
-struct IteratorOwner<std::vector<bool>::const_iterator> : IteratorOwnerCommon<std::vector<bool>::const_iterator>
-{
-public:
- static const void *getData(void * const *iterator)
- {
- return **static_cast<std::vector<bool>::const_iterator*>(*iterator) ?
- &VectorBoolElements::true_element : &VectorBoolElements::false_element;
- }
-
- static const void *getData(const std::vector<bool>::const_iterator& it)
- {
- return *it ? &VectorBoolElements::true_element : &VectorBoolElements::false_element;
- }
-};
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ const QtPrivate::QMetaTypeInterface *iface() { return d_ptr; }
+#endif
+ const QtPrivate::QMetaTypeInterface *iface() const { return d_ptr; }
-template<typename value_type>
-struct IteratorOwner<const value_type*>
-{
private:
- // We need to disable typed overloads of assign() and getData() if the value_type
- // is void* to avoid overloads conflicts. We do it by injecting unaccessible Dummy
- // type as part of the overload signature.
- struct Dummy {};
- typedef typename std::conditional<std::is_same<value_type, void*>::value, Dummy, value_type>::type value_type_OR_Dummy;
-public:
- static void assign(void **ptr, const value_type_OR_Dummy *iterator )
- {
- *ptr = const_cast<value_type*>(iterator);
- }
- static void assign(void **ptr, void * const * src)
- {
- *ptr = static_cast<value_type*>(*src);
- }
+ static bool isDefaultConstructible(const QtPrivate::QMetaTypeInterface *) noexcept Q_DECL_PURE_FUNCTION;
+ static bool isCopyConstructible(const QtPrivate::QMetaTypeInterface *) noexcept Q_DECL_PURE_FUNCTION;
+ static bool isMoveConstructible(const QtPrivate::QMetaTypeInterface *) noexcept Q_DECL_PURE_FUNCTION;
+ static bool isDestructible(const QtPrivate::QMetaTypeInterface *) noexcept Q_DECL_PURE_FUNCTION;
- static void advance(void **iterator, int step)
- {
- value_type *it = static_cast<value_type*>(*iterator);
- std::advance(it, step);
- *iterator = it;
- }
-
- static void destroy(void **)
- {
- }
-
- static const void *getData(void * const *iterator)
- {
- return *iterator;
- }
-
- static const void *getData(const value_type_OR_Dummy *it)
- {
- return it;
- }
-
- static bool equal(void * const *it, void * const *other)
- {
- return static_cast<value_type*>(*it) == static_cast<value_type*>(*other);
+#if QT_CORE_REMOVED_SINCE(6, 5)
+ 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;
}
-};
-
-enum IteratorCapability
-{
- ForwardCapability = 1,
- BiDirectionalCapability = 2,
- RandomAccessCapability = 4
-};
-
-enum ContainerCapability
-{
- ContainerIsAppendable = 1
-};
-
-template<typename Container, typename T = void>
-struct ContainerCapabilitiesImpl
-{
- enum {ContainerCapabilities = 0};
- using appendFunction = void(*)(const void *container, const void *newElement);
- static constexpr const appendFunction appendImpl = nullptr;
-};
-
-template<typename Container>
-struct ContainerCapabilitiesImpl<Container, decltype(std::declval<Container>().push_back(std::declval<typename Container::value_type>()))>
-{
- enum {ContainerCapabilities = ContainerIsAppendable};
-
- // The code below invokes undefined behavior if and only if the pointer passed into QSequentialIterableImpl
- // pointed to a const object to begin with
- static void appendImpl(const void *container, const void *value)
- { static_cast<Container *>(const_cast<void *>(container))->push_back(*static_cast<const typename Container::value_type *>(value)); }
-};
-
-namespace QtPrivate {
-namespace ContainerCapabilitiesMetaProgrammingHelper {
- template<typename... Ts>
- using void_t = void;
-}
-}
-
-template<typename Container>
-struct ContainerCapabilitiesImpl<Container, QtPrivate::ContainerCapabilitiesMetaProgrammingHelper::void_t<decltype(std::declval<Container>().insert(std::declval<typename Container::value_type>())), decltype(std::declval<typename Container::value_type>() == std::declval<typename Container::value_type>())>>
-{
- enum {ContainerCapabilities = ContainerIsAppendable};
-
- // The code below invokes undefined behavior if and only if the pointer passed into QSequentialIterableImpl
- // pointed to a const object to begin with
- static void appendImpl(const void *container, const void *value)
- { static_cast<Container *>(const_cast<void *>(container))->insert(*static_cast<const typename Container::value_type *>(value)); }
-};
-template<typename T, typename Category = typename std::iterator_traits<typename T::const_iterator>::iterator_category>
-struct CapabilitiesImpl;
+ friend int qRegisterMetaType(QMetaType meta);
-template<typename T>
-struct CapabilitiesImpl<T, std::forward_iterator_tag>
-{ enum { IteratorCapabilities = ForwardCapability }; };
-template<typename T>
-struct CapabilitiesImpl<T, std::bidirectional_iterator_tag>
-{ enum { IteratorCapabilities = BiDirectionalCapability | ForwardCapability }; };
-template<typename T>
-struct CapabilitiesImpl<T, std::random_access_iterator_tag>
-{ enum { IteratorCapabilities = RandomAccessCapability | BiDirectionalCapability | ForwardCapability }; };
-
-template<typename T>
-struct ContainerAPI : CapabilitiesImpl<T>
-{
- static int size(const T *t) { return int(std::distance(t->begin(), t->end())); }
+ friend class QVariant;
+ const QtPrivate::QMetaTypeInterface *d_ptr = nullptr;
};
-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<std::vector<T> > : CapabilitiesImpl<std::vector<T> >
-{ static int size(const std::vector<T> *t) { return int(t->size()); } };
-
-template<typename T>
-struct ContainerAPI<std::list<T> > : CapabilitiesImpl<std::list<T> >
-{ static int size(const std::list<T> *t) { return int(t->size()); } };
-
-/*
- revision 0: _iteratorCapabilities is simply a uint, where the bits at _revision were never set
- revision 1: _iteratorCapabilties is treated as a bitfield, the remaining bits are used to introduce
- _revision, _containerCapabilities and _unused. The latter contains 21 bits that are
- not used yet
-*/
-class QSequentialIterableImpl
-{
-public:
- const void * _iterable;
- void *_iterator;
- int _metaType_id;
- uint _metaType_flags;
- uint _iteratorCapabilities;
- // Iterator capabilities looks actually like
- // uint _iteratorCapabilities:4;
- // uint _revision:3;
- // uint _containerCapabilities:4;
- // uint _unused:21;
- typedef int(*sizeFunc)(const void *p);
- typedef const void * (*atFunc)(const void *p, int);
- typedef void (*moveIteratorFunc)(const void *p, void **);
- enum Position { ToBegin, ToEnd };
- typedef void (*moveIteratorFunc2)(const void *p, void **, Position position);
- typedef void (*advanceFunc)(void **p, int);
- typedef VariantData (*getFunc)( void * const *p, int metaTypeId, uint flags);
- typedef void (*destroyIterFunc)(void **p);
- typedef bool (*equalIterFunc)(void * const *p, void * const *other);
- typedef void (*copyIterFunc)(void **, void * const *);
- typedef void(*appendFunction)(const void *container, const void *newElement);
-
- IteratorCapability iteratorCapabilities() {return static_cast<IteratorCapability>(_iteratorCapabilities & 0xF);}
- uint revision() {return _iteratorCapabilities >> 4 & 0x7;}
- uint containerCapabilities() {return _iteratorCapabilities >> 7 & 0xF;}
-
- sizeFunc _size;
- atFunc _at;
- union {
- moveIteratorFunc _moveToBegin;
- moveIteratorFunc2 _moveTo;
- };
- union {
- moveIteratorFunc _moveToEnd;
- appendFunction _append;
- };
- advanceFunc _advance;
- getFunc _get;
- destroyIterFunc _destroyIter;
- equalIterFunc _equalIter;
- copyIterFunc _copyIter;
-
- template<class T>
- static int sizeImpl(const void *p)
- { return ContainerAPI<T>::size(static_cast<const T*>(p)); }
-
- template<class T>
- static const void* atImpl(const void *p, int idx)
- {
- typename T::const_iterator i = static_cast<const T*>(p)->begin();
- std::advance(i, idx);
- return IteratorOwner<typename T::const_iterator>::getData(i);
- }
-
- template<class T>
- static void moveToBeginImpl(const void *container, void **iterator)
- { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->begin()); }
-
- template<class T>
- static void moveToEndImpl(const void *container, void **iterator)
- { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->end()); }
-
- template<class Container>
- static void moveToImpl(const void *container, void **iterator, Position position)
- {
- if (position == ToBegin)
- moveToBeginImpl<Container>(container, iterator);
- else
- moveToEndImpl<Container>(container, iterator);
- }
-
- template<class T>
- static VariantData getImpl(void * const *iterator, int metaTypeId, uint flags)
- { return VariantData(metaTypeId, IteratorOwner<typename T::const_iterator>::getData(iterator), flags); }
-
-public:
- template<class T> QSequentialIterableImpl(const T*p)
- : _iterable(p)
- , _iterator(nullptr)
- , _metaType_id(qMetaTypeId<typename T::value_type>())
- , _metaType_flags(QTypeInfo<typename T::value_type>::isPointer)
- , _iteratorCapabilities(ContainerAPI<T>::IteratorCapabilities | (1 << 4) | (ContainerCapabilitiesImpl<T>::ContainerCapabilities << (4+3)))
- , _size(sizeImpl<T>)
- , _at(atImpl<T>)
- , _moveTo(moveToImpl<T>)
- , _append(ContainerCapabilitiesImpl<T>::appendImpl)
- , _advance(IteratorOwner<typename T::const_iterator>::advance)
- , _get(getImpl<T>)
- , _destroyIter(IteratorOwner<typename T::const_iterator>::destroy)
- , _equalIter(IteratorOwner<typename T::const_iterator>::equal)
- , _copyIter(IteratorOwner<typename T::const_iterator>::assign)
- {
- }
-
- QSequentialIterableImpl()
- : _iterable(nullptr)
- , _iterator(nullptr)
- , _metaType_id(QMetaType::UnknownType)
- , _metaType_flags(0)
- , _iteratorCapabilities(0 | (1 << 4) ) // no iterator capabilities, revision 1
- , _size(nullptr)
- , _at(nullptr)
- , _moveToBegin(nullptr)
- , _moveToEnd(nullptr)
- , _advance(nullptr)
- , _get(nullptr)
- , _destroyIter(nullptr)
- , _equalIter(nullptr)
- , _copyIter(nullptr)
- {
- }
-
- inline void moveToBegin() {
- if (revision() == 0)
- _moveToBegin(_iterable, &_iterator);
- else
- _moveTo(_iterable, &_iterator, ToBegin);
- }
- inline void moveToEnd() {
- if (revision() == 0)
- _moveToEnd(_iterable, &_iterator);
- else
- _moveTo(_iterable, &_iterator, ToEnd);
- }
- inline bool equal(const QSequentialIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); }
- inline QSequentialIterableImpl &advance(int i) {
- Q_ASSERT(i > 0 || _iteratorCapabilities & BiDirectionalCapability);
- _advance(&_iterator, i);
- return *this;
- }
-
- inline void append(const void *newElement) {
- if (containerCapabilities() & ContainerIsAppendable)
- _append(_iterable, newElement);
- }
-
- inline VariantData getCurrent() const { return _get(&_iterator, _metaType_id, _metaType_flags); }
-
- VariantData at(int idx) const
- { return VariantData(_metaType_id, _at(_iterable, idx), _metaType_flags); }
+#undef QT_DEFINE_METATYPE_ID
- int size() const { Q_ASSERT(_iterable); return _size(_iterable); }
+Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaType::TypeFlags)
- inline void destroyIter() { _destroyIter(&_iterator); }
+#define QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(C, F) \
+ } \
+ Q_DECLARE_TYPEINFO(QtMetaTypePrivate:: C, (F)); \
+ namespace QtMetaTypePrivate {
- void copy(const QSequentialIterableImpl &other)
- {
- *this = other;
- _copyIter(&_iterator, &other._iterator);
- }
-};
-QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QSequentialIterableImpl, Q_MOVABLE_TYPE)
-
-template<typename From>
-struct QSequentialIterableConvertFunctor
-{
- QSequentialIterableImpl operator()(const From &f) const
- {
- return QSequentialIterableImpl(&f);
- }
-};
-}
namespace QtMetaTypePrivate {
-template<typename T, bool = std::is_same<typename T::const_iterator::value_type, typename T::mapped_type>::value>
-struct AssociativeContainerAccessor
-{
- static const typename T::key_type& getKey(const typename T::const_iterator &it)
- {
- return it.key();
- }
-
- static const typename T::mapped_type& getValue(const typename T::const_iterator &it)
- {
- return it.value();
- }
-};
-
-template<typename T, bool = std::is_same<typename T::const_iterator::value_type, std::pair<const typename T::key_type, typename T::mapped_type> >::value>
-struct StlStyleAssociativeContainerAccessor;
-
-template<typename T>
-struct StlStyleAssociativeContainerAccessor<T, true>
-{
- static const typename T::key_type& getKey(const typename T::const_iterator &it)
- {
- return it->first;
- }
-
- static const typename T::mapped_type& getValue(const typename T::const_iterator &it)
- {
- return it->second;
- }
-};
-
-template<typename T>
-struct AssociativeContainerAccessor<T, false> : public StlStyleAssociativeContainerAccessor<T>
-{
-};
-
-class QAssociativeIterableImpl
-{
-public:
- const void *_iterable;
- void *_iterator;
- int _metaType_id_key;
- uint _metaType_flags_key;
- int _metaType_id_value;
- uint _metaType_flags_value;
- typedef int(*sizeFunc)(const void *p);
- typedef void (*findFunc)(const void *container, const void *p, void **iterator);
- typedef void (*beginFunc)(const void *p, void **);
- typedef void (*advanceFunc)(void **p, int);
- typedef VariantData (*getFunc)(void * const *p, int metaTypeId, uint flags);
- typedef void (*destroyIterFunc)(void **p);
- typedef bool (*equalIterFunc)(void * const *p, void * const *other);
- typedef void (*copyIterFunc)(void **, void * const *);
-
- sizeFunc _size;
- findFunc _find;
- beginFunc _begin;
- beginFunc _end;
- advanceFunc _advance;
- getFunc _getKey;
- getFunc _getValue;
- destroyIterFunc _destroyIter;
- equalIterFunc _equalIter;
- copyIterFunc _copyIter;
-
- template<class T>
- static int sizeImpl(const void *p)
- { return int(std::distance(static_cast<const T*>(p)->begin(),
- static_cast<const T*>(p)->end())); }
-
- template<class T>
- static void findImpl(const void *container, const void *p, void **iterator)
- { IteratorOwner<typename T::const_iterator>::assign(iterator,
- static_cast<const T*>(container)->find(*static_cast<const typename T::key_type*>(p))); }
-
- template<class T>
- static void advanceImpl(void **p, int step)
- { std::advance(*static_cast<typename T::const_iterator*>(*p), step); }
-
- template<class T>
- static void beginImpl(const void *container, void **iterator)
- { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->begin()); }
-
- template<class T>
- static void endImpl(const void *container, void **iterator)
- { IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->end()); }
-
- template<class T>
- static VariantData getKeyImpl(void * const *iterator, int metaTypeId, uint flags)
- { return VariantData(metaTypeId, &AssociativeContainerAccessor<T>::getKey(*static_cast<typename T::const_iterator*>(*iterator)), flags); }
-
- template<class T>
- static VariantData getValueImpl(void * const *iterator, int metaTypeId, uint flags)
- { return VariantData(metaTypeId, &AssociativeContainerAccessor<T>::getValue(*static_cast<typename T::const_iterator*>(*iterator)), flags); }
-
-public:
- template<class T> QAssociativeIterableImpl(const T*p)
- : _iterable(p)
- , _iterator(nullptr)
- , _metaType_id_key(qMetaTypeId<typename T::key_type>())
- , _metaType_flags_key(QTypeInfo<typename T::key_type>::isPointer)
- , _metaType_id_value(qMetaTypeId<typename T::mapped_type>())
- , _metaType_flags_value(QTypeInfo<typename T::mapped_type>::isPointer)
- , _size(sizeImpl<T>)
- , _find(findImpl<T>)
- , _begin(beginImpl<T>)
- , _end(endImpl<T>)
- , _advance(advanceImpl<T>)
- , _getKey(getKeyImpl<T>)
- , _getValue(getValueImpl<T>)
- , _destroyIter(IteratorOwner<typename T::const_iterator>::destroy)
- , _equalIter(IteratorOwner<typename T::const_iterator>::equal)
- , _copyIter(IteratorOwner<typename T::const_iterator>::assign)
- {
- }
-
- QAssociativeIterableImpl()
- : _iterable(nullptr)
- , _iterator(nullptr)
- , _metaType_id_key(QMetaType::UnknownType)
- , _metaType_flags_key(0)
- , _metaType_id_value(QMetaType::UnknownType)
- , _metaType_flags_value(0)
- , _size(nullptr)
- , _find(nullptr)
- , _begin(nullptr)
- , _end(nullptr)
- , _advance(nullptr)
- , _getKey(nullptr)
- , _getValue(nullptr)
- , _destroyIter(nullptr)
- , _equalIter(nullptr)
- , _copyIter(nullptr)
- {
- }
-
- inline void begin() { _begin(_iterable, &_iterator); }
- inline void end() { _end(_iterable, &_iterator); }
- inline bool equal(const QAssociativeIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); }
- inline QAssociativeIterableImpl &advance(int i) { _advance(&_iterator, i); return *this; }
-
- inline void destroyIter() { _destroyIter(&_iterator); }
-
- inline VariantData getCurrentKey() const { return _getKey(&_iterator, _metaType_id_key, _metaType_flags_key); }
- inline VariantData getCurrentValue() const { return _getValue(&_iterator, _metaType_id_value, _metaType_flags_value); }
-
- inline void find(const VariantData &key)
- { _find(_iterable, key.data, &_iterator); }
-
- int size() const { Q_ASSERT(_iterable); return _size(_iterable); }
-
- void copy(const QAssociativeIterableImpl &other)
- {
- *this = other;
- _copyIter(&_iterator, &other._iterator);
- }
-};
-QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QAssociativeIterableImpl, Q_MOVABLE_TYPE)
-
-template<typename From>
-struct QAssociativeIterableConvertFunctor
-{
- QAssociativeIterableImpl operator()(const From& f) const
- {
- return QAssociativeIterableImpl(&f);
- }
-};
class QPairVariantInterfaceImpl
{
+public:
const void *_pair;
- int _metaType_id_first;
- uint _metaType_flags_first;
- int _metaType_id_second;
- uint _metaType_flags_second;
+ QMetaType _metaType_first;
+ QMetaType _metaType_second;
- typedef VariantData (*getFunc)(const void * const *p, int metaTypeId, uint flags);
+ typedef void (*getFunc)(const void * const *p, void *);
getFunc _getFirst;
getFunc _getSecond;
template<class T>
- static VariantData getFirstImpl(const void * const *pair, int metaTypeId, uint flags)
- { return VariantData(metaTypeId, &static_cast<const T*>(*pair)->first, flags); }
+ static void getFirstImpl(const void * const *pair, void *dataPtr)
+ { *static_cast<typename T::first_type *>(dataPtr) = static_cast<const T*>(*pair)->first; }
template<class T>
- static VariantData getSecondImpl(const void * const *pair, int metaTypeId, uint flags)
- { return VariantData(metaTypeId, &static_cast<const T*>(*pair)->second, flags); }
+ static void getSecondImpl(const void * const *pair, void *dataPtr)
+ { *static_cast<typename T::second_type *>(dataPtr) = static_cast<const T*>(*pair)->second; }
public:
template<class T> QPairVariantInterfaceImpl(const T*p)
: _pair(p)
- , _metaType_id_first(qMetaTypeId<typename T::first_type>())
- , _metaType_flags_first(QTypeInfo<typename T::first_type>::isPointer)
- , _metaType_id_second(qMetaTypeId<typename T::second_type>())
- , _metaType_flags_second(QTypeInfo<typename T::second_type>::isPointer)
+ , _metaType_first(QMetaType::fromType<typename T::first_type>())
+ , _metaType_second(QMetaType::fromType<typename T::second_type>())
, _getFirst(getFirstImpl<T>)
, _getSecond(getSecondImpl<T>)
{
}
- QPairVariantInterfaceImpl()
+ constexpr QPairVariantInterfaceImpl()
: _pair(nullptr)
- , _metaType_id_first(QMetaType::UnknownType)
- , _metaType_flags_first(0)
- , _metaType_id_second(QMetaType::UnknownType)
- , _metaType_flags_second(0)
, _getFirst(nullptr)
, _getSecond(nullptr)
{
}
- inline VariantData first() const { return _getFirst(&_pair, _metaType_id_first, _metaType_flags_first); }
- inline VariantData second() const { return _getSecond(&_pair, _metaType_id_second, _metaType_flags_second); }
+ inline void first(void *dataPtr) const { _getFirst(&_pair, dataPtr); }
+ inline void second(void *dataPtr) const { _getSecond(&_pair, dataPtr); }
};
-QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QPairVariantInterfaceImpl, Q_MOVABLE_TYPE)
+QT_METATYPE_PRIVATE_DECLARE_TYPEINFO(QPairVariantInterfaceImpl, Q_RELOCATABLE_TYPE)
template<typename From>
struct QPairVariantInterfaceConvertFunctor;
@@ -1343,7 +865,6 @@ struct QPairVariantInterfaceConvertFunctor<std::pair<T, U> >
}
class QObject;
-class QWidget;
#define QT_FORWARD_DECLARE_SHARED_POINTER_TYPES_ITER(Name) \
template <class T> class Name; \
@@ -1352,6 +873,34 @@ QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(QT_FORWARD_DECLARE_SHARED_POINTER_T
namespace QtPrivate
{
+ namespace detail {
+ template<typename T, typename ODR_VIOLATION_PREVENTER>
+ struct is_complete_helper
+ {
+ template<typename U>
+ static auto check(U *) -> std::integral_constant<bool, sizeof(U) != 0>;
+ static auto check(...) -> std::false_type;
+ using type = decltype(check(static_cast<T *>(nullptr)));
+ };
+ } // namespace detail
+
+ template <typename T, typename ODR_VIOLATION_PREVENTER>
+ struct is_complete : detail::is_complete_helper<std::remove_reference_t<T>, ODR_VIOLATION_PREVENTER>::type {};
+
+ template <typename T> struct MetatypeDecay { using type = T; };
+ template <typename T> struct MetatypeDecay<const T> { using type = T; };
+ template <typename T> struct MetatypeDecay<const T &> { using type = T; };
+
+ template <typename T> struct IsPointerDeclaredOpaque :
+ std::disjunction<std::is_member_pointer<T>,
+ std::is_function<std::remove_pointer_t<T>>>
+ {};
+ template <> struct IsPointerDeclaredOpaque<void *> : std::true_type {};
+ template <> struct IsPointerDeclaredOpaque<const void *> : std::true_type {};
+
+ // Note: this does not check that T = U* isn't pointing to a
+ // forward-declared type. You may want to combine with
+ // checkTypeIsSuitableForMetaType().
template<typename T>
struct IsPointerToTypeDerivedFromQObject
{
@@ -1383,9 +932,9 @@ namespace QtPrivate
#ifndef QT_NO_QOBJECT
static yes_type checkType(QObject* );
+ static yes_type checkType(const QObject* );
#endif
static no_type checkType(...);
- static_assert(sizeof(T), "Type argument of Q_DECLARE_METATYPE(T*) must be fully defined");
enum { Value = sizeof(checkType(static_cast<T*>(nullptr))) == sizeof(yes_type) };
};
@@ -1404,6 +953,9 @@ namespace QtPrivate
};
};
+ template <typename T>
+ using IsRealGadget = std::bool_constant<IsGadgetHelper<T>::IsRealGadget>;
+
template<typename T, typename Enable = void>
struct IsPointerToGadgetHelper { enum { IsRealGadget = false, IsGadgetOrDerivedFrom = false }; };
@@ -1437,36 +989,42 @@ namespace QtPrivate
template<typename T, typename Enable = void>
struct MetaObjectForType
{
- static constexpr inline const QMetaObject *value() { return nullptr; }
+ static constexpr const QMetaObject *value() { return nullptr; }
+ using MetaObjectFn = const QMetaObject *(*)(const QMetaTypeInterface *);
+ static constexpr MetaObjectFn metaObjectFunction = nullptr;
};
#ifndef QT_NO_QOBJECT
- template<>
- struct MetaObjectForType<void>
- {
- static constexpr inline const QMetaObject *value() { return nullptr; }
- };
template<typename T>
struct MetaObjectForType<T*, typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value>::type>
{
- static constexpr inline const QMetaObject *value() { return &T::staticMetaObject; }
+ static constexpr const QMetaObject *value() { return &T::staticMetaObject; }
+ static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return &T::staticMetaObject; }
};
template<typename T>
- struct MetaObjectForType<T, typename std::enable_if<IsGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
- {
- static constexpr inline const QMetaObject *value() { return &T::staticMetaObject; }
+ struct MetaObjectForType<T, std::enable_if_t<
+ std::disjunction_v<
+ std::bool_constant<IsGadgetHelper<T>::IsGadgetOrDerivedFrom>,
+ std::is_base_of<QObject, T>
+ >
+ >>
+ {
+ static constexpr const QMetaObject *value() { return &T::staticMetaObject; }
+ static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return &T::staticMetaObject; }
};
template<typename T>
struct MetaObjectForType<T, typename std::enable_if<IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom>::type>
{
- static constexpr inline const QMetaObject *value()
+ static constexpr const QMetaObject *value()
{
return &IsPointerToGadgetHelper<T>::BaseType::staticMetaObject;
}
+ static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return value(); }
};
template<typename T>
struct MetaObjectForType<T, typename std::enable_if<IsQEnumHelper<T>::Value>::type >
{
- static constexpr inline const QMetaObject *value() { return qt_getEnumMetaObject(T()); }
+ static constexpr const QMetaObject *value() { return qt_getEnumMetaObject(T()); }
+ static constexpr const QMetaObject *metaObjectFunction(const QMetaTypeInterface *) { return value(); }
};
#endif
@@ -1517,62 +1075,82 @@ namespace QtPrivate
};
template<typename T, bool = QtPrivate::IsSequentialContainer<T>::Value>
- struct SequentialContainerConverterHelper
+ struct SequentialContainerTransformationHelper
{
- static bool registerConverter(int)
+ static bool registerConverter()
+ {
+ return false;
+ }
+
+ static bool registerMutableView()
{
return false;
}
};
template<typename T, bool = QMetaTypeId2<typename T::value_type>::Defined>
- struct ValueTypeIsMetaType
+ struct SequentialValueTypeIsMetaType
{
- static bool registerConverter(int)
+ static bool registerConverter()
+ {
+ return false;
+ }
+
+ static bool registerMutableView()
{
return false;
}
};
template<typename T>
- struct SequentialContainerConverterHelper<T, true> : ValueTypeIsMetaType<T>
+ struct SequentialContainerTransformationHelper<T, true> : SequentialValueTypeIsMetaType<T>
{
};
template<typename T, bool = QtPrivate::IsAssociativeContainer<T>::Value>
- struct AssociativeContainerConverterHelper
+ struct AssociativeContainerTransformationHelper
{
- static bool registerConverter(int)
+ static bool registerConverter()
{
return false;
}
- };
- template<typename T, bool = QMetaTypeId2<typename T::mapped_type>::Defined>
- struct AssociativeValueTypeIsMetaType
- {
- static bool registerConverter(int)
+ static bool registerMutableView()
{
return false;
}
};
template<typename T, bool = QMetaTypeId2<typename T::key_type>::Defined>
- struct KeyAndValueTypeIsMetaType
+ struct AssociativeKeyTypeIsMetaType
{
- static bool registerConverter(int)
+ static bool registerConverter()
+ {
+ return false;
+ }
+
+ static bool registerMutableView()
{
return false;
}
};
- template<typename T>
- struct KeyAndValueTypeIsMetaType<T, true> : AssociativeValueTypeIsMetaType<T>
+ template<typename T, bool = QMetaTypeId2<typename T::mapped_type>::Defined>
+ struct AssociativeMappedTypeIsMetaType
{
+ static bool registerConverter()
+ {
+ return false;
+ }
+
+ static bool registerMutableView()
+ {
+ return false;
+ }
};
template<typename T>
- struct AssociativeContainerConverterHelper<T, true> : KeyAndValueTypeIsMetaType<T>
+ struct AssociativeContainerTransformationHelper<T, true> : AssociativeKeyTypeIsMetaType<T>
{
};
@@ -1580,7 +1158,7 @@ namespace QtPrivate
&& QMetaTypeId2<typename T::second_type>::Defined>
struct IsMetaTypePair
{
- static bool registerConverter(int)
+ static bool registerConverter()
{
return false;
}
@@ -1589,13 +1167,13 @@ namespace QtPrivate
template<typename T>
struct IsMetaTypePair<T, true>
{
- inline static bool registerConverter(int id);
+ inline static bool registerConverter();
};
template<typename T>
struct IsPair
{
- static bool registerConverter(int)
+ static bool registerConverter()
{
return false;
}
@@ -1609,15 +1187,39 @@ namespace QtPrivate
template<typename T, typename = void>
struct MetaTypeSmartPointerHelper
{
- static bool registerConverter(int) { return false; }
+ static bool registerConverter() { return false; }
};
+#if QT_CONFIG(future)
+ template<typename T>
+ struct MetaTypeQFutureHelper
+ {
+ static bool registerConverter() { return false; }
+ };
+#endif
+
+ template <typename X> static constexpr bool checkTypeIsSuitableForMetaType()
+ {
+ using T = typename MetatypeDecay<X>::type;
+ static_assert(is_complete<T, void>::value || std::is_void_v<T>,
+ "Meta Types must be fully defined");
+ static_assert(!std::is_reference_v<T>,
+ "Meta Types cannot be non-const references or rvalue references.");
+ if constexpr (std::is_pointer_v<T> && !IsPointerDeclaredOpaque<T>::value) {
+ using Pointed = std::remove_pointer_t<T>;
+ static_assert(is_complete<Pointed, void>::value,
+ "Pointer Meta Types must either point to fully-defined types "
+ "or be declared with Q_DECLARE_OPAQUE_POINTER(T *)");
+ }
+ return true;
+ }
+
Q_CORE_EXPORT bool isBuiltinType(const QByteArray &type);
} // namespace QtPrivate
template <typename T, int =
QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject :
- QtPrivate::IsGadgetHelper<T>::IsRealGadget ? QMetaType::IsGadget :
+ QtPrivate::IsRealGadget<T>::value ? QMetaType::IsGadget :
QtPrivate::IsPointerToGadgetHelper<T>::IsRealGadget ? QMetaType::PointerToGadget :
QtPrivate::IsQEnumHelper<T>::Value ? QMetaType::IsEnumeration : 0>
struct QMetaTypeIdQObject
@@ -1635,24 +1237,30 @@ struct QMetaTypeId : public QMetaTypeIdQObject<T>
template <typename T>
struct QMetaTypeId2
{
+ using NameAsArrayType = void;
enum { Defined = QMetaTypeId<T>::Defined, IsBuiltIn=false };
- static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }
+ static inline constexpr int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }
};
template <typename T>
struct QMetaTypeId2<const T&> : QMetaTypeId2<T> {};
template <typename T>
-struct QMetaTypeId2<T&> { enum {Defined = false }; };
+struct QMetaTypeId2<T&>
+{
+ using NameAsArrayType = void;
+ enum { Defined = false, IsBuiltIn = false };
+ static inline constexpr int qt_metatype_id() { return 0; }
+};
namespace QtPrivate {
template <typename T, bool Defined = QMetaTypeId2<T>::Defined>
struct QMetaTypeIdHelper {
- static inline Q_DECL_CONSTEXPR int qt_metatype_id()
+ static inline constexpr int qt_metatype_id()
{ return QMetaTypeId2<T>::qt_metatype_id(); }
};
template <typename T> struct QMetaTypeIdHelper<T, false> {
- static inline Q_DECL_CONSTEXPR int qt_metatype_id()
+ static inline constexpr int qt_metatype_id()
{ return -1; }
};
@@ -1661,11 +1269,21 @@ namespace QtPrivate {
struct IsPointerToTypeDerivedFromQObject<Result(*)(Args...)> { enum { Value = false }; };
template<typename T>
+ inline constexpr bool IsQmlListType = false;
+
+ template<typename T, bool = std::is_enum<T>::value>
+ constexpr bool IsUnsignedEnum = false;
+ template<typename T>
+ constexpr bool IsUnsignedEnum<T, true> = !std::is_signed_v<std::underlying_type_t<T>>;
+
+ template<typename T>
struct QMetaTypeTypeFlags
{
- enum { Flags = (QTypeInfoQuery<T>::isRelocatable ? QMetaType::MovableType : 0)
- | (QTypeInfo<T>::isComplex ? QMetaType::NeedsConstruction : 0)
- | (QTypeInfo<T>::isComplex ? QMetaType::NeedsDestruction : 0)
+ enum { Flags = (QTypeInfo<T>::isRelocatable ? QMetaType::RelocatableType : 0)
+ | ((!std::is_default_constructible_v<T> || !QTypeInfo<T>::isValueInitializationBitwiseZero) ? QMetaType::NeedsConstruction : 0)
+ | (!std::is_trivially_destructible_v<T> ? QMetaType::NeedsDestruction : 0)
+ | (!std::is_trivially_copy_constructible_v<T> ? QMetaType::NeedsCopyConstruction : 0)
+ | (!std::is_trivially_move_constructible_v<T> ? QMetaType::NeedsMoveConstruction : 0)
| (IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject : 0)
| (IsSharedPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::SharedPointerToQObject : 0)
| (IsWeakPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::WeakPointerToQObject : 0)
@@ -1673,7 +1291,10 @@ namespace QtPrivate {
| (IsEnumOrFlags<T>::value ? QMetaType::IsEnumeration : 0)
| (IsGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::IsGadget : 0)
| (IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::PointerToGadget : 0)
- | (QTypeInfo<T>::isPointer ? QMetaType::IsPointer : 0)
+ | (std::is_pointer_v<T> ? QMetaType::IsPointer : 0)
+ | (IsUnsignedEnum<T> ? QMetaType::IsUnsignedEnumeration : 0)
+ | (IsQmlListType<T> ? QMetaType::IsQmlList : 0)
+ | (std::is_const_v<std::remove_pointer_t<T>> ? QMetaType::IsConst : 0)
};
};
@@ -1708,65 +1329,85 @@ namespace QtPrivate {
}
template <typename T>
-int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName
-#ifndef Q_CLANG_QDOC
- , T * = 0
- , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType = QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined
-#endif
-)
+int qRegisterNormalizedMetaTypeImplementation(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName)
{
#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.");
+ Q_ASSERT_X(normalizedTypeName == QMetaObject::normalizedType(normalizedTypeName.constData()),
+ "qRegisterNormalizedMetaType",
+ "qRegisterNormalizedMetaType was called with a not normalized type name, "
+ "please call qRegisterMetaType instead.");
#endif
const QMetaType metaType = QMetaType::fromType<T>();
const int id = metaType.id();
- if (id > 0) {
+ QtPrivate::SequentialContainerTransformationHelper<T>::registerConverter();
+ QtPrivate::SequentialContainerTransformationHelper<T>::registerMutableView();
+ QtPrivate::AssociativeContainerTransformationHelper<T>::registerConverter();
+ QtPrivate::AssociativeContainerTransformationHelper<T>::registerMutableView();
+ QtPrivate::MetaTypePairHelper<T>::registerConverter();
+ QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter();
+#if QT_CONFIG(future)
+ QtPrivate::MetaTypeQFutureHelper<T>::registerConverter();
+#endif
+
+ if (normalizedTypeName != metaType.name())
QMetaType::registerNormalizedTypedef(normalizedTypeName, metaType);
- QtPrivate::SequentialContainerConverterHelper<T>::registerConverter(id);
- QtPrivate::AssociativeContainerConverterHelper<T>::registerConverter(id);
- QtPrivate::MetaTypePairHelper<T>::registerConverter(id);
- QtPrivate::MetaTypeSmartPointerHelper<T>::registerConverter(id);
- }
return id;
}
+// This primary template calls the -Implementation, like all other specialisations should.
+// But the split allows to
+// - in a header:
+// - define a specialization of this template calling an out-of-line function
+// (QT_DECL_METATYPE_EXTERN{,_TAGGED})
+// - in the .cpp file:
+// - define the out-of-line wrapper to call the -Implementation
+// (QT_IMPL_METATYPE_EXTERN{,_TAGGED})
+// The _TAGGED variants let you choose a tag (must be a C identifier) to disambiguate
+// the out-of-line function; the non-_TAGGED variants use the passed class name as tag.
template <typename T>
-int qRegisterMetaType(const char *typeName
-#ifndef Q_CLANG_QDOC
- , T * dummy = nullptr
- , typename QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::DefinedType defined = QtPrivate::MetaTypeDefinedHelper<T, QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn>::Defined
-#endif
-)
+int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName)
+{
+ return qRegisterNormalizedMetaTypeImplementation<T>(normalizedTypeName);
+}
+
+#define QT_DECL_METATYPE_EXTERN_TAGGED(TYPE, TAG, EXPORT) \
+ QT_BEGIN_NAMESPACE \
+ EXPORT int qRegisterNormalizedMetaType_ ## TAG (const QByteArray &); \
+ template <> inline int qRegisterNormalizedMetaType< TYPE >(const QByteArray &name) \
+ { return qRegisterNormalizedMetaType_ ## TAG (name); } \
+ QT_END_NAMESPACE \
+ Q_DECLARE_METATYPE(TYPE) \
+ /* end */
+#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG) \
+ int qRegisterNormalizedMetaType_ ## TAG (const QByteArray &name) \
+ { return qRegisterNormalizedMetaTypeImplementation< TYPE >(name); } \
+ /* end */
+#define QT_DECL_METATYPE_EXTERN(TYPE, EXPORT) \
+ QT_DECL_METATYPE_EXTERN_TAGGED(TYPE, TYPE, EXPORT)
+#define QT_IMPL_METATYPE_EXTERN(TYPE) \
+ QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TYPE)
+
+template <typename T>
+int qRegisterMetaType(const char *typeName)
{
#ifdef QT_NO_QOBJECT
QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = typeName;
#else
QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
#endif
- return qRegisterNormalizedMetaType<T>(normalizedTypeName, dummy, defined);
-}
-
-#ifndef QT_NO_DATASTREAM
-template <typename T>
-void qRegisterMetaTypeStreamOperators(const char *typeName
-#ifndef Q_CLANG_QDOC
- , T * /* dummy */ = nullptr
-#endif
-)
-{
- qRegisterMetaType<T>(typeName);
- QMetaType::registerStreamOperators(typeName, QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Save,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Load);
+ return qRegisterNormalizedMetaType<T>(normalizedTypeName);
}
-#endif // QT_NO_DATASTREAM
template <typename T>
-inline Q_DECL_CONSTEXPR int qMetaTypeId()
+inline constexpr int qMetaTypeId()
{
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;
} else {
return QMetaType::fromType<T>().id();
@@ -1774,22 +1415,16 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId()
}
template <typename T>
-inline Q_DECL_CONSTEXPR int qRegisterMetaType()
+inline constexpr int qRegisterMetaType()
{
- return qMetaTypeId<T>();
+ int id = qMetaTypeId<T>();
+ return id;
}
-#if QT_DEPRECATED_SINCE(5, 1) && !defined(Q_CLANG_QDOC)
-// There used to be a T *dummy = 0 argument in Qt 4.0 to support MSVC6
-template <typename T>
-QT_DEPRECATED inline Q_DECL_CONSTEXPR int qMetaTypeId(T *)
-{ return qMetaTypeId<T>(); }
-#ifndef Q_CC_SUN
-template <typename T>
-QT_DEPRECATED inline Q_DECL_CONSTEXPR int qRegisterMetaType(T *)
-{ return qRegisterMetaType<T>(); }
-#endif
-#endif
+inline int qRegisterMetaType(QMetaType meta)
+{
+ return meta.registerHelper();
+}
#ifndef QT_NO_QOBJECT
template <typename T>
@@ -1801,16 +1436,14 @@ struct QMetaTypeIdQObject<T*, QMetaType::PointerToQObject>
static int qt_metatype_id()
{
- static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
+ Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
if (const int id = metatype_id.loadAcquire())
return id;
- const char * const cName = T::staticMetaObject.className();
+ const char *const cName = T::staticMetaObject.className();
QByteArray typeName;
- typeName.reserve(int(strlen(cName)) + 1);
+ typeName.reserve(strlen(cName) + 1);
typeName.append(cName).append('*');
- const int newId = qRegisterNormalizedMetaType<T*>(
- typeName,
- reinterpret_cast<T**>(quintptr(-1)));
+ const int newId = qRegisterNormalizedMetaType<T *>(typeName);
metatype_id.storeRelease(newId);
return newId;
}
@@ -1825,13 +1458,11 @@ struct QMetaTypeIdQObject<T, QMetaType::IsGadget>
static int qt_metatype_id()
{
- static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
+ Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
if (const int id = metatype_id.loadAcquire())
return id;
- const char * const cName = T::staticMetaObject.className();
- const int newId = qRegisterNormalizedMetaType<T>(
- cName,
- reinterpret_cast<T*>(quintptr(-1)));
+ const char *const cName = T::staticMetaObject.className();
+ const int newId = qRegisterNormalizedMetaType<T>(cName);
metatype_id.storeRelease(newId);
return newId;
}
@@ -1846,16 +1477,14 @@ struct QMetaTypeIdQObject<T*, QMetaType::PointerToGadget>
static int qt_metatype_id()
{
- static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
+ Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
if (const int id = metatype_id.loadAcquire())
return id;
- const char * const cName = T::staticMetaObject.className();
+ const char *const cName = T::staticMetaObject.className();
QByteArray typeName;
- typeName.reserve(int(strlen(cName)) + 1);
+ typeName.reserve(strlen(cName) + 1);
typeName.append(cName).append('*');
- const int newId = qRegisterNormalizedMetaType<T*>(
- typeName,
- reinterpret_cast<T**>(quintptr(-1)));
+ const int newId = qRegisterNormalizedMetaType<T *>(typeName);
metatype_id.storeRelease(newId);
return newId;
}
@@ -1870,41 +1499,25 @@ struct QMetaTypeIdQObject<T, QMetaType::IsEnumeration>
static int qt_metatype_id()
{
- static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
+ Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
if (const int id = metatype_id.loadAcquire())
return id;
const char *eName = qt_getEnumName(T());
const char *cName = qt_getEnumMetaObject(T())->className();
QByteArray typeName;
- typeName.reserve(int(strlen(cName) + 2 + strlen(eName)));
+ typeName.reserve(strlen(cName) + 2 + strlen(eName));
typeName.append(cName).append("::").append(eName);
- const int newId = qRegisterNormalizedMetaType<T>(
- typeName,
- reinterpret_cast<T*>(quintptr(-1)));
+ const int newId = qRegisterNormalizedMetaType<T>(typeName);
metatype_id.storeRelease(newId);
return newId;
}
};
#endif
-#ifndef QT_NO_DATASTREAM
-template <typename T>
-inline int qRegisterMetaTypeStreamOperators()
-{
- int id = qMetaTypeId<T>();
- QMetaType::registerStreamOperators(id, QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Save,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<T>::Load);
- return id;
-}
-#endif
-
#define Q_DECLARE_OPAQUE_POINTER(POINTER) \
QT_BEGIN_NAMESPACE namespace QtPrivate { \
- template <> \
- struct IsPointerToTypeDerivedFromQObject<POINTER > \
- { \
- enum { Value = false }; \
- }; \
+ template <> struct IsPointerDeclaredOpaque<POINTER> \
+ : std::true_type {}; \
} QT_END_NAMESPACE \
/**/
@@ -1916,13 +1529,20 @@ inline int qRegisterMetaTypeStreamOperators()
struct QMetaTypeId< TYPE > \
{ \
enum { Defined = 1 }; \
+ static_assert(QtPrivate::checkTypeIsSuitableForMetaType<TYPE>()); \
static int qt_metatype_id() \
{ \
- static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
+ Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
if (const int id = metatype_id.loadAcquire()) \
return id; \
- const int newId = qRegisterMetaType< TYPE >(#TYPE, \
- reinterpret_cast< TYPE *>(quintptr(-1))); \
+ constexpr auto arr = QtPrivate::typenameHelper<TYPE>(); \
+ auto name = arr.data(); \
+ if (QByteArrayView(name) == (#TYPE)) { \
+ const int id = qRegisterNormalizedMetaType<TYPE>(name); \
+ metatype_id.storeRelease(id); \
+ return id; \
+ } \
+ const int newId = qRegisterMetaType< TYPE >(#TYPE); \
metatype_id.storeRelease(newId); \
return newId; \
} \
@@ -1934,9 +1554,10 @@ inline int qRegisterMetaTypeStreamOperators()
QT_BEGIN_NAMESPACE \
template<> struct QMetaTypeId2<NAME> \
{ \
+ using NameAsArrayType = std::array<char, sizeof(#NAME)>; \
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; \
+ static inline constexpr int qt_metatype_id() { return METATYPEID; } \
+ static constexpr NameAsArrayType nameAsArray = { #NAME }; \
}; \
QT_END_NAMESPACE
@@ -1949,15 +1570,6 @@ QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER)
#undef QT_FORWARD_DECLARE_STATIC_TYPES_ITER
-typedef QList<QVariant> QVariantList;
-typedef QMap<QString, QVariant> QVariantMap;
-typedef QHash<QString, QVariant> QVariantHash;
-#ifdef Q_CLANG_QDOC
-class QByteArrayList;
-#else
-using QByteArrayList = QList<QByteArray>;
-#endif
-
#define Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE) \
QT_BEGIN_NAMESPACE \
template <typename T> \
@@ -1968,31 +1580,22 @@ struct QMetaTypeId< SINGLE_ARG_TEMPLATE<T> > \
}; \
static int qt_metatype_id() \
{ \
- static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
+ Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
if (const int id = metatype_id.loadRelaxed()) \
return id; \
- const char *tName = QMetaType::typeName(qMetaTypeId<T>()); \
+ const char *tName = QMetaType::fromType<T>().name(); \
Q_ASSERT(tName); \
- const int tNameLen = int(qstrlen(tName)); \
+ const size_t tNameLen = qstrlen(tName); \
QByteArray typeName; \
- typeName.reserve(int(sizeof(#SINGLE_ARG_TEMPLATE)) + 1 + tNameLen + 1 + 1); \
+ typeName.reserve(sizeof(#SINGLE_ARG_TEMPLATE) + 1 + tNameLen + 1 + 1); \
typeName.append(#SINGLE_ARG_TEMPLATE, int(sizeof(#SINGLE_ARG_TEMPLATE)) - 1) \
.append('<').append(tName, tNameLen); \
typeName.append('>'); \
- const int newId = qRegisterNormalizedMetaType< SINGLE_ARG_TEMPLATE<T> >( \
- typeName, \
- reinterpret_cast< SINGLE_ARG_TEMPLATE<T> *>(quintptr(-1))); \
+ const int newId = qRegisterNormalizedMetaType< SINGLE_ARG_TEMPLATE<T> >(typeName); \
metatype_id.storeRelease(newId); \
return newId; \
} \
}; \
-namespace QtPrivate { \
-template<typename T> \
-struct IsSequentialContainer<SINGLE_ARG_TEMPLATE<T> > \
-{ \
- enum { Value = true }; \
-}; \
-} \
QT_END_NAMESPACE
#define Q_DECLARE_METATYPE_TEMPLATE_2ARG(DOUBLE_ARG_TEMPLATE) \
@@ -2005,23 +1608,21 @@ struct QMetaTypeId< DOUBLE_ARG_TEMPLATE<T, U> > \
}; \
static int qt_metatype_id() \
{ \
- static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
+ Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
if (const int id = metatype_id.loadAcquire()) \
return id; \
- const char *tName = QMetaType::typeName(qMetaTypeId<T>()); \
- const char *uName = QMetaType::typeName(qMetaTypeId<U>()); \
+ const char *tName = QMetaType::fromType<T>().name(); \
+ const char *uName = QMetaType::fromType<U>().name(); \
Q_ASSERT(tName); \
Q_ASSERT(uName); \
- const int tNameLen = int(qstrlen(tName)); \
- const int uNameLen = int(qstrlen(uName)); \
+ const size_t tNameLen = qstrlen(tName); \
+ const size_t uNameLen = qstrlen(uName); \
QByteArray typeName; \
- typeName.reserve(int(sizeof(#DOUBLE_ARG_TEMPLATE)) + 1 + tNameLen + 1 + uNameLen + 1 + 1); \
+ typeName.reserve(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); \
typeName.append('>'); \
- const int newId = qRegisterNormalizedMetaType< DOUBLE_ARG_TEMPLATE<T, U> >(\
- typeName, \
- reinterpret_cast< DOUBLE_ARG_TEMPLATE<T, U> *>(quintptr(-1))); \
+ const int newId = qRegisterNormalizedMetaType< DOUBLE_ARG_TEMPLATE<T, U> >(typeName); \
metatype_id.storeRelease(newId); \
return newId; \
} \
@@ -2055,34 +1656,29 @@ struct SharedPointerMetaTypeIdHelper<SMART_POINTER<T>, true> \
}; \
static int qt_metatype_id() \
{ \
- static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
+ Q_CONSTINIT static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
if (const int id = metatype_id.loadAcquire()) \
return id; \
const char * const cName = T::staticMetaObject.className(); \
QByteArray typeName; \
- typeName.reserve(int(sizeof(#SMART_POINTER) + 1 + strlen(cName) + 1)); \
+ typeName.reserve(sizeof(#SMART_POINTER) + 1 + strlen(cName) + 1); \
typeName.append(#SMART_POINTER, int(sizeof(#SMART_POINTER)) - 1) \
.append('<').append(cName).append('>'); \
- const int newId = qRegisterNormalizedMetaType< SMART_POINTER<T> >( \
- typeName, \
- reinterpret_cast< SMART_POINTER<T> *>(quintptr(-1))); \
+ const int newId = qRegisterNormalizedMetaType< SMART_POINTER<T> >(typeName); \
metatype_id.storeRelease(newId); \
return newId; \
} \
}; \
template<typename T> \
struct MetaTypeSmartPointerHelper<SMART_POINTER<T> , \
- typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value>::type> \
+ typename std::enable_if<IsPointerToTypeDerivedFromQObject<T*>::Value && !std::is_const_v<T>>::type> \
{ \
- static bool registerConverter(int id) \
+ static bool registerConverter() \
{ \
- const int toId = QMetaType::QObjectStar; \
- if (!QMetaType::hasRegisteredConverterFunction(id, toId)) { \
+ const QMetaType to = QMetaType(QMetaType::QObjectStar); \
+ if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<SMART_POINTER<T>>(), to)) { \
QtPrivate::QSmartPointerConvertFunctor<SMART_POINTER<T> > o; \
- static const QtPrivate::ConverterFunctor<SMART_POINTER<T>, \
- QObject*, \
- QSmartPointerConvertFunctor<SMART_POINTER<T> > > f(o); \
- return QMetaType::registerConverterFunction(&f, id, toId); \
+ return QMetaType::registerConverter<SMART_POINTER<T>, QObject*>(o); \
} \
return true; \
} \
@@ -2096,11 +1692,20 @@ struct QMetaTypeId< SMART_POINTER<T> > \
};\
QT_END_NAMESPACE
-#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER(TEMPLATENAME) \
+#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(SINGLE_ARG_TEMPLATE) \
QT_BEGIN_NAMESPACE \
- template <class T> class TEMPLATENAME; \
+ namespace QtPrivate { \
+ template<typename T> \
+ struct IsSequentialContainer<SINGLE_ARG_TEMPLATE<T> > \
+ { \
+ enum { Value = true }; \
+ }; \
+ } \
QT_END_NAMESPACE \
- Q_DECLARE_METATYPE_TEMPLATE_1ARG(TEMPLATENAME)
+ Q_DECLARE_METATYPE_TEMPLATE_1ARG(SINGLE_ARG_TEMPLATE)
+
+#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER(TEMPLATENAME) \
+ Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(TEMPLATENAME)
QT_END_NAMESPACE
@@ -2108,20 +1713,9 @@ QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER
#undef Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE_ITER
-#define Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE Q_DECLARE_METATYPE_TEMPLATE_1ARG
-
Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::vector)
Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::list)
-#define Q_FORWARD_DECLARE_METATYPE_TEMPLATE_2ARG_ITER(TEMPLATENAME, CPPTYPE) \
- QT_BEGIN_NAMESPACE \
- template <class T1, class T2> CPPTYPE TEMPLATENAME; \
- QT_END_NAMESPACE \
-
-QT_FOR_EACH_AUTOMATIC_TEMPLATE_2ARG(Q_FORWARD_DECLARE_METATYPE_TEMPLATE_2ARG_ITER)
-
-#undef Q_DECLARE_METATYPE_TEMPLATE_2ARG_ITER
-
#define Q_DECLARE_ASSOCIATIVE_CONTAINER_METATYPE(TEMPLATENAME) \
QT_BEGIN_NAMESPACE \
namespace QtPrivate { \
@@ -2143,7 +1737,6 @@ Q_DECLARE_METATYPE_TEMPLATE_2ARG(std::pair)
#define Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER(TEMPLATENAME) \
Q_DECLARE_SMART_POINTER_METATYPE(TEMPLATENAME)
-
QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER)
QT_BEGIN_NAMESPACE
@@ -2152,99 +1745,108 @@ QT_BEGIN_NAMESPACE
QT_END_NAMESPACE
-
QT_FOR_EACH_STATIC_TYPE(Q_DECLARE_BUILTIN_METATYPE)
-Q_DECLARE_METATYPE(QtMetaTypePrivate::QSequentialIterableImpl)
-Q_DECLARE_METATYPE(QtMetaTypePrivate::QAssociativeIterableImpl)
-Q_DECLARE_METATYPE(QtMetaTypePrivate::QPairVariantInterfaceImpl)
QT_BEGIN_NAMESPACE
template <typename T>
-inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter(int id)
+inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter()
{
- const int toId = qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
- if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
+ const QMetaType to = QMetaType::fromType<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
+ if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<T>(), to)) {
QtMetaTypePrivate::QPairVariantInterfaceConvertFunctor<T> o;
- static const QtPrivate::ConverterFunctor<T,
- QtMetaTypePrivate::QPairVariantInterfaceImpl,
- QtMetaTypePrivate::QPairVariantInterfaceConvertFunctor<T> > f(o);
- return QMetaType::registerConverterFunction(&f, id, toId);
+ return QMetaType::registerConverter<T, QtMetaTypePrivate::QPairVariantInterfaceImpl>(o);
}
return true;
}
namespace QtPrivate {
- template<typename T>
- struct ValueTypeIsMetaType<T, true>
+
+template<typename From>
+struct QSequentialIterableConvertFunctor
+{
+ QIterable<QMetaSequence> operator()(const From &f) const
{
- static bool registerConverter(int id)
- {
- const int toId = qMetaTypeId<QtMetaTypePrivate::QSequentialIterableImpl>();
- if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
- QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> o;
- static const QtPrivate::ConverterFunctor<T,
- QtMetaTypePrivate::QSequentialIterableImpl,
- QtMetaTypePrivate::QSequentialIterableConvertFunctor<T> > f(o);
- return QMetaType::registerConverterFunction(&f, id, toId);
- }
- return true;
- }
- };
+ return QIterable<QMetaSequence>(QMetaSequence::fromContainer<From>(), &f);
+ }
+};
- template<typename T>
- struct AssociativeValueTypeIsMetaType<T, true>
+template<typename From>
+struct QSequentialIterableMutableViewFunctor
+{
+ QIterable<QMetaSequence> operator()(From &f) const
{
- static bool registerConverter(int id)
- {
- const int toId = qMetaTypeId<QtMetaTypePrivate::QAssociativeIterableImpl>();
- if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
- QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> o;
- static const QtPrivate::ConverterFunctor<T,
- QtMetaTypePrivate::QAssociativeIterableImpl,
- QtMetaTypePrivate::QAssociativeIterableConvertFunctor<T> > f(o);
- return QMetaType::registerConverterFunction(&f, id, toId);
- }
- return true;
+ return QIterable<QMetaSequence>(QMetaSequence::fromContainer<From>(), &f);
+ }
+};
+
+template<typename T>
+struct SequentialValueTypeIsMetaType<T, true>
+{
+ static bool registerConverter()
+ {
+ const QMetaType to = QMetaType::fromType<QIterable<QMetaSequence>>();
+ if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<T>(), to)) {
+ QSequentialIterableConvertFunctor<T> o;
+ return QMetaType::registerConverter<T, QIterable<QMetaSequence>>(o);
}
- };
-}
+ return true;
+ }
-namespace QtPrivate {
+ static bool registerMutableView()
+ {
+ const QMetaType to = QMetaType::fromType<QIterable<QMetaSequence>>();
+ if (!QMetaType::hasRegisteredMutableViewFunction(QMetaType::fromType<T>(), to)) {
+ QSequentialIterableMutableViewFunctor<T> o;
+ return QMetaType::registerMutableView<T, QIterable<QMetaSequence>>(o);
+ }
+ return true;
+ }
+};
-class QMetaTypeInterface
+template<typename From>
+struct QAssociativeIterableConvertFunctor
{
-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;
+ QIterable<QMetaAssociation> operator()(const From &f) const
+ {
+ return QIterable<QMetaAssociation>(QMetaAssociation::fromContainer<From>(), &f);
+ }
+};
- // Called when the type is unregistered, to delete this
- using DeleteSelf = void (*)(QMetaTypeInterface *);
- DeleteSelf deleteSelf;
+template<typename From>
+struct QAssociativeIterableMutableViewFunctor
+{
+ QIterable<QMetaAssociation> operator()(From &f) const
+ {
+ return QIterable<QMetaAssociation>(QMetaAssociation::fromContainer<From>(), &f);
+ }
+};
- 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 EqualsFn = bool (*)(const QMetaTypeInterface *, const void *, const void *);
- EqualsFn equals;
- using LessThanFn = bool (*)(const QMetaTypeInterface *, const void *, const void *);
- LessThanFn lessThan;
+// Mapped type can be omitted, for example in case of a set.
+// However, if it is available, we want to instantiate the metatype here.
+template<typename T>
+struct AssociativeKeyTypeIsMetaType<T, true> : AssociativeMappedTypeIsMetaType<T>
+{
+ static bool registerConverter()
+ {
+ const QMetaType to = QMetaType::fromType<QIterable<QMetaAssociation>>();
+ if (!QMetaType::hasRegisteredConverterFunction(QMetaType::fromType<T>(), to)) {
+ QAssociativeIterableConvertFunctor<T> o;
+ return QMetaType::registerConverter<T, QIterable<QMetaAssociation>>(o);
+ }
+ return true;
+ }
- using LegacyRegisterOp = void (*)();
- LegacyRegisterOp legacyRegisterOp;
+ static bool registerMutableView()
+ {
+ const QMetaType to = QMetaType::fromType<QIterable<QMetaAssociation>>();
+ if (!QMetaType::hasRegisteredMutableViewFunction(QMetaType::fromType<T>(), to)) {
+ QAssociativeIterableMutableViewFunctor<T> o;
+ return QMetaType::registerMutableView<T, QIterable<QMetaAssociation>>(o);
+ }
+ return true;
+ }
};
struct QTypeNormalizer
@@ -2273,7 +1875,7 @@ private:
#ifdef Q_CC_MSVC
/// On MSVC, keywords like class or struct are not separated with spaces in constexpr
/// context
- if (msvcKw)
+ if (msvcKw && !is_ident_char(*b))
return true;
#endif
Q_UNUSED(msvcKw);
@@ -2305,7 +1907,7 @@ private:
if (x != e)
x++;
return x;
- };
+ }
static constexpr const char *skipTemplate(const char *x, const char *e, bool stopAtComa = false)
{
int scopeDepth = 0;
@@ -2346,7 +1948,7 @@ private:
x++;
}
return x;
- };
+ }
constexpr void append(char x)
{
@@ -2356,13 +1958,156 @@ private:
*output++ = x;
}
+ constexpr void replaceLast(char x)
+ {
+ last = x;
+ if (output)
+ *(output - 1) = x;
+ }
+
constexpr void appendStr(const char *x)
{
while (*x)
append(*x++);
- };
+ }
+
+ constexpr void normalizeIntegerTypes(const char *&begin, const char *end)
+ {
+ 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;
+ }
+#ifdef Q_CC_MSVC
+ if (skipToken(begin, end, "__int64")) {
+ numLong = 2;
+ continue;
+ }
+#endif
+ break;
+ }
+ if (numLong == 2)
+ append('q'); // q(u)longlong
+ if (numSigned && numChar)
+ appendStr("signed ");
+ else if (numUnsigned)
+ appendStr("u");
+ if (numChar)
+ appendStr("char");
+ else if (numShort)
+ appendStr("short");
+ else if (numLong == 1)
+ appendStr("long");
+ else if (numLong == 2)
+ appendStr("longlong");
+ else if (numUnsigned || numSigned || numInt)
+ appendStr("int");
+ }
+
+ constexpr void skipStructClassOrEnum(const char *&begin, const char *end)
+ {
+ // 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);
+ }
+
+ constexpr void skipQtNamespace(const char *&begin, const char *end)
+ {
+#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++;
+ }
+#else
+ Q_UNUSED(begin);
+ Q_UNUSED(end);
+#endif
+ }
public:
+#if defined(Q_CC_CLANG) || defined (Q_CC_GNU)
+ // this is much simpler than the full type normalization below
+ // the reason is that the signature returned by Q_FUNC_INFO is already
+ // normalized to the largest degree, and we need to do only small adjustments
+ constexpr int normalizeTypeFromSignature(const char *begin, const char *end)
+ {
+ // bail out if there is an anonymous struct
+ std::string_view name(begin, end-begin);
+#if defined (Q_CC_CLANG)
+ if (name.find("anonymous ") != std::string_view::npos)
+ return normalizeType(begin, end);
+#endif
+ if (name.find("unnamed ") != std::string_view::npos)
+ return normalizeType(begin, end);
+ while (begin < end) {
+ if (*begin == ' ') {
+ if (last == ',' || last == '>' || last == '<' || last == '*' || last == '&') {
+ ++begin;
+ continue;
+ }
+ }
+ if (last == ' ') {
+ if (*begin == '*' || *begin == '&' || *begin == '(') {
+ replaceLast(*begin);
+ ++begin;
+ continue;
+ }
+ }
+ if (!is_ident_char(last)) {
+ skipStructClassOrEnum(begin, end);
+ if (begin == end)
+ break;
+
+ skipQtNamespace(begin, end);
+ if (begin == end)
+ break;
+
+ normalizeIntegerTypes(begin, end);
+ if (begin == end)
+ break;
+ }
+ append(*begin);
+ ++begin;
+ }
+ return len;
+ }
+#else
+ // MSVC needs the full normalization, as it puts the const in a different
+ // place than we expect
+ constexpr int normalizeTypeFromSignature(const char *begin, const char *end)
+ { return normalizeType(begin, end); }
+#endif
+
constexpr int normalizeType(const char *begin, const char *end, bool adjustConst = true)
{
// Trim spaces
@@ -2445,20 +2190,8 @@ public:
}
}
- // 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
+ skipStructClassOrEnum(begin, end);
+ skipQtNamespace(begin, end);
if (skipToken(begin, end, "QVector")) {
// Replace QVector by QList
@@ -2467,73 +2200,12 @@ public:
if (skipToken(begin, end, "QPair")) {
// replace QPair by std::pair
-#ifdef _LIBCPP_VERSION
- appendStr("std::" QT_STRINGIFY(_LIBCPP_ABI_NAMESPACE) "::pair");
-#else
appendStr("std::pair");
-#endif
}
- if (!hasMiddleConst) {
+ 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");
- }
- }
+ normalizeIntegerTypes(begin, end);
bool spaceSkiped = true;
while (begin != end) {
@@ -2576,43 +2248,92 @@ constexpr int qNormalizeType(const char *begin, const char *end, char *output)
}
template<typename T>
+struct is_std_pair : std::false_type {};
+
+template <typename T1_, typename T2_>
+struct is_std_pair<std::pair<T1_, T2_>> : std::true_type {
+ using T1 = T1_;
+ using T2 = T2_;
+};
+
+namespace TypeNameHelper {
+template<typename T>
constexpr auto typenameHelper()
{
- constexpr auto prefix = sizeof(
+ if constexpr (is_std_pair<T>::value) {
+ using T1 = typename is_std_pair<T>::T1;
+ using T2 = typename is_std_pair<T>::T2;
+ std::remove_const_t<std::conditional_t<bool (QMetaTypeId2<T1>::IsBuiltIn), typename QMetaTypeId2<T1>::NameAsArrayType, decltype(typenameHelper<T1>())>> t1Name {};
+ std::remove_const_t<std::conditional_t<bool (QMetaTypeId2<T2>::IsBuiltIn), typename QMetaTypeId2<T2>::NameAsArrayType, decltype(typenameHelper<T2>())>> t2Name {};
+ if constexpr (bool (QMetaTypeId2<T1>::IsBuiltIn) ) {
+ t1Name = QMetaTypeId2<T1>::nameAsArray;
+ } else {
+ t1Name = typenameHelper<T1>();
+ }
+ if constexpr (bool(QMetaTypeId2<T2>::IsBuiltIn)) {
+ t2Name = QMetaTypeId2<T2>::nameAsArray;
+ } else {
+ t2Name = typenameHelper<T2>();
+ }
+ constexpr auto nonTypeDependentLen = sizeof("std::pair<,>");
+ constexpr auto t1Len = t1Name.size() - 1;
+ constexpr auto t2Len = t2Name.size() - 1;
+ constexpr auto length = nonTypeDependentLen + t1Len + t2Len;
+ std::array<char, length + 1> result {};
+ constexpr auto prefix = "std::pair<";
+ int currentLength = 0;
+ for (; currentLength < int(sizeof("std::pair<") - 1); ++currentLength)
+ result[currentLength] = prefix[currentLength];
+ for (int i = 0; i < int(t1Len); ++currentLength, ++i)
+ result[currentLength] = t1Name[i];
+ result[currentLength++] = ',';
+ for (int i = 0; i < int(t2Len); ++currentLength, ++i)
+ result[currentLength] = t2Name[i];
+ result[currentLength++] = '>';
+ result[currentLength++] = '\0';
+ return result;
+ } else {
+ constexpr auto prefix = sizeof(
#ifdef QT_NAMESPACE
- QT_STRINGIFY(QT_NAMESPACE) "::"
+ QT_STRINGIFY(QT_NAMESPACE) "::"
#endif
-#ifdef Q_CC_MSVC
- "auto __cdecl QtPrivate::typenameHelper<"
+#if defined(Q_CC_MSVC) && defined(Q_CC_CLANG)
+ "auto __cdecl QtPrivate::TypeNameHelper::typenameHelper(void) [T = "
+#elif defined(Q_CC_MSVC)
+ "auto __cdecl QtPrivate::TypeNameHelper::typenameHelper<"
#elif defined(Q_CC_CLANG)
- "auto QtPrivate::typenameHelper() [T = "
+ "auto QtPrivate::TypeNameHelper::typenameHelper() [T = "
+#elif defined(Q_CC_GHS)
+ "auto QtPrivate::TypeNameHelper::typenameHelper<T>()[with T="
#else
- "constexpr auto QtPrivate::typenameHelper() [with T = "
+ "constexpr auto QtPrivate::TypeNameHelper::typenameHelper() [with T = "
#endif
- ) - 1;
-#ifdef Q_CC_MSVC
- constexpr int suffix = sizeof(">(void)");
+ ) - 1;
+#if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
+ constexpr int suffix = sizeof(">(void)");
#else
- constexpr int suffix = sizeof("]");
+ 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;
+#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU_ONLY < 804
+ 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
+ constexpr int len = sizeof(Q_FUNC_INFO) - suffix - prefix;
+#else
+ 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 = QTypeNormalizer{ nullptr }.normalizeTypeFromSignature(begin, end);
#endif
- std::array<char, len + 1> result {};
- qNormalizeType(begin, end, result.data());
- return result;
+ std::array<char, len + 1> result {};
+ QTypeNormalizer{ result.data() }.normalizeTypeFromSignature(begin, end);
+ return result;
+ }
}
+} // namespace TypeNameHelper
+using TypeNameHelper::typenameHelper;
template<typename T, typename = void>
struct BuiltinMetaType : std::integral_constant<int, 0>
@@ -2624,11 +2345,14 @@ struct BuiltinMetaType<T, std::enable_if_t<QMetaTypeId2<T>::IsBuiltIn>>
{
};
-template<typename T, bool = QTypeTraits::has_operator_equal_v<T>>
+template<typename T, bool = (QTypeTraits::has_operator_equal_v<T> && !std::is_pointer_v<T>)>
struct QEqualityOperatorForType
{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_FLOAT_COMPARE
static bool equals(const QMetaTypeInterface *, const void *a, const void *b)
{ return *reinterpret_cast<const T *>(a) == *reinterpret_cast<const T *>(b); }
+QT_WARNING_POP
};
template<typename T>
@@ -2637,7 +2361,7 @@ struct QEqualityOperatorForType <T, false>
static constexpr QMetaTypeInterface::EqualsFn equals = nullptr;
};
-template<typename T, bool = QTypeTraits::has_operator_less_than_v<T>>
+template<typename T, bool = (QTypeTraits::has_operator_less_than_v<T> && !std::is_pointer_v<T>)>
struct QLessThanOperatorForType
{
static bool lessThan(const QMetaTypeInterface *, const void *a, const void *b)
@@ -2650,168 +2374,208 @@ struct QLessThanOperatorForType <T, false>
static constexpr QMetaTypeInterface::LessThanFn lessThan = nullptr;
};
+template<typename T, bool = (QTypeTraits::has_ostream_operator_v<QDebug, T> && !std::is_pointer_v<T>)>
+struct QDebugStreamOperatorForType
+{
+ static void debugStream(const QMetaTypeInterface *, QDebug &dbg, const void *a)
+ { dbg << *reinterpret_cast<const T *>(a); }
+};
+
+template<typename T>
+struct QDebugStreamOperatorForType <T, false>
+{
+ static constexpr QMetaTypeInterface::DebugStreamFn debugStream = nullptr;
+};
+
+template<typename T, bool = QTypeTraits::has_stream_operator_v<QDataStream, T>>
+struct QDataStreamOperatorForType
+{
+ static constexpr QMetaTypeInterface::DataStreamOutFn dataStreamOut = nullptr;
+ static constexpr QMetaTypeInterface::DataStreamInFn dataStreamIn = nullptr;
+};
+
+#ifndef QT_NO_DATASTREAM
+template<typename T>
+struct QDataStreamOperatorForType <T, true>
+{
+ static void dataStreamOut(const QMetaTypeInterface *, QDataStream &ds, const void *a)
+ { ds << *reinterpret_cast<const T *>(a); }
+ static void dataStreamIn(const QMetaTypeInterface *, QDataStream &ds, void *a)
+ { ds >> *reinterpret_cast<T *>(a); }
+};
+#endif
+
+// Performance optimization:
+//
+// Don't add all these symbols to the dynamic symbol tables on ELF systems and
+// on Darwin. Each library is going to have a copy anyway and QMetaType already
+// copes with some of these being "hidden" (see QMetaType::idHelper()). We may
+// as well let the linker know it can always use the local copy.
+//
+// This is currently not enabled for GCC due to
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106023
+
+#if !defined(Q_OS_WIN) && defined(Q_CC_CLANG)
+# pragma GCC visibility push(hidden)
+#endif
+
template<typename S>
class QMetaTypeForType
{
- static const decltype(typenameHelper<S>()) name;
+public:
+ static constexpr decltype(typenameHelper<S>()) name = typenameHelper<S>();
+ static constexpr unsigned Flags = QMetaTypeTypeFlags<S>::Flags;
- template<typename T>
static constexpr QMetaTypeInterface::DefaultCtrFn getDefaultCtr()
{
- if constexpr (std::is_default_constructible_v<T>) {
- return [](const QMetaTypeInterface *, void *addr) { new (addr) T(); };
- } else {
- return nullptr;
- }
+ if constexpr (std::is_default_constructible_v<S> && !QTypeInfo<S>::isValueInitializationBitwiseZero) {
+ return [](const QMetaTypeInterface *, void *addr) { new (addr) S(); };
+ } else {
+ return nullptr;
+ }
}
- template<typename T>
static constexpr QMetaTypeInterface::CopyCtrFn getCopyCtr()
{
- 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;
- }
+ if constexpr (std::is_copy_constructible_v<S> && !std::is_trivially_copy_constructible_v<S>) {
+ return [](const QMetaTypeInterface *, void *addr, const void *other) {
+ new (addr) S(*reinterpret_cast<const S *>(other));
+ };
+ } else {
+ return nullptr;
+ }
}
- template<typename T>
static constexpr QMetaTypeInterface::MoveCtrFn getMoveCtr()
{
- 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;
- }
+ if constexpr (std::is_move_constructible_v<S> && !std::is_trivially_move_constructible_v<S>) {
+ return [](const QMetaTypeInterface *, void *addr, void *other) {
+ new (addr) S(std::move(*reinterpret_cast<S *>(other)));
+ };
+ } else {
+ return nullptr;
+ }
}
- template<typename T>
static constexpr QMetaTypeInterface::DtorFn getDtor()
{
- if constexpr (std::is_destructible_v<T>)
- return [](const QMetaTypeInterface *, void *addr) { reinterpret_cast<T *>(addr)->~T(); };
- else
- return nullptr;
+ if constexpr (std::is_destructible_v<S> && !std::is_trivially_destructible_v<S>)
+ return [](const QMetaTypeInterface *, void *addr) {
+ reinterpret_cast<S *>(addr)->~S();
+ };
+ else
+ return nullptr;
}
- template<typename T>
static constexpr QMetaTypeInterface::LegacyRegisterOp getLegacyRegister()
{
- if constexpr (QMetaTypeId2<T>::Defined && !QMetaTypeId2<T>::IsBuiltIn) {
- return []() { QMetaTypeId2<T>::qt_metatype_id(); };
- } else {
- return nullptr;
- }
+ if constexpr (QMetaTypeId2<S>::Defined && !QMetaTypeId2<S>::IsBuiltIn) {
+ return []() { QMetaTypeId2<S>::qt_metatype_id(); };
+ } else {
+ return nullptr;
+ }
}
static constexpr const char *getName()
{
if constexpr (bool(QMetaTypeId2<S>::IsBuiltIn)) {
- return QMetaTypeId2<S>::name;
+ return QMetaTypeId2<S>::nameAsArray.data();
} else {
return name.data();
}
}
-
-public:
- static QMetaTypeInterface metaType;
};
template<typename T>
-QMetaTypeInterface QMetaTypeForType<T>::metaType = {
- /*.revision=*/ 0,
- /*.size=*/ sizeof(T),
- /*.alignment=*/ alignof(T),
- /*.flags=*/ QMetaTypeTypeFlags<T>::Flags,
- /*.metaObject=*/ MetaObjectForType<T>::value(),
- /*.name=*/ getName(),
- /*.typeId=*/ BuiltinMetaType<T>::value,
- /*.ref=*/ Q_REFCOUNT_INITIALIZE_STATIC,
- /*.deleteSelf=*/ nullptr,
- /*.defaultCtr=*/ getDefaultCtr<T>(),
- /*.copyCtr=*/ getCopyCtr<T>(),
- /*.moveCtr=*/ getMoveCtr<T>(),
- /*.dtor=*/ getDtor<T>(),
- /*.equals=*/ QEqualityOperatorForType<T>::equals,
- /*.lessThan=*/ QLessThanOperatorForType<T>::lessThan,
- /*.legacyRegisterOp=*/ getLegacyRegister<T>()
+struct QMetaTypeInterfaceWrapper
+{
+ // if the type ID for T is known at compile-time, then we can declare
+ // the QMetaTypeInterface object const; otherwise, we declare it as
+ // non-const and the .typeId is updated by QMetaType::idHelper().
+ static constexpr bool IsConstMetaTypeInterface = !!BuiltinMetaType<T>::value;
+ using InterfaceType = std::conditional_t<IsConstMetaTypeInterface, const QMetaTypeInterface, NonConstMetaTypeInterface>;
+
+ static inline InterfaceType metaType = {
+ /*.revision=*/ QMetaTypeInterface::CurrentRevision,
+ /*.alignment=*/ alignof(T),
+ /*.size=*/ sizeof(T),
+ /*.flags=*/ QMetaTypeForType<T>::Flags,
+ /*.typeId=*/ BuiltinMetaType<T>::value,
+ /*.metaObjectFn=*/ MetaObjectForType<T>::metaObjectFunction,
+ /*.name=*/ QMetaTypeForType<T>::getName(),
+ /*.defaultCtr=*/ QMetaTypeForType<T>::getDefaultCtr(),
+ /*.copyCtr=*/ QMetaTypeForType<T>::getCopyCtr(),
+ /*.moveCtr=*/ QMetaTypeForType<T>::getMoveCtr(),
+ /*.dtor=*/ QMetaTypeForType<T>::getDtor(),
+ /*.equals=*/ QEqualityOperatorForType<T>::equals,
+ /*.lessThan=*/ QLessThanOperatorForType<T>::lessThan,
+ /*.debugStream=*/ QDebugStreamOperatorForType<T>::debugStream,
+ /*.dataStreamOut=*/ QDataStreamOperatorForType<T>::dataStreamOut,
+ /*.dataStreamIn=*/ QDataStreamOperatorForType<T>::dataStreamIn,
+ /*.legacyRegisterOp=*/ QMetaTypeForType<T>::getLegacyRegister()
+ };
};
-template<typename T>
-constexpr const decltype(typenameHelper<T>()) QMetaTypeForType<T>::name = typenameHelper<T>();
+#if !defined(Q_OS_WIN) && defined(Q_CC_CLANG)
+# pragma GCC visibility pop
+#endif
template<>
-class QMetaTypeForType<void>
+class QMetaTypeInterfaceWrapper<void>
{
- static const decltype(typenameHelper<void>()) name;
-
public:
- static inline QMetaTypeInterface metaType =
+ static constexpr QMetaTypeInterface metaType =
{
/*.revision=*/ 0,
- /*.size=*/ 0,
/*.alignment=*/ 0,
+ /*.size=*/ 0,
/*.flags=*/ 0,
- /*.metaObject=*/ nullptr,
- /*.name=*/ "void",
/*.typeId=*/ BuiltinMetaType<void>::value,
- /*.ref=*/ Q_REFCOUNT_INITIALIZE_STATIC,
- /*.deleteSelf=*/ nullptr,
+ /*.metaObjectFn=*/ nullptr,
+ /*.name=*/ "void",
/*.defaultCtr=*/ nullptr,
/*.copyCtr=*/ nullptr,
/*.moveCtr=*/ nullptr,
/*.dtor=*/ nullptr,
/*.equals=*/ nullptr,
/*.lessThan=*/ nullptr,
+ /*.debugStream=*/ nullptr,
+ /*.dataStreamOut=*/ nullptr,
+ /*.dataStreamIn=*/ nullptr,
/*.legacyRegisterOp=*/ nullptr
};
};
-#undef QT_METATYPE_CONSTEXPRLAMDA
-#ifndef QT_BOOTSTRAPPED
-#define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name) \
+/*
+ MSVC instantiates extern templates
+(https://developercommunity.visualstudio.com/t/c11-extern-templates-doesnt-work-for-class-templat/157868)
+
+ The INTEGRITY compiler apparently does too.
+
+ On Windows (with other compilers or whenever MSVC is fixed), we can't declare
+ QMetaTypeInterfaceWrapper with __declspec(dllimport) because taking its
+ address is not a core constant expression.
+ */
+#if !defined(QT_BOOTSTRAPPED) && !defined(Q_CC_MSVC) && !defined(Q_OS_INTEGRITY)
+
+#ifdef QT_NO_DATA_RELOCATION
+# 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
+#else
+# define QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER(TypeName, Id, Name) \
+ extern template class Q_CORE_EXPORT QMetaTypeForType<Name>; \
+ extern template struct Q_CORE_EXPORT QMetaTypeInterfaceWrapper<Name>;
+#endif
+
+QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
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>>;
- return &QMetaTypeForType<Ty>::metaType;
-}
-
-namespace detail {
-
-template <typename T, typename ODR_VIOLATION_PREVENTER>
-struct is_complete_helper {
- template <typename U>
- static auto check(U*) -> std::integral_constant<bool, sizeof(U) != 0>;
- static auto check(...) -> std::false_type;
- using type = decltype(check(static_cast<T*>(nullptr)));
-};
-
-}
-
-template <typename T, typename ODR_VIOLATION_PREVENTER>
-struct is_complete : detail::is_complete_helper<T, ODR_VIOLATION_PREVENTER>::type {};
-
-template<typename T>
struct qRemovePointerLike
{
using type = std::remove_pointer_t<T>;
@@ -2836,38 +2600,99 @@ struct TypeAndForceComplete
using ForceComplete = ForceComplete_;
};
+template<typename T>
+constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType()
+{
+ // don't check the type is suitable here
+ using Ty = typename MetatypeDecay<T>::type;
+ return &QMetaTypeInterfaceWrapper<Ty>::metaType;
+}
+
template<typename Unique, typename TypeCompletePair>
-constexpr QMetaTypeInterface *qTryMetaTypeInterfaceForType()
+constexpr const QMetaTypeInterface *qTryMetaTypeInterfaceForType()
{
using T = typename TypeCompletePair::type;
using ForceComplete = typename TypeCompletePair::ForceComplete;
- using Ty = std::remove_cv_t<std::remove_reference_t<T>>;
+ using Ty = typename MetatypeDecay<T>::type;
using Tz = qRemovePointerLike_t<Ty>;
- if constexpr (!is_complete<Tz, Unique>::value && !ForceComplete::value) {
+
+ if constexpr (std::is_void_v<Tz>) {
+ // early out to avoid expanding the rest of the templates
+ return &QMetaTypeInterfaceWrapper<Ty>::metaType;
+ } else if constexpr (ForceComplete::value) {
+ checkTypeIsSuitableForMetaType<Ty>();
+ return &QMetaTypeInterfaceWrapper<Ty>::metaType;
+ } else if constexpr (std::is_reference_v<Tz>) {
+ return nullptr;
+ } else if constexpr (!is_complete<Tz, Unique>::value) {
return nullptr;
} else {
- return &QMetaTypeForType<Ty>::metaType;
+ // don't check the type is suitable here
+ return &QMetaTypeInterfaceWrapper<Ty>::metaType;
}
}
} // namespace QtPrivate
template<typename T>
-QMetaType QMetaType::fromType()
+constexpr QMetaType QMetaType::fromType()
{
+ QtPrivate::checkTypeIsSuitableForMetaType<T>();
return QMetaType(QtPrivate::qMetaTypeInterfaceForType<T>());
}
+constexpr qsizetype QMetaType::sizeOf() const
+{
+ return d_ptr ? d_ptr->size : 0;
+}
+
+constexpr qsizetype QMetaType::alignOf() const
+{
+ return d_ptr ? d_ptr->alignment : 0;
+}
+
+constexpr QMetaType::TypeFlags QMetaType::flags() const
+{
+ return d_ptr ? TypeFlags(d_ptr->flags) : TypeFlags{};
+}
+
+constexpr const QMetaObject *QMetaType::metaObject() const
+{
+ return d_ptr && d_ptr->metaObjectFn ? d_ptr->metaObjectFn(d_ptr) : nullptr;
+}
+
template<typename... T>
-QtPrivate::QMetaTypeInterface *const qt_metaTypeArray[] = {
- QtPrivate::qMetaTypeInterfaceForType<T>()...
+constexpr const QtPrivate::QMetaTypeInterface *const qt_metaTypeArray[] = {
+ /*
+ Unique in qTryMetaTypeInterfaceForType does not have to be unique here
+ as we require _all_ types here to be actually complete.
+ We just want to have the additional type processing that exist in
+ QtPrivate::qTryMetaTypeInterfaceForType as opposed to the normal
+ QtPrivate::qMetaTypeInterfaceForType used in QMetaType::fromType
+ */
+ QtPrivate::qTryMetaTypeInterfaceForType<void, QtPrivate::TypeAndForceComplete<T, std::true_type>>()...
};
+constexpr const char *QMetaType::name() const
+{
+ return d_ptr ? d_ptr->name : nullptr;
+}
+
template<typename Unique,typename... T>
-QtPrivate::QMetaTypeInterface *const qt_incomplete_metaTypeArray[] = {
+constexpr const QtPrivate::QMetaTypeInterface *const qt_incomplete_metaTypeArray[] = {
QtPrivate::qTryMetaTypeInterfaceForType<Unique, T>()...
};
+inline size_t qHash(QMetaType type, size_t seed = 0)
+{
+ // We cannot use d_ptr here since the same type in different DLLs
+ // might result in different pointers!
+ return qHash(type.id(), seed);
+}
+
QT_END_NAMESPACE
+QT_DECL_METATYPE_EXTERN_TAGGED(QtMetaTypePrivate::QPairVariantInterfaceImpl,
+ QPairVariantInterfaceImpl, Q_CORE_EXPORT)
+
#endif // QMETATYPE_H