QMetaType: add is{Default,Copy,Move}Constructible and isDestructible

Unit tests will come after I've fixed the flags themselves. At this point,
they are wrong.

[ChangeLog][QtCore][QMetaType] Added isDefaultConstructible(),
isCopyConstructible(), isMoveConstructible() and isDestructible().

Change-Id: I3859764fed084846bcb0fffd170353109378e34c
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Thiago Macieira 2022-07-19 12:53:38 -07:00
parent 74fac865cf
commit 764d82ceb5
3 changed files with 121 additions and 3 deletions

View File

@ -65,6 +65,8 @@ QT_BEGIN_NAMESPACE
QT_IMPL_METATYPE_EXTERN_TAGGED(QtMetaTypePrivate::QPairVariantInterfaceImpl, QPairVariantInterfaceImpl)
using QtMetaTypePrivate::isVoid;
namespace {
struct QMetaTypeCustomRegistry
@ -554,9 +556,13 @@ int QMetaType::registerHelper(const QtPrivate::QMetaTypeInterface *iface)
\fn constexpr TypeFlags QMetaType::flags() const
\since 5.0
Returns flags of the type for which this QMetaType instance was constructed.
Returns flags of the type for which this QMetaType instance was
constructed. To inspect specific type traits, prefer using one of the "is-"
functions rather than the flags directly.
\sa QMetaType::TypeFlags, QMetaType::flags()
\sa QMetaType::TypeFlags, QMetaType::flags(), isDefaultConstructible(),
isCopyConstructible(), isMoveConstructible(), isDestructible(),
isEqualityComparable(), isOrdered()
*/
/*!
@ -777,6 +783,68 @@ bool QMetaType::equals(const void *lhs, const void *rhs) const
return false;
}
/*!
\fn bool QMetaType::isDefaultConstructible() const noexcept
\since 6.5
Returns true if this type can be default-constructed. If it can be, then
construct() and create() can be used with a \c{copy} parameter that is
null.
\sa flags(), isCopyConstructible(), isMoveConstructible(), isDestructible()
*/
/*!
\fn bool QMetaType::isCopyConstructible() const noexcept
\since 6.5
Returns true if this type can be copy-constructed. If it can be, then
construct() and create() can be used with a \c{copy} parameter that is
not null.
\sa flags(), isDefaultConstructible(), isMoveConstructible(), isDestructible()
*/
/*!
\fn bool QMetaType::isMoveConstructible() const noexcept
\since 6.5
Returns true if this type can be move-constructed. QMetaType currently does
not have an API to make use of this trait.
\sa flags(), isDefaultConstructible(), isCopyConstructible(), isDestructible()
*/
/*!
\fn bool QMetaType::isDestructible() const noexcept
\since 6.5
Returns true if this type can be destroyed. If it can be, then destroy()
and destruct() can be called.
\sa flags(), isDefaultConstructible(), isCopyConstructible(), isMoveConstructible()
*/
bool QMetaType::isDefaultConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
{
return !isVoid(iface) && QtMetaTypePrivate::isDefaultConstructible(iface);
}
bool QMetaType::isCopyConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
{
return !isVoid(iface) && QtMetaTypePrivate::isCopyConstructible(iface);
}
bool QMetaType::isMoveConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
{
return !isVoid(iface) && QtMetaTypePrivate::isMoveConstructible(iface);
}
bool QMetaType::isDestructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
{
return !isVoid(iface) && QtMetaTypePrivate::isDestructible(iface);
}
/*!
Returns \c true if a less than or equality operator for the type described by
this metatype was visible to the metatype declaration, otherwise \c false.

View File

@ -455,6 +455,10 @@ public:
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;
@ -722,6 +726,11 @@ public:
const QtPrivate::QMetaTypeInterface *iface() const { return d_ptr; }
private:
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;
#if QT_CORE_REMOVED_SINCE(6, 5)
int idHelper() const;
#endif

View File

@ -116,6 +116,48 @@ template<> struct TypeDefinition<QQuaternion> { static const bool IsAvailable =
template<> struct TypeDefinition<QIcon> { static const bool IsAvailable = false; };
#endif
inline bool isVoid(const QtPrivate::QMetaTypeInterface *iface)
{
// void is special because it can't be constructed, copied or destroyed,
// but iface->flags doesn't set Needs{Construction,Destruction}.
return iface->typeId.loadRelaxed() == QMetaType::Void;
}
template <typename FPointer>
inline bool checkMetaTypeFlagOrPointer(const QtPrivate::QMetaTypeInterface *iface, FPointer ptr, QMetaType::TypeFlag Flag)
{
// helper to the isXxxConstructible & isDestructible functions below: a
// meta type has the trait if the trait is trivial or we have the pointer
// to perform the operation
Q_ASSERT(!isVoid(iface));
Q_ASSERT(iface->size);
return ptr != nullptr || (iface->flags & Flag) == 0;
}
inline bool isDefaultConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
{
return checkMetaTypeFlagOrPointer(iface, iface->defaultCtr, QMetaType::NeedsConstruction);
}
inline bool isCopyConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
{
// ### broken
return checkMetaTypeFlagOrPointer(iface, iface->copyCtr, QMetaType::NeedsConstruction);
}
inline bool isMoveConstructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
{
return iface->moveCtr;
}
inline bool isDestructible(const QtPrivate::QMetaTypeInterface *iface) noexcept
{
// ### broken
return checkMetaTypeFlagOrPointer(iface, iface->dtor, QMetaType::NeedsDestruction);
}
const char *typedefNameForType(const QtPrivate::QMetaTypeInterface *type_d);
template<typename T>
static const QT_PREPEND_NAMESPACE(QtPrivate::QMetaTypeInterface) *getInterfaceFromType()
{
@ -129,7 +171,6 @@ static const QT_PREPEND_NAMESPACE(QtPrivate::QMetaTypeInterface) *getInterfaceFr
case QMetaType::MetaTypeName: \
return QtMetaTypePrivate::getInterfaceFromType<RealName>();
const char *typedefNameForType(const QtPrivate::QMetaTypeInterface *type_d);
} //namespace QtMetaTypePrivate
QT_END_NAMESPACE