Make most of QMetaTypeInterface constexpr
The only thing we need to modify at runtime is the typeId and that can be mutable. This way we can have a constexpr ctor for QMetaType which hopefully makes the importing and exporting of related symbols less fickle. On Windows we cannot make QMetaTypeForType constexpr as that leads to mysterious errors in other places. Until we figure out why that is, we just leave this class as non-constexpr. This reveals that qcoreapplication.h and qvariant.h are using QDebug without including it. We now get template instantiation errors. Include qdebug.h to avoid that. Change-Id: If1bf0437ada52459c59c6fa45bab3d22dfb0bc92 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
0b0acce5a7
commit
9ceedd5863
@ -49,6 +49,9 @@
|
||||
#else
|
||||
#include <QtCore/qscopedpointer.h>
|
||||
#endif
|
||||
#ifndef QT_NO_DEBUGSTREAM
|
||||
#include <QtCore/qdebug.h>
|
||||
#endif
|
||||
|
||||
#ifndef QT_NO_QOBJECT
|
||||
#if defined(Q_OS_WIN) && !defined(tagMSG)
|
||||
|
@ -50,7 +50,7 @@ class QMetaType;
|
||||
namespace QtPrivate {
|
||||
class QMetaTypeInterface;
|
||||
template<typename T>
|
||||
constexpr QMetaTypeInterface *qMetaTypeInterfaceForType();
|
||||
constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType();
|
||||
}
|
||||
|
||||
namespace QtMetaContainerPrivate {
|
||||
@ -132,7 +132,7 @@ public:
|
||||
class QMetaSequenceInterface : public QMetaContainerInterface
|
||||
{
|
||||
public:
|
||||
QtPrivate::QMetaTypeInterface *valueMetaType;
|
||||
const QtPrivate::QMetaTypeInterface *valueMetaType;
|
||||
AddRemoveCapabilities addRemoveCapabilities;
|
||||
|
||||
using ValueAtIndexFn = void(*)(const void *, qsizetype, void *);
|
||||
@ -183,8 +183,8 @@ public:
|
||||
class QMetaAssociationInterface : public QMetaContainerInterface
|
||||
{
|
||||
public:
|
||||
QtPrivate::QMetaTypeInterface *keyMetaType;
|
||||
QtPrivate::QMetaTypeInterface *mappedMetaType;
|
||||
const QtPrivate::QMetaTypeInterface *keyMetaType;
|
||||
const QtPrivate::QMetaTypeInterface *mappedMetaType;
|
||||
|
||||
using InsertKeyFn = void(*)(void *, const void *);
|
||||
InsertKeyFn insertKeyFn;
|
||||
@ -470,7 +470,7 @@ class QMetaSequenceForContainer : public QMetaContainerForContainer<C>
|
||||
{
|
||||
friend QMetaSequenceInterface;
|
||||
|
||||
static constexpr QtPrivate::QMetaTypeInterface *getValueMetaType()
|
||||
static constexpr const QtPrivate::QMetaTypeInterface *getValueMetaType()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_value_type_v<C>)
|
||||
return QtPrivate::qMetaTypeInterfaceForType<typename C::value_type>();
|
||||
@ -697,7 +697,7 @@ class QMetaAssociationForContainer : public QMetaContainerForContainer<C>
|
||||
{
|
||||
friend QMetaAssociationInterface;
|
||||
|
||||
static constexpr QtPrivate::QMetaTypeInterface *getKeyMetaType()
|
||||
static constexpr const QtPrivate::QMetaTypeInterface *getKeyMetaType()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_key_type_v<C>)
|
||||
return QtPrivate::qMetaTypeInterfaceForType<typename C::key_type>();
|
||||
@ -705,7 +705,7 @@ class QMetaAssociationForContainer : public QMetaContainerForContainer<C>
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static constexpr QtPrivate::QMetaTypeInterface *getMappedMetaType()
|
||||
static constexpr const QtPrivate::QMetaTypeInterface *getMappedMetaType()
|
||||
{
|
||||
if constexpr (QContainerTraits::has_mapped_type_v<C>)
|
||||
return QtPrivate::qMetaTypeInterfaceForType<typename C::mapped_type>();
|
||||
|
@ -107,12 +107,12 @@ struct DefinedTypesFilter {
|
||||
struct QMetaTypeCustomRegistry
|
||||
{
|
||||
QReadWriteLock lock;
|
||||
QList<QtPrivate::QMetaTypeInterface *> registry;
|
||||
QHash<QByteArray, QtPrivate::QMetaTypeInterface *> aliases;
|
||||
QList<const QtPrivate::QMetaTypeInterface *> registry;
|
||||
QHash<QByteArray, const QtPrivate::QMetaTypeInterface *> aliases;
|
||||
// index of first empty (unregistered) type in registry, if any.
|
||||
int firstEmpty = 0;
|
||||
|
||||
int registerCustomType(QtPrivate::QMetaTypeInterface *ti)
|
||||
int registerCustomType(const QtPrivate::QMetaTypeInterface *ti)
|
||||
{
|
||||
{
|
||||
QWriteLocker l(&lock);
|
||||
@ -168,7 +168,7 @@ struct QMetaTypeCustomRegistry
|
||||
firstEmpty = std::min(firstEmpty, idx);
|
||||
}
|
||||
|
||||
QtPrivate::QMetaTypeInterface *getCustomType(int id)
|
||||
const QtPrivate::QMetaTypeInterface *getCustomType(int id)
|
||||
{
|
||||
QReadLocker l(&lock);
|
||||
return registry.value(id - QMetaType::User - 1);
|
||||
@ -847,7 +847,7 @@ static const struct : QMetaTypeModuleHelper
|
||||
return !(str.isEmpty() || str == LiteralWrapper("0") || str == LiteralWrapper("false"));
|
||||
}
|
||||
|
||||
QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override {
|
||||
const QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override {
|
||||
switch (type) {
|
||||
QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(QT_METATYPE_CONVERT_ID_TO_TYPE)
|
||||
QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(QT_METATYPE_CONVERT_ID_TO_TYPE)
|
||||
@ -2898,9 +2898,9 @@ QMetaType QMetaType::fromName(QByteArrayView typeName)
|
||||
\sa Q_DECLARE_METATYPE(), QMetaType::type()
|
||||
*/
|
||||
|
||||
static QtPrivate::QMetaTypeInterface *interfaceForType(int typeId)
|
||||
static const QtPrivate::QMetaTypeInterface *interfaceForType(int typeId)
|
||||
{
|
||||
QtPrivate::QMetaTypeInterface *iface = nullptr;
|
||||
const QtPrivate::QMetaTypeInterface *iface = nullptr;
|
||||
if (typeId >= QMetaType::User) {
|
||||
if (auto reg = customTypeRegistry())
|
||||
iface = reg->getCustomType(typeId);
|
||||
|
@ -399,7 +399,7 @@ public:
|
||||
static bool isRegistered(int type);
|
||||
|
||||
explicit QMetaType(int type);
|
||||
explicit constexpr QMetaType(QtPrivate::QMetaTypeInterface *d) : d_ptr(d) {}
|
||||
explicit constexpr QMetaType(const QtPrivate::QMetaTypeInterface *d) : d_ptr(d) {}
|
||||
constexpr QMetaType() = default;
|
||||
|
||||
bool isValid() const;
|
||||
@ -436,7 +436,7 @@ public:
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
static QMetaType fromType();
|
||||
constexpr static QMetaType fromType();
|
||||
static QMetaType fromName(QByteArrayView name);
|
||||
|
||||
friend bool operator==(QMetaType a, QMetaType b) { return a.d_ptr == b.d_ptr || a.id() == b.id(); }
|
||||
@ -647,11 +647,11 @@ public:
|
||||
static void unregisterMutableViewFunction(QMetaType from, QMetaType to);
|
||||
|
||||
static void unregisterMetaType(QMetaType type);
|
||||
QtPrivate::QMetaTypeInterface *iface() { return d_ptr; }
|
||||
const QtPrivate::QMetaTypeInterface *iface() { return d_ptr; }
|
||||
|
||||
private:
|
||||
friend class QVariant;
|
||||
QtPrivate::QMetaTypeInterface *d_ptr = nullptr;
|
||||
const QtPrivate::QMetaTypeInterface *d_ptr = nullptr;
|
||||
};
|
||||
|
||||
#undef QT_DEFINE_METATYPE_ID
|
||||
@ -1610,7 +1610,7 @@ public:
|
||||
ushort alignment;
|
||||
uint size;
|
||||
uint flags;
|
||||
QBasicAtomicInt typeId;
|
||||
mutable QBasicAtomicInt typeId;
|
||||
const QMetaObject *metaObject;
|
||||
const char *name;
|
||||
|
||||
@ -2179,56 +2179,52 @@ struct QDataStreamOperatorForType <T, false>
|
||||
template<typename S>
|
||||
class QMetaTypeForType
|
||||
{
|
||||
public:
|
||||
static constexpr decltype(typenameHelper<S>()) name = typenameHelper<S>();
|
||||
|
||||
template<typename T>
|
||||
static constexpr QMetaTypeInterface::DefaultCtrFn getDefaultCtr()
|
||||
{
|
||||
if constexpr (std::is_default_constructible_v<T>) {
|
||||
return [](const QMetaTypeInterface *, void *addr) { new (addr) T(); };
|
||||
if constexpr (std::is_default_constructible_v<S>) {
|
||||
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>) {
|
||||
if constexpr (std::is_copy_constructible_v<S>) {
|
||||
return [](const QMetaTypeInterface *, void *addr, const void *other) {
|
||||
new (addr) T(*reinterpret_cast<const T *>(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>) {
|
||||
if constexpr (std::is_move_constructible_v<S>) {
|
||||
return [](const QMetaTypeInterface *, void *addr, void *other) {
|
||||
new (addr) T(std::move(*reinterpret_cast<T *>(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(); };
|
||||
if constexpr (std::is_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(); };
|
||||
if constexpr (QMetaTypeId2<S>::Defined && !QMetaTypeId2<S>::IsBuiltIn) {
|
||||
return []() { QMetaTypeId2<S>::qt_metatype_id(); };
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
@ -2242,37 +2238,53 @@ class QMetaTypeForType
|
||||
return name.data();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static QMetaTypeInterface metaType;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
QMetaTypeInterface QMetaTypeForType<T>::metaType = {
|
||||
/*.revision=*/ 0,
|
||||
/*.alignment=*/ alignof(T),
|
||||
/*.size=*/ sizeof(T),
|
||||
/*.flags=*/ QMetaTypeTypeFlags<T>::Flags,
|
||||
/*.typeId=*/ BuiltinMetaType<T>::value,
|
||||
/*.metaObject=*/ MetaObjectForType<T>::value(),
|
||||
/*.name=*/ getName(),
|
||||
/*.defaultCtr=*/ getDefaultCtr<T>(),
|
||||
/*.copyCtr=*/ getCopyCtr<T>(),
|
||||
/*.moveCtr=*/ getMoveCtr<T>(),
|
||||
/*.dtor=*/ getDtor<T>(),
|
||||
/*.equals=*/ QEqualityOperatorForType<T>::equals,
|
||||
/*.lessThan=*/ QLessThanOperatorForType<T>::lessThan,
|
||||
/*.debugStream=*/ QDebugStreamOperatorForType<T>::debugStream,
|
||||
/*.dataStreamOut=*/ QDataStreamOperatorForType<T>::dataStreamOut,
|
||||
/*.dataStreamIn=*/ QDataStreamOperatorForType<T>::dataStreamIn,
|
||||
/*.legacyRegisterOp=*/ getLegacyRegister<T>()
|
||||
struct QMetaTypeInterfaceWrapper
|
||||
{
|
||||
static inline constexpr QMetaTypeInterface create()
|
||||
{
|
||||
return {
|
||||
/*.revision=*/ 0,
|
||||
/*.alignment=*/ alignof(T),
|
||||
/*.size=*/ sizeof(T),
|
||||
/*.flags=*/ QMetaTypeTypeFlags<T>::Flags,
|
||||
/*.typeId=*/ BuiltinMetaType<T>::value,
|
||||
/*.metaObject=*/ MetaObjectForType<T>::value(),
|
||||
/*.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()
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// MSVC produces link errors when the metaType is constexpr
|
||||
static const QMetaTypeInterface metaType;
|
||||
#else
|
||||
static constexpr const QMetaTypeInterface metaType = create();
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
template<typename T>
|
||||
const QMetaTypeInterface QMetaTypeInterfaceWrapper<T>::metaType
|
||||
= QMetaTypeInterfaceWrapper<T>::create();
|
||||
#endif
|
||||
|
||||
template<>
|
||||
class QMetaTypeForType<void>
|
||||
class QMetaTypeInterfaceWrapper<void>
|
||||
{
|
||||
public:
|
||||
static inline QMetaTypeInterface metaType =
|
||||
static constexpr QMetaTypeInterface metaType =
|
||||
{
|
||||
/*.revision=*/ 0,
|
||||
/*.alignment=*/ 0,
|
||||
@ -2318,10 +2330,10 @@ QT_FOR_EACH_STATIC_CORE_TEMPLATE(QT_METATYPE_DECLARE_EXTERN_TEMPLATE_ITER)
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
constexpr QMetaTypeInterface *qMetaTypeInterfaceForType()
|
||||
constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType()
|
||||
{
|
||||
using Ty = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
return &QMetaTypeForType<Ty>::metaType;
|
||||
return &QMetaTypeInterfaceWrapper<Ty>::metaType;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
@ -2365,7 +2377,7 @@ struct TypeAndForceComplete
|
||||
};
|
||||
|
||||
template<typename Unique, typename TypeCompletePair>
|
||||
constexpr QMetaTypeInterface *qTryMetaTypeInterfaceForType()
|
||||
constexpr const QMetaTypeInterface *qTryMetaTypeInterfaceForType()
|
||||
{
|
||||
using T = typename TypeCompletePair::type;
|
||||
using ForceComplete = typename TypeCompletePair::ForceComplete;
|
||||
@ -2374,25 +2386,25 @@ constexpr QMetaTypeInterface *qTryMetaTypeInterfaceForType()
|
||||
if constexpr (!is_complete<Tz, Unique>::value && !ForceComplete::value) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return &QMetaTypeForType<Ty>::metaType;
|
||||
return &QMetaTypeInterfaceWrapper<Ty>::metaType;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace QtPrivate
|
||||
|
||||
template<typename T>
|
||||
QMetaType QMetaType::fromType()
|
||||
constexpr QMetaType QMetaType::fromType()
|
||||
{
|
||||
return QMetaType(QtPrivate::qMetaTypeInterfaceForType<T>());
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
QtPrivate::QMetaTypeInterface *const qt_metaTypeArray[] = {
|
||||
constexpr const QtPrivate::QMetaTypeInterface *const qt_metaTypeArray[] = {
|
||||
QtPrivate::qMetaTypeInterfaceForType<T>()...
|
||||
};
|
||||
|
||||
template<typename Unique,typename... T>
|
||||
QtPrivate::QMetaTypeInterface *const qt_incomplete_metaTypeArray[] = {
|
||||
constexpr const QtPrivate::QMetaTypeInterface *const qt_incomplete_metaTypeArray[] = {
|
||||
QtPrivate::qTryMetaTypeInterfaceForType<Unique, T>()...
|
||||
};
|
||||
|
||||
|
@ -154,7 +154,7 @@ public:
|
||||
return (quint64(from) << 32) + quint64(to);
|
||||
};
|
||||
|
||||
virtual QtPrivate::QMetaTypeInterface *interfaceForType(int) const = 0;
|
||||
virtual const QtPrivate::QMetaTypeInterface *interfaceForType(int) const = 0;
|
||||
virtual bool convert(const void *, int, void *, int) const { return false; }
|
||||
};
|
||||
|
||||
@ -221,10 +221,10 @@ template<> struct TypeDefinition<QIcon> { static const bool IsAvailable = false;
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
static QT_PREPEND_NAMESPACE(QtPrivate::QMetaTypeInterface) *getInterfaceFromType()
|
||||
static const QT_PREPEND_NAMESPACE(QtPrivate::QMetaTypeInterface) *getInterfaceFromType()
|
||||
{
|
||||
if constexpr (QtMetaTypePrivate::TypeDefinition<T>::IsAvailable) {
|
||||
return &QT_PREPEND_NAMESPACE(QtPrivate::QMetaTypeForType)<T>::metaType;
|
||||
return &QT_PREPEND_NAMESPACE(QtPrivate::QMetaTypeInterfaceWrapper)<T>::metaType;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -429,7 +429,7 @@ struct Q_CORE_EXPORT QMetaObject
|
||||
typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **);
|
||||
StaticMetacallFunction static_metacall;
|
||||
const SuperData *relatedMetaObjects;
|
||||
QtPrivate::QMetaTypeInterface *const *metaTypes;
|
||||
const QtPrivate::QMetaTypeInterface *const *metaTypes;
|
||||
void *extradata; //reserved for future use
|
||||
} d;
|
||||
|
||||
|
@ -49,6 +49,9 @@
|
||||
#include <QtCore/qstring.h>
|
||||
#include <QtCore/qstringlist.h>
|
||||
#include <QtCore/qobject.h>
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
#include <QtCore/qdebug.h>
|
||||
#endif
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
#include <QtCore/qbytearraylist.h>
|
||||
#endif
|
||||
|
@ -104,7 +104,7 @@ static const struct : QMetaTypeModuleHelper
|
||||
#define QT_IMPL_METATYPEINTERFACE_GUI_TYPES(MetaTypeName, MetaTypeId, RealName) \
|
||||
QT_METATYPE_INTERFACE_INIT(RealName),
|
||||
|
||||
QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override {
|
||||
const QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override {
|
||||
switch (type) {
|
||||
QT_FOR_EACH_STATIC_GUI_CLASS(QT_METATYPE_CONVERT_ID_TO_TYPE)
|
||||
default: return nullptr;
|
||||
|
@ -51,7 +51,7 @@ namespace {
|
||||
|
||||
static const struct : QMetaTypeModuleHelper
|
||||
{
|
||||
QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override {
|
||||
const QtPrivate::QMetaTypeInterface *interfaceForType(int type) const override {
|
||||
switch (type) {
|
||||
QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_METATYPE_CONVERT_ID_TO_TYPE)
|
||||
default: return nullptr;
|
||||
|
Loading…
Reference in New Issue
Block a user