Make QMetaTypeInterface constexpr on Windows
This was so far problematic as it gave various link errors. The solution to that seems to be to make the default constructor of QPairVariantInterfaceImpl constexpr to get around one set of problems. The other problem to solve where undefined references to metaobjects. The reason for that is apparently that QMetaTypeInterface contains a direct pointer to the meta object, something the linker doesn't like. Adding a level of indirection by using a function that returns the pointer seems to solve that problem. Fixes: QTBUG-88468 Change-Id: I5612ae807ea3b7e49bc40349d8d1fca1be9bd7ee Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
185d212bf5
commit
b4c1747612
@ -698,7 +698,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
QPairVariantInterfaceImpl()
|
||||
constexpr QPairVariantInterfaceImpl()
|
||||
: _pair(nullptr)
|
||||
, _getFirst(nullptr)
|
||||
, _getSecond(nullptr)
|
||||
@ -818,36 +818,44 @@ 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; }
|
||||
static constexpr const QMetaObject *value() { return nullptr; }
|
||||
using MetaObjectFn = const QMetaObject *(*)(const QMetaTypeInterface *);
|
||||
static constexpr MetaObjectFn metaObjectFunction = 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; }
|
||||
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
|
||||
|
||||
@ -1590,7 +1598,10 @@ public:
|
||||
uint size;
|
||||
uint flags;
|
||||
mutable QBasicAtomicInt typeId;
|
||||
const QMetaObject *metaObject;
|
||||
|
||||
using MetaObjectFn = const QMetaObject *(*)(const QMetaTypeInterface *);
|
||||
const MetaObjectFn metaObjectFn;
|
||||
|
||||
const char *name;
|
||||
|
||||
using DefaultCtrFn = void (*)(const QMetaTypeInterface *, void *);
|
||||
@ -2224,42 +2235,27 @@ public:
|
||||
template<typename 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
|
||||
static inline constexpr const QMetaTypeInterface metaType = {
|
||||
/*.revision=*/ 0,
|
||||
/*.alignment=*/ alignof(T),
|
||||
/*.size=*/ sizeof(T),
|
||||
/*.flags=*/ QMetaTypeTypeFlags<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()
|
||||
};
|
||||
};
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
template<typename T>
|
||||
const QMetaTypeInterface QMetaTypeInterfaceWrapper<T>::metaType
|
||||
= QMetaTypeInterfaceWrapper<T>::create();
|
||||
#endif
|
||||
|
||||
template<>
|
||||
class QMetaTypeInterfaceWrapper<void>
|
||||
@ -2272,7 +2268,7 @@ public:
|
||||
/*.size=*/ 0,
|
||||
/*.flags=*/ 0,
|
||||
/*.typeId=*/ BuiltinMetaType<void>::value,
|
||||
/*.metaObject=*/ nullptr,
|
||||
/*.metaObjectFn=*/ nullptr,
|
||||
/*.name=*/ "void",
|
||||
/*.defaultCtr=*/ nullptr,
|
||||
/*.copyCtr=*/ nullptr,
|
||||
@ -2395,7 +2391,7 @@ constexpr QMetaType::TypeFlags QMetaType::flags() const
|
||||
|
||||
constexpr const QMetaObject *QMetaType::metaObject() const
|
||||
{
|
||||
return d_ptr ? d_ptr->metaObject : nullptr;
|
||||
return d_ptr && d_ptr->metaObjectFn ? d_ptr->metaObjectFn(d_ptr) : nullptr;
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
|
@ -413,19 +413,30 @@ void tst_QMetaType::registerGadget(const char *name, const QList<GadgetPropertyT
|
||||
meta->d.static_metacall = &GadgetsStaticMetacallFunction;
|
||||
meta->d.superdata = nullptr;
|
||||
const auto flags = QMetaType::IsGadget | QMetaType::NeedsConstruction | QMetaType::NeedsDestruction;
|
||||
using TypeInfo = QtPrivate::QMetaTypeInterface;
|
||||
struct TypeInfo : public QtPrivate::QMetaTypeInterface
|
||||
{
|
||||
QMetaObject *mo;
|
||||
};
|
||||
|
||||
auto typeInfo = new TypeInfo {
|
||||
0, alignof(GenericGadgetType), sizeof(GenericGadgetType), uint(flags), 0, meta, name,
|
||||
[](const TypeInfo *self, void *where) { GadgetTypedConstructor(self->typeId, where, nullptr); },
|
||||
[](const TypeInfo *self, void *where, const void *copy) { GadgetTypedConstructor(self->typeId, where, copy); },
|
||||
[](const TypeInfo *self, void *where, void *copy) { GadgetTypedConstructor(self->typeId, where, copy); },
|
||||
[](const TypeInfo *self, void *ptr) { GadgetTypedDestructor(self->typeId, ptr); },
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
GadgetSaveOperator,
|
||||
GadgetLoadOperator,
|
||||
nullptr
|
||||
{
|
||||
0, alignof(GenericGadgetType), sizeof(GenericGadgetType), uint(flags), 0,
|
||||
[](const QtPrivate::QMetaTypeInterface *self) -> const QMetaObject * {
|
||||
return reinterpret_cast<const TypeInfo *>(self)->mo;
|
||||
},
|
||||
name,
|
||||
[](const QtPrivate::QMetaTypeInterface *self, void *where) { GadgetTypedConstructor(self->typeId, where, nullptr); },
|
||||
[](const QtPrivate::QMetaTypeInterface *self, void *where, const void *copy) { GadgetTypedConstructor(self->typeId, where, copy); },
|
||||
[](const QtPrivate::QMetaTypeInterface *self, void *where, void *copy) { GadgetTypedConstructor(self->typeId, where, copy); },
|
||||
[](const QtPrivate::QMetaTypeInterface *self, void *ptr) { GadgetTypedDestructor(self->typeId, ptr); },
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
GadgetSaveOperator,
|
||||
GadgetLoadOperator,
|
||||
nullptr
|
||||
},
|
||||
meta
|
||||
};
|
||||
QMetaType gadgetMetaType(typeInfo);
|
||||
dynamicGadgetProperties->m_metatype = gadgetMetaType;
|
||||
|
Loading…
x
Reference in New Issue
Block a user