QMetaType: don't record trivial construction function pointers
We can implement the trivial {default,copy,move} construction outselves
inside qmetatype.cpp and qvariant.cpp, simplifying the QMetaType
interface object, removing up to three relocations per QMTI.
This adds the testing for QMetaType::isXxxConstructible and
isDestructible that couldn't be added before.
Change-Id: Ic44396b31ba04712aab3fffd16ff0a28f541d507
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
bb10
parent
cfdaf9226d
commit
2e6398bd46
|
|
@ -414,7 +414,9 @@ const char *QtMetaTypePrivate::typedefNameForType(const QtPrivate::QMetaTypeInte
|
|||
|
||||
The enum describes attributes of a type supported by QMetaType.
|
||||
|
||||
\value NeedsConstruction This type has non-trivial constructors. If the flag is not set instances can be safely initialized with memset to 0.
|
||||
\value NeedsConstruction This type has a non-trivial default constructor. If the flag is not set, instances can be safely initialized with memset to 0.
|
||||
\value NeedsCopyConstruction (since 6.5) This type has a non-trivial copy construtcor. If the flag is not set, instances can be copied with memcpy.
|
||||
\value NeedsMoveConstruction (since 6.5) This type has a non-trivial move constructor. If the flag is not set, instances can be moved with memcpy.
|
||||
\value NeedsDestruction This type has a non-trivial destructor. If the flag is not set calls to the destructor are not necessary before discarding objects.
|
||||
\value RelocatableType An instance of a type having this attribute can be safely moved to a different memory location using memcpy.
|
||||
\omitvalue MovableType
|
||||
|
|
@ -429,6 +431,14 @@ const char *QtMetaTypePrivate::typedefNameForType(const QtPrivate::QMetaTypeInte
|
|||
\omitvalue PointerToGadget
|
||||
\omitvalue IsQmlList
|
||||
\value IsConst Indicates that values of this types are immutable; for instance because they are pointers to const objects.
|
||||
|
||||
\note Before Qt 6.5, both the NeedsConstruction and NeedsDestruction flags
|
||||
were incorrectly set if the either copy construtor or destructor were
|
||||
non-trivial (that is, if the type was not trivial).
|
||||
|
||||
Note that the Needs flags may be set but the meta type may not have a
|
||||
publicly-accessible constructor of the relevant type or a
|
||||
publicly-accessible destructor.
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
|
@ -598,16 +608,17 @@ int QMetaType::registerHelper(const QtPrivate::QMetaTypeInterface *iface)
|
|||
*/
|
||||
void *QMetaType::create(const void *copy) const
|
||||
{
|
||||
if (d_ptr && (copy ? !!d_ptr->copyCtr : !!d_ptr->defaultCtr)) {
|
||||
void *where =
|
||||
if (copy ? !isCopyConstructible() : !isDefaultConstructible())
|
||||
return nullptr;
|
||||
|
||||
void *where =
|
||||
#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
|
||||
d_ptr->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__ ?
|
||||
operator new(d_ptr->size, std::align_val_t(d_ptr->alignment)) :
|
||||
#endif
|
||||
operator new(d_ptr->size);
|
||||
return construct(where, copy);
|
||||
}
|
||||
return nullptr;
|
||||
QtMetaTypePrivate::construct(d_ptr, where, copy);
|
||||
return where;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -621,9 +632,8 @@ void *QMetaType::create(const void *copy) const
|
|||
*/
|
||||
void QMetaType::destroy(void *data) const
|
||||
{
|
||||
if (d_ptr) {
|
||||
if (d_ptr->dtor)
|
||||
d_ptr->dtor(d_ptr, data);
|
||||
if (data && isDestructible()) {
|
||||
QtMetaTypePrivate::destruct(d_ptr, data);
|
||||
if (d_ptr->alignment > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
|
||||
operator delete(data, std::align_val_t(d_ptr->alignment));
|
||||
} else {
|
||||
|
|
@ -662,16 +672,11 @@ void *QMetaType::construct(void *where, const void *copy) const
|
|||
{
|
||||
if (!where)
|
||||
return nullptr;
|
||||
if (d_ptr) {
|
||||
if (copy && d_ptr->copyCtr) {
|
||||
d_ptr->copyCtr(d_ptr, where, copy);
|
||||
return where;
|
||||
} else if (!copy && d_ptr->defaultCtr) {
|
||||
d_ptr->defaultCtr(d_ptr, where);
|
||||
return where;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
if (copy ? !isCopyConstructible() : !isDefaultConstructible())
|
||||
return nullptr;
|
||||
|
||||
QtMetaTypePrivate::construct(d_ptr, where, copy);
|
||||
return where;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -687,12 +692,8 @@ void *QMetaType::construct(void *where, const void *copy) const
|
|||
*/
|
||||
void QMetaType::destruct(void *data) const
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
if (d_ptr && d_ptr->dtor) {
|
||||
d_ptr->dtor(d_ptr, data);
|
||||
return;
|
||||
}
|
||||
if (data && isDestructible())
|
||||
QtMetaTypePrivate::destruct(d_ptr, data);
|
||||
}
|
||||
|
||||
static QPartialOrdering threeWayCompare(const void *ptr1, const void *ptr2)
|
||||
|
|
|
|||
|
|
@ -381,6 +381,9 @@ public:
|
|||
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)
|
||||
|
||||
|
|
@ -1187,8 +1190,10 @@ namespace QtPrivate {
|
|||
struct QMetaTypeTypeFlags
|
||||
{
|
||||
enum { Flags = (QTypeInfo<T>::isRelocatable ? QMetaType::RelocatableType : 0)
|
||||
| (QTypeInfo<T>::isComplex ? QMetaType::NeedsConstruction : 0)
|
||||
| (QTypeInfo<T>::isComplex ? QMetaType::NeedsDestruction : 0)
|
||||
| (!std::is_trivially_default_constructible_v<T> ? 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)
|
||||
|
|
@ -2312,10 +2317,11 @@ class QMetaTypeForType
|
|||
{
|
||||
public:
|
||||
static constexpr decltype(typenameHelper<S>()) name = typenameHelper<S>();
|
||||
static constexpr unsigned Flags = QMetaTypeTypeFlags<S>::Flags;
|
||||
|
||||
static constexpr QMetaTypeInterface::DefaultCtrFn getDefaultCtr()
|
||||
{
|
||||
if constexpr (std::is_default_constructible_v<S>) {
|
||||
if constexpr (std::is_default_constructible_v<S> && !std::is_trivially_default_constructible_v<S>) {
|
||||
return [](const QMetaTypeInterface *, void *addr) { new (addr) S(); };
|
||||
} else {
|
||||
return nullptr;
|
||||
|
|
@ -2324,7 +2330,7 @@ public:
|
|||
|
||||
static constexpr QMetaTypeInterface::CopyCtrFn getCopyCtr()
|
||||
{
|
||||
if constexpr (std::is_copy_constructible_v<S>) {
|
||||
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));
|
||||
};
|
||||
|
|
@ -2335,7 +2341,7 @@ public:
|
|||
|
||||
static constexpr QMetaTypeInterface::MoveCtrFn getMoveCtr()
|
||||
{
|
||||
if constexpr (std::is_move_constructible_v<S>) {
|
||||
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)));
|
||||
};
|
||||
|
|
@ -2386,7 +2392,7 @@ struct QMetaTypeInterfaceWrapper
|
|||
/*.revision=*/ 0,
|
||||
/*.alignment=*/ alignof(T),
|
||||
/*.size=*/ sizeof(T),
|
||||
/*.flags=*/ QMetaTypeTypeFlags<T>::Flags,
|
||||
/*.flags=*/ QMetaTypeForType<T>::Flags,
|
||||
/*.typeId=*/ BuiltinMetaType<T>::value,
|
||||
/*.metaObjectFn=*/ MetaObjectForType<T>::metaObjectFunction,
|
||||
/*.name=*/ QMetaTypeForType<T>::getName(),
|
||||
|
|
|
|||
|
|
@ -141,21 +141,52 @@ inline bool isDefaultConstructible(const QtPrivate::QMetaTypeInterface *iface) n
|
|||
|
||||
inline bool isCopyConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
|
||||
{
|
||||
// ### broken
|
||||
return checkMetaTypeFlagOrPointer(iface, iface->copyCtr, QMetaType::NeedsConstruction);
|
||||
return checkMetaTypeFlagOrPointer(iface, iface->copyCtr, QMetaType::NeedsCopyConstruction);
|
||||
}
|
||||
|
||||
inline bool isMoveConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
|
||||
{
|
||||
return iface->moveCtr;
|
||||
return checkMetaTypeFlagOrPointer(iface, iface->moveCtr, QMetaType::NeedsMoveConstruction);
|
||||
}
|
||||
|
||||
inline bool isDestructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
|
||||
{
|
||||
// ### broken
|
||||
return checkMetaTypeFlagOrPointer(iface, iface->dtor, QMetaType::NeedsDestruction);
|
||||
}
|
||||
|
||||
inline void defaultConstruct(const QtPrivate::QMetaTypeInterface *iface, void *where)
|
||||
{
|
||||
Q_ASSERT(isDefaultConstructible(iface));
|
||||
if (iface->defaultCtr)
|
||||
iface->defaultCtr(iface, where);
|
||||
else
|
||||
memset(where, 0, iface->size);
|
||||
}
|
||||
|
||||
inline void copyConstruct(const QtPrivate::QMetaTypeInterface *iface, void *where, const void *copy)
|
||||
{
|
||||
Q_ASSERT(isCopyConstructible(iface));
|
||||
if (iface->copyCtr)
|
||||
iface->copyCtr(iface, where, copy);
|
||||
else
|
||||
memcpy(where, copy, iface->size);
|
||||
}
|
||||
|
||||
inline void construct(const QtPrivate::QMetaTypeInterface *iface, void *where, const void *copy)
|
||||
{
|
||||
if (copy)
|
||||
copyConstruct(iface, where, copy);
|
||||
else
|
||||
defaultConstruct(iface, where);
|
||||
}
|
||||
|
||||
inline void destruct(const QtPrivate::QMetaTypeInterface *iface, void *where)
|
||||
{
|
||||
Q_ASSERT(isDestructible(iface));
|
||||
if (iface->dtor)
|
||||
iface->dtor(iface, where);
|
||||
}
|
||||
|
||||
const char *typedefNameForType(const QtPrivate::QMetaTypeInterface *type_d);
|
||||
|
||||
template<typename T>
|
||||
|
|
|
|||
|
|
@ -222,7 +222,8 @@ static void customConstruct(QVariant::Private *d, const void *copy)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!isCopyConstructible(iface) || (!copy && !isDefaultConstructible(iface))) {
|
||||
if (!isCopyConstructible(iface) || (!copy && !isDefaultConstructible(iface))
|
||||
|| !isDestructible(iface)) {
|
||||
*d = QVariant::Private();
|
||||
qWarning("QVariant: Provided metatype does not support "
|
||||
"destruction, copy and default construction");
|
||||
|
|
|
|||
|
|
@ -397,14 +397,16 @@ protected:
|
|||
++failureCount;
|
||||
qWarning() << "Wrong typeInfo returned for" << tp;
|
||||
}
|
||||
if (info.flags() != (QMetaType::NeedsConstruction | QMetaType::NeedsDestruction |
|
||||
QMetaType::NeedsCopyConstruction | QMetaType::NeedsMoveConstruction)) {
|
||||
++failureCount;
|
||||
qWarning() << "Wrong typeInfo returned for" << tp << "got"
|
||||
<< Qt::showbase << Qt::hex << info.flags();
|
||||
}
|
||||
if (!info.isRegistered()) {
|
||||
++failureCount;
|
||||
qWarning() << name << "is not a registered metatype";
|
||||
}
|
||||
if (QMetaType::typeFlags(tp) != (QMetaType::NeedsConstruction | QMetaType::NeedsDestruction)) {
|
||||
++failureCount;
|
||||
qWarning() << "Wrong typeInfo returned for" << tp;
|
||||
}
|
||||
if (!QMetaType::isRegistered(tp)) {
|
||||
++failureCount;
|
||||
qWarning() << name << "is not a registered metatype";
|
||||
|
|
@ -981,7 +983,9 @@ template <typename T> void addFlagsRow(const char *name, int id = qMetaTypeId<T>
|
|||
QTest::newRow(name)
|
||||
<< id
|
||||
<< bool(QTypeInfo<T>::isRelocatable)
|
||||
<< bool(QTypeInfo<T>::isComplex)
|
||||
<< bool(!std::is_trivially_default_constructible_v<T>)
|
||||
<< bool(!std::is_trivially_copy_constructible_v<T>)
|
||||
<< bool(!std::is_trivially_destructible_v<T>)
|
||||
<< bool(QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value)
|
||||
<< bool(std::is_enum<T>::value)
|
||||
<< false;
|
||||
|
|
@ -991,15 +995,17 @@ void tst_QMetaType::flags_data()
|
|||
{
|
||||
QTest::addColumn<int>("type");
|
||||
QTest::addColumn<bool>("isRelocatable");
|
||||
QTest::addColumn<bool>("isComplex");
|
||||
QTest::addColumn<bool>("needsConstruction");
|
||||
QTest::addColumn<bool>("needsCopyConstruction");
|
||||
QTest::addColumn<bool>("needsDestruction");
|
||||
QTest::addColumn<bool>("isPointerToQObject");
|
||||
QTest::addColumn<bool>("isEnum");
|
||||
QTest::addColumn<bool>("isQmlList");
|
||||
|
||||
// invalid ids.
|
||||
QTest::newRow("-1") << -1 << false << false << false << false << false;
|
||||
QTest::newRow("-124125534") << -124125534 << false << false << false << false << false;
|
||||
QTest::newRow("124125534") << 124125534 << false << false << false << false << false;
|
||||
QTest::newRow("-1") << -1 << false << false << false << false << false << false << false;
|
||||
QTest::newRow("-124125534") << -124125534 << false << false << false << false << false << false << false;
|
||||
QTest::newRow("124125534") << 124125534 << false << false << false << false << false << false << false;
|
||||
|
||||
#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
|
||||
addFlagsRow<RealType>(#RealType, MetaTypeId);
|
||||
|
|
@ -1029,7 +1035,9 @@ void tst_QMetaType::flags()
|
|||
{
|
||||
QFETCH(int, type);
|
||||
QFETCH(bool, isRelocatable);
|
||||
QFETCH(bool, isComplex);
|
||||
QFETCH(bool, needsConstruction);
|
||||
QFETCH(bool, needsCopyConstruction);
|
||||
QFETCH(bool, needsDestruction);
|
||||
QFETCH(bool, isPointerToQObject);
|
||||
QFETCH(bool, isEnum);
|
||||
QFETCH(bool, isQmlList);
|
||||
|
|
@ -1037,14 +1045,92 @@ void tst_QMetaType::flags()
|
|||
ignoreInvalidMetaTypeWarning(type);
|
||||
QMetaType meta(type);
|
||||
|
||||
QCOMPARE(bool(meta.flags() & QMetaType::NeedsConstruction), isComplex);
|
||||
QCOMPARE(bool(meta.flags() & QMetaType::NeedsDestruction), isComplex);
|
||||
QCOMPARE(bool(meta.flags() & QMetaType::NeedsConstruction), needsConstruction);
|
||||
QCOMPARE(bool(meta.flags() & QMetaType::NeedsCopyConstruction), needsCopyConstruction);
|
||||
QCOMPARE(bool(meta.flags() & QMetaType::NeedsDestruction), needsDestruction);
|
||||
QCOMPARE(bool(meta.flags() & QMetaType::RelocatableType), isRelocatable);
|
||||
QCOMPARE(bool(meta.flags() & QMetaType::PointerToQObject), isPointerToQObject);
|
||||
QCOMPARE(bool(meta.flags() & QMetaType::IsEnumeration), isEnum);
|
||||
QCOMPARE(bool(meta.flags() & QMetaType::IsQmlList), isQmlList);
|
||||
}
|
||||
|
||||
class NonDefaultConstructible
|
||||
{
|
||||
NonDefaultConstructible(int) {}
|
||||
};
|
||||
|
||||
struct MoveOnly
|
||||
{
|
||||
MoveOnly() = default;
|
||||
MoveOnly(const MoveOnly &) = delete;
|
||||
MoveOnly(MoveOnly &&) = default;
|
||||
MoveOnly &operator=(const MoveOnly &) = delete;
|
||||
MoveOnly &operator=(MoveOnly &&) = default;
|
||||
};
|
||||
|
||||
class Indestructible
|
||||
{
|
||||
protected:
|
||||
~Indestructible() {}
|
||||
};
|
||||
|
||||
template <typename T> static void addFlags2Row(QMetaType metaType = QMetaType::fromType<T>())
|
||||
{
|
||||
QTest::newRow(metaType.name() ? metaType.name() : "UnknownType")
|
||||
<< metaType
|
||||
<< std::is_default_constructible_v<T>
|
||||
<< std::is_copy_constructible_v<T>
|
||||
<< std::is_move_constructible_v<T>
|
||||
<< std::is_destructible_v<T>
|
||||
<< (QTypeTraits::has_operator_equal<T>::value || QTypeTraits::has_operator_less_than<T>::value)
|
||||
<< QTypeTraits::has_operator_less_than<T>::value;
|
||||
};
|
||||
|
||||
void tst_QMetaType::flags2_data()
|
||||
{
|
||||
QTest::addColumn<QMetaType>("type");
|
||||
QTest::addColumn<bool>("isDefaultConstructible");
|
||||
QTest::addColumn<bool>("isCopyConstructible");
|
||||
QTest::addColumn<bool>("isMoveConstructible");
|
||||
QTest::addColumn<bool>("isDestructible");
|
||||
QTest::addColumn<bool>("isEqualityComparable");
|
||||
QTest::addColumn<bool>("isOrdered");
|
||||
|
||||
addFlags2Row<void>(QMetaType());
|
||||
addFlags2Row<void>();
|
||||
|
||||
#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
|
||||
addFlags2Row<RealType>();
|
||||
QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(ADD_METATYPE_TEST_ROW)
|
||||
QT_FOR_EACH_STATIC_CORE_CLASS(ADD_METATYPE_TEST_ROW)
|
||||
QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(ADD_METATYPE_TEST_ROW)
|
||||
QT_FOR_EACH_STATIC_CORE_POINTER(ADD_METATYPE_TEST_ROW)
|
||||
#undef ADD_METATYPE_TEST_ROW
|
||||
|
||||
addFlags2Row<NonDefaultConstructible>();
|
||||
addFlags2Row<MoveOnly>();
|
||||
addFlags2Row<QObject>();
|
||||
addFlags2Row<Indestructible>();
|
||||
}
|
||||
|
||||
void tst_QMetaType::flags2()
|
||||
{
|
||||
QFETCH(QMetaType, type);
|
||||
QFETCH(bool, isDefaultConstructible);
|
||||
QFETCH(bool, isCopyConstructible);
|
||||
QFETCH(bool, isMoveConstructible);
|
||||
QFETCH(bool, isDestructible);
|
||||
QFETCH(bool, isEqualityComparable);
|
||||
QFETCH(bool, isOrdered);
|
||||
|
||||
QCOMPARE(type.isDefaultConstructible(), isDefaultConstructible);
|
||||
QCOMPARE(type.isCopyConstructible(), isCopyConstructible);
|
||||
QCOMPARE(type.isMoveConstructible(), isMoveConstructible);
|
||||
QCOMPARE(type.isDestructible(), isDestructible);
|
||||
QCOMPARE(type.isEqualityComparable(), isEqualityComparable);
|
||||
QCOMPARE(type.isOrdered(), isOrdered);
|
||||
}
|
||||
|
||||
void tst_QMetaType::flagsBinaryCompatibility6_0_data()
|
||||
{
|
||||
// Changing traits of a built-in type is illegal from BC point of view.
|
||||
|
|
@ -1092,14 +1178,12 @@ void tst_QMetaType::flagsBinaryCompatibility6_0()
|
|||
|
||||
const auto currentFlags = QMetaType::typeFlags(id);
|
||||
auto expectedFlags = QMetaType::TypeFlags(flags);
|
||||
if (!(currentFlags.testFlag(QMetaType::NeedsConstruction) && currentFlags.testFlag(QMetaType::NeedsDestruction))) {
|
||||
if (expectedFlags.testFlag(QMetaType::NeedsConstruction) && expectedFlags.testFlag(QMetaType::NeedsDestruction)) {
|
||||
// If type changed from RELOCATABLE to trivial, that's fine
|
||||
expectedFlags.setFlag(QMetaType::NeedsConstruction, false);
|
||||
expectedFlags.setFlag(QMetaType::NeedsDestruction, false);
|
||||
}
|
||||
}
|
||||
quint32 mask_5_0 = 0x1fb; // Only compare the values that were already defined in 5.0
|
||||
|
||||
// Only compare the values that were already defined in 5.0.
|
||||
// In 6.5, some types lost NeedsConstruction and NeedsDestruction, but
|
||||
// that's acceptable if that's because they were trivial
|
||||
quint32 mask_5_0 = 0x1ff & ~quint32(QMetaType::NeedsConstruction | QMetaType::NeedsDestruction
|
||||
| QMetaType::RelocatableType);
|
||||
|
||||
QCOMPARE(quint32(currentFlags) & mask_5_0, quint32(expectedFlags) & mask_5_0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ private slots:
|
|||
void alignOf();
|
||||
void flags_data();
|
||||
void flags();
|
||||
void flags2_data();
|
||||
void flags2();
|
||||
void flagsBinaryCompatibility6_0_data();
|
||||
void flagsBinaryCompatibility6_0();
|
||||
void construct_data();
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ private slots:
|
|||
void sizeOf();
|
||||
void flags_data();
|
||||
void flags();
|
||||
void flags2_data();
|
||||
void flags2();
|
||||
void construct_data();
|
||||
void construct();
|
||||
void constructCopy_data();
|
||||
|
|
@ -298,15 +300,19 @@ template <typename T> void addFlagsRow(const char *name, int id = qMetaTypeId<T>
|
|||
QTest::newRow(name)
|
||||
<< id
|
||||
<< bool(QTypeInfo<T>::isRelocatable)
|
||||
<< bool(QTypeInfo<T>::isComplex);
|
||||
<< bool(!std::is_trivially_default_constructible_v<T>)
|
||||
<< bool(!std::is_trivially_copy_constructible_v<T>)
|
||||
<< bool(!std::is_trivially_destructible_v<T>);
|
||||
}
|
||||
|
||||
|
||||
// tst_QGuiMetaType::flags is nearly identical to tst_QMetaType::flags
|
||||
void tst_QGuiMetaType::flags_data()
|
||||
{
|
||||
QTest::addColumn<int>("type");
|
||||
QTest::addColumn<bool>("isRelocatable");
|
||||
QTest::addColumn<bool>("isComplex");
|
||||
QTest::addColumn<bool>("needsConstruction");
|
||||
QTest::addColumn<bool>("needsCopyConstruction");
|
||||
QTest::addColumn<bool>("needsDestruction");
|
||||
|
||||
#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
|
||||
addFlagsRow<RealType>(#RealType, MetaTypeId);
|
||||
|
|
@ -318,13 +324,62 @@ void tst_QGuiMetaType::flags()
|
|||
{
|
||||
QFETCH(int, type);
|
||||
QFETCH(bool, isRelocatable);
|
||||
QFETCH(bool, isComplex);
|
||||
QFETCH(bool, needsConstruction);
|
||||
QFETCH(bool, needsCopyConstruction);
|
||||
QFETCH(bool, needsDestruction);
|
||||
|
||||
QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsConstruction), isComplex);
|
||||
QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsDestruction), isComplex);
|
||||
QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsConstruction), needsConstruction);
|
||||
QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsCopyConstruction), needsCopyConstruction);
|
||||
QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsDestruction), needsDestruction);
|
||||
QCOMPARE(bool(QMetaType(type).flags() & QMetaType::RelocatableType), isRelocatable);
|
||||
}
|
||||
|
||||
template <typename T> static void addFlags2Row(QMetaType metaType = QMetaType::fromType<T>())
|
||||
{
|
||||
QTest::newRow(metaType.name() ? metaType.name() : "UnknownType")
|
||||
<< metaType
|
||||
<< std::is_default_constructible_v<T>
|
||||
<< std::is_copy_constructible_v<T>
|
||||
<< std::is_move_constructible_v<T>
|
||||
<< std::is_destructible_v<T>
|
||||
<< (QTypeTraits::has_operator_equal<T>::value || QTypeTraits::has_operator_less_than<T>::value)
|
||||
<< QTypeTraits::has_operator_less_than<T>::value;
|
||||
};
|
||||
|
||||
// tst_QGuiMetaType::flags2 is nearly identical to tst_QMetaType::flags2
|
||||
void tst_QGuiMetaType::flags2_data()
|
||||
{
|
||||
QTest::addColumn<QMetaType>("type");
|
||||
QTest::addColumn<bool>("isDefaultConstructible");
|
||||
QTest::addColumn<bool>("isCopyConstructible");
|
||||
QTest::addColumn<bool>("isMoveConstructible");
|
||||
QTest::addColumn<bool>("isDestructible");
|
||||
QTest::addColumn<bool>("isEqualityComparable");
|
||||
QTest::addColumn<bool>("isOrdered");
|
||||
|
||||
#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
|
||||
addFlags2Row<RealType>();
|
||||
QT_FOR_EACH_STATIC_GUI_CLASS(ADD_METATYPE_TEST_ROW)
|
||||
#undef ADD_METATYPE_TEST_ROW
|
||||
}
|
||||
|
||||
void tst_QGuiMetaType::flags2()
|
||||
{
|
||||
QFETCH(QMetaType, type);
|
||||
QFETCH(bool, isDefaultConstructible);
|
||||
QFETCH(bool, isCopyConstructible);
|
||||
QFETCH(bool, isMoveConstructible);
|
||||
QFETCH(bool, isDestructible);
|
||||
QFETCH(bool, isEqualityComparable);
|
||||
QFETCH(bool, isOrdered);
|
||||
|
||||
QCOMPARE(type.isDefaultConstructible(), isDefaultConstructible);
|
||||
QCOMPARE(type.isCopyConstructible(), isCopyConstructible);
|
||||
QCOMPARE(type.isMoveConstructible(), isMoveConstructible);
|
||||
QCOMPARE(type.isDestructible(), isDestructible);
|
||||
QCOMPARE(type.isEqualityComparable(), isEqualityComparable);
|
||||
QCOMPARE(type.isOrdered(), isOrdered);
|
||||
}
|
||||
|
||||
void tst_QGuiMetaType::construct_data()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue