Automatically register comparison operators in QMetaType
This removes the fully manual registration of comparison operators in QMetaType and replaces it with an automatic registration through Q_DECLARE_METATYPE(). [ChangeLog][QMetaType] The QMetaType::registerComparator() and QMetaType::registerEqualsComparator() have been removed. Q_DECLARE_METATYPE() now automatically registers any operator==() and/or operator<() for a type visible where it is used on that type, as part of declaring its meta-type. Change-Id: I3df451b652b735c093533838bf32f3cc785439f8 Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
0e2cfdedf2
commit
986d89c2ee
@ -657,6 +657,98 @@ void QMetaType::destruct(void *data) const
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Compares the objects at \a lhs and \a rhs for ordering.
|
||||
|
||||
Returns an empty optional if comparison is not supported or the values are unordered.
|
||||
Otherwise, returns -1, 0 or +1 according as \a lhs is less than, equal to or greater
|
||||
than \a rhs.
|
||||
|
||||
Both objects must be of the type described by this metatype. If either \a lhs
|
||||
or \a rhs is \nullptr, the values are unordered. Comparison is only supported
|
||||
if the type's less than operator was visible to the metatype declaration.
|
||||
|
||||
If the type's equality operator was also visible, values will only compare equal if the
|
||||
equality operator says they are. In the absence of an equality operator, when neither
|
||||
value is less than the other, values are considered equal; if equality is also available
|
||||
and two such values are not equal, they are considered unordered, just as NaN (not a
|
||||
number) values of a floating point type lie outside its ordering.
|
||||
|
||||
\note If no less than operator was visible to the metatype declaration, values are
|
||||
unordered even if an equality operator visible to the declaration considers them equal:
|
||||
\s{compare() == 0} only agrees with equals() if the less than operator was visible.
|
||||
|
||||
\since 6.0
|
||||
\sa equals(), isOrdered()
|
||||
*/
|
||||
std::optional<int> QMetaType::compare(const void *lhs, const void *rhs) const
|
||||
{
|
||||
if (!lhs || !rhs)
|
||||
return std::optional<int>{};
|
||||
if (d_ptr && d_ptr->lessThan) {
|
||||
if (d_ptr->equals && d_ptr->equals(d_ptr, lhs, rhs))
|
||||
return 0;
|
||||
if (d_ptr->lessThan(d_ptr, lhs, rhs))
|
||||
return -1;
|
||||
if (d_ptr->lessThan(d_ptr, rhs, lhs))
|
||||
return 1;
|
||||
if (!d_ptr->equals)
|
||||
return 0;
|
||||
}
|
||||
return std::optional<int>{};
|
||||
}
|
||||
|
||||
/*!
|
||||
Compares the objects at \a lhs and \a rhs for equality.
|
||||
|
||||
Both objects must be of the type described by this metatype. Can only compare the
|
||||
two objects if a less than or equality operator for the type was visible to the
|
||||
metatype declaration. Otherwise, the metatype never considers values equal. When
|
||||
an equality operator was visible to the metatype declaration, it is authoritative;
|
||||
otherwise, if less than is visible, when neither value is less than the other, the
|
||||
two are considered equal. If values are unordered (see compare() for details) they
|
||||
are not equal.
|
||||
|
||||
Returns true if the two objects compare equal, otherwise false.
|
||||
|
||||
\since 6.0
|
||||
\sa isEqualityComparable(), compare()
|
||||
*/
|
||||
bool QMetaType::equals(const void *lhs, const void *rhs) const
|
||||
{
|
||||
if (!lhs || !rhs)
|
||||
return false;
|
||||
if (d_ptr) {
|
||||
if (d_ptr->equals)
|
||||
return d_ptr->equals(d_ptr, lhs, rhs);
|
||||
if (d_ptr->lessThan && !d_ptr->lessThan(d_ptr, lhs, rhs) && !d_ptr->lessThan(d_ptr, rhs, lhs))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
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.
|
||||
|
||||
\sa equals(), isOrdered()
|
||||
*/
|
||||
bool QMetaType::isEqualityComparable() const
|
||||
{
|
||||
return d_ptr && (d_ptr->equals != nullptr || d_ptr->lessThan != nullptr);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if a less than operator for the type described by this metatype
|
||||
was visible to the metatype declaration, otherwise \c false.
|
||||
|
||||
\sa compare(), isEqualityComparable()
|
||||
*/
|
||||
bool QMetaType::isOrdered() const
|
||||
{
|
||||
return d_ptr && d_ptr->lessThan != nullptr;
|
||||
}
|
||||
|
||||
void QtMetaTypePrivate::derefAndDestroy(NS(QtPrivate::QMetaTypeInterface) *d_ptr)
|
||||
{
|
||||
if (d_ptr && !d_ptr->ref.deref()) {
|
||||
@ -789,13 +881,10 @@ private:
|
||||
|
||||
typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractConverterFunction,QPair<int,int> >
|
||||
QMetaTypeConverterRegistry;
|
||||
typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractComparatorFunction,int>
|
||||
QMetaTypeComparatorRegistry;
|
||||
typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int>
|
||||
QMetaTypeDebugStreamRegistry;
|
||||
|
||||
Q_GLOBAL_STATIC(QMetaTypeConverterRegistry, customTypesConversionRegistry)
|
||||
Q_GLOBAL_STATIC(QMetaTypeComparatorRegistry, customTypesComparatorRegistry)
|
||||
Q_GLOBAL_STATIC(QMetaTypeDebugStreamRegistry, customTypesDebugStreamRegistry)
|
||||
|
||||
/*!
|
||||
@ -829,22 +918,6 @@ Q_GLOBAL_STATIC(QMetaTypeDebugStreamRegistry, customTypesDebugStreamRegistry)
|
||||
to type To in the meta type system. Returns \c true if the registration succeeded, otherwise false.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool QMetaType::registerComparators()
|
||||
\since 5.2
|
||||
Registers comparison operators for the user-registered type T. This requires T to have
|
||||
both an operator== and an operator<.
|
||||
Returns \c true if the registration succeeded, otherwise false.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool QMetaType::registerEqualsComparator()
|
||||
\since 5.5
|
||||
Registers equals operator for the user-registered type T. This requires T to have
|
||||
an operator==.
|
||||
Returns \c true if the registration succeeded, otherwise false.
|
||||
*/
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
/*!
|
||||
\fn bool QMetaType::registerDebugStreamOperator()
|
||||
@ -883,30 +956,6 @@ void QMetaType::unregisterConverterFunction(int from, int to)
|
||||
customTypesConversionRegistry()->remove(from, to);
|
||||
}
|
||||
|
||||
bool QMetaType::registerComparatorFunction(const QtPrivate::AbstractComparatorFunction *f, int type)
|
||||
{
|
||||
if (!customTypesComparatorRegistry()->insertIfNotContains(type, f)) {
|
||||
qWarning("Comparators already registered for type %s", QMetaType::typeName(type));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn bool QMetaType::hasRegisteredComparators()
|
||||
Returns \c true, if the meta type system has registered comparators for type T.
|
||||
\since 5.2
|
||||
*/
|
||||
|
||||
/*!
|
||||
Returns \c true, if the meta type system has registered comparators for type id \a typeId.
|
||||
\since 5.2
|
||||
*/
|
||||
bool QMetaType::hasRegisteredComparators(int typeId)
|
||||
{
|
||||
return customTypesComparatorRegistry()->contains(typeId);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
bool QMetaType::registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f,
|
||||
int type)
|
||||
@ -948,44 +997,24 @@ bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId
|
||||
}
|
||||
|
||||
/*!
|
||||
bool QMetaType::compare(const void *lhs, const void *rhs, int typeId, int* result)
|
||||
\deprecated Use the non-static compare method instead
|
||||
|
||||
Compares the objects at \a lhs and \a rhs. Both objects need to be of type \a typeId.
|
||||
\a result is set to less than, equal to or greater than zero, if \a lhs is less than, equal to
|
||||
or greater than \a rhs. Returns \c true, if the comparison succeeded, otherwise \c false.
|
||||
\since 5.2
|
||||
*/
|
||||
bool QMetaType::compare(const void *lhs, const void *rhs, int typeId, int* result)
|
||||
{
|
||||
const QtPrivate::AbstractComparatorFunction * const f =
|
||||
customTypesComparatorRegistry()->function(typeId);
|
||||
if (!f)
|
||||
return false;
|
||||
if (f->equals(f, lhs, rhs))
|
||||
*result = 0;
|
||||
else if (f->lessThan)
|
||||
*result = f->lessThan(f, lhs, rhs) ? -1 : 1;
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
bool QMetaType::equals(const void *lhs, const void *rhs, int typeId, int *result)
|
||||
\deprecated Use the non-static equals method instead
|
||||
|
||||
Compares the objects at \a lhs and \a rhs. Both objects need to be of type \a typeId.
|
||||
\a result is set to zero, if \a lhs equals to rhs. Returns \c true, if the comparison
|
||||
succeeded, otherwise \c false.
|
||||
\since 5.5
|
||||
*/
|
||||
bool QMetaType::equals(const void *lhs, const void *rhs, int typeId, int *result)
|
||||
{
|
||||
const QtPrivate::AbstractComparatorFunction * const f
|
||||
= customTypesComparatorRegistry()->function(typeId);
|
||||
if (!f)
|
||||
return false;
|
||||
if (f->equals(f, lhs, rhs))
|
||||
*result = 0;
|
||||
else
|
||||
*result = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Streams the object at \a rhs of type \a typeId to the debug stream \a dbg. Returns \c true
|
||||
|
@ -56,6 +56,7 @@
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
|
||||
#ifdef Bool
|
||||
#error qmetatype.h must be included before any header file that defines Bool
|
||||
@ -296,62 +297,6 @@ struct BuiltInDebugStreamFunction : public AbstractDebugStreamFunction
|
||||
};
|
||||
#endif
|
||||
|
||||
struct AbstractComparatorFunction
|
||||
{
|
||||
typedef bool (*LessThan)(const AbstractComparatorFunction *, const void *, const void *);
|
||||
typedef bool (*Equals)(const AbstractComparatorFunction *, const void *, const void *);
|
||||
typedef void (*Destroy)(AbstractComparatorFunction *);
|
||||
explicit AbstractComparatorFunction(LessThan lt = nullptr, Equals e = nullptr, Destroy d = nullptr)
|
||||
: lessThan(lt), equals(e), destroy(d) {}
|
||||
Q_DISABLE_COPY(AbstractComparatorFunction)
|
||||
LessThan lessThan;
|
||||
Equals equals;
|
||||
Destroy destroy;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct BuiltInComparatorFunction : public AbstractComparatorFunction
|
||||
{
|
||||
BuiltInComparatorFunction()
|
||||
: AbstractComparatorFunction(lessThan, equals, destroy) {}
|
||||
static bool lessThan(const AbstractComparatorFunction *, const void *l, const void *r)
|
||||
{
|
||||
const T *lhs = static_cast<const T *>(l);
|
||||
const T *rhs = static_cast<const T *>(r);
|
||||
return *lhs < *rhs;
|
||||
}
|
||||
|
||||
static bool equals(const AbstractComparatorFunction *, const void *l, const void *r)
|
||||
{
|
||||
const T *lhs = static_cast<const T *>(l);
|
||||
const T *rhs = static_cast<const T *>(r);
|
||||
return *lhs == *rhs;
|
||||
}
|
||||
|
||||
static void destroy(AbstractComparatorFunction *_this)
|
||||
{
|
||||
delete static_cast<BuiltInComparatorFunction *>(_this);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct BuiltInEqualsComparatorFunction : public AbstractComparatorFunction
|
||||
{
|
||||
BuiltInEqualsComparatorFunction()
|
||||
: AbstractComparatorFunction(nullptr, equals, destroy) {}
|
||||
static bool equals(const AbstractComparatorFunction *, const void *l, const void *r)
|
||||
{
|
||||
const T *lhs = static_cast<const T *>(l);
|
||||
const T *rhs = static_cast<const T *>(r);
|
||||
return *lhs == *rhs;
|
||||
}
|
||||
|
||||
static void destroy(AbstractComparatorFunction *_this)
|
||||
{
|
||||
delete static_cast<BuiltInEqualsComparatorFunction *>(_this);
|
||||
}
|
||||
};
|
||||
|
||||
struct AbstractConverterFunction
|
||||
{
|
||||
typedef bool (*Converter)(const AbstractConverterFunction *, const void *, void*);
|
||||
@ -569,6 +514,11 @@ public:
|
||||
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;
|
||||
bool equals(const void *lhs, const void *rhs) const;
|
||||
|
||||
bool isEqualityComparable() const;
|
||||
bool isOrdered() const;
|
||||
|
||||
template<typename T>
|
||||
static QMetaType fromType();
|
||||
@ -577,33 +527,6 @@ public:
|
||||
friend bool operator!=(const QMetaType &a, const QMetaType &b) { return !(a == b); }
|
||||
|
||||
public:
|
||||
template<typename T>
|
||||
static bool registerComparators()
|
||||
{
|
||||
static_assert((!QMetaTypeId2<T>::IsBuiltIn),
|
||||
"QMetaType::registerComparators: The type must be a custom type.");
|
||||
|
||||
const int typeId = qMetaTypeId<T>();
|
||||
static const QtPrivate::BuiltInComparatorFunction<T> f;
|
||||
return registerComparatorFunction( &f, typeId);
|
||||
}
|
||||
template<typename T>
|
||||
static bool registerEqualsComparator()
|
||||
{
|
||||
static_assert((!QMetaTypeId2<T>::IsBuiltIn),
|
||||
"QMetaType::registerEqualsComparator: The type must be a custom type.");
|
||||
const int typeId = qMetaTypeId<T>();
|
||||
static const QtPrivate::BuiltInEqualsComparatorFunction<T> f;
|
||||
return registerComparatorFunction( &f, typeId);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static bool hasRegisteredComparators()
|
||||
{
|
||||
return hasRegisteredComparators(qMetaTypeId<T>());
|
||||
}
|
||||
static bool hasRegisteredComparators(int typeId);
|
||||
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
template<typename T>
|
||||
@ -680,8 +603,30 @@ public:
|
||||
#endif
|
||||
|
||||
static bool convert(const void *from, int fromTypeId, void *to, int toTypeId);
|
||||
static bool compare(const void *lhs, const void *rhs, int typeId, int* result);
|
||||
static bool equals(const void *lhs, const void *rhs, int typeId, int* result);
|
||||
#if QT_DEPRECATED_SINCE(6, 0)
|
||||
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) {
|
||||
*result = 0;
|
||||
return false;
|
||||
}
|
||||
*result = *c;
|
||||
return true;
|
||||
}
|
||||
QT_DEPRECATED_VERSION_6_0
|
||||
static bool equals(const void *lhs, const void *rhs, int typeId, int *result)
|
||||
{
|
||||
QMetaType t(typeId);
|
||||
if (!t.isEqualityComparable())
|
||||
return false;
|
||||
*result = t.equals(lhs, rhs) ? 0 : -1;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool debugStream(QDebug& dbg, const void *rhs, int typeId);
|
||||
|
||||
template<typename From, typename To>
|
||||
@ -692,7 +637,6 @@ public:
|
||||
|
||||
static bool hasRegisteredConverterFunction(int fromTypeId, int toTypeId);
|
||||
|
||||
static bool registerComparatorFunction(const QtPrivate::AbstractComparatorFunction *f, int type);
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
static bool registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f, int type);
|
||||
#endif
|
||||
@ -2297,6 +2241,10 @@ public:
|
||||
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 LegacyRegisterOp = void (*)();
|
||||
LegacyRegisterOp legacyRegisterOp;
|
||||
@ -2679,6 +2627,32 @@ struct BuiltinMetaType<T, std::enable_if_t<QMetaTypeId2<T>::IsBuiltIn>>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T, bool = QTypeTraits::has_operator_equal_v<T>>
|
||||
struct QEqualityOperatorForType
|
||||
{
|
||||
static bool equals(const QMetaTypeInterface *, const void *a, const void *b)
|
||||
{ return *reinterpret_cast<const T *>(a) == *reinterpret_cast<const T *>(b); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct QEqualityOperatorForType <T, false>
|
||||
{
|
||||
static constexpr QMetaTypeInterface::EqualsFn equals = nullptr;
|
||||
};
|
||||
|
||||
template<typename T, bool = QTypeTraits::has_operator_less_than_v<T>>
|
||||
struct QLessThanOperatorForType
|
||||
{
|
||||
static bool lessThan(const QMetaTypeInterface *, const void *a, const void *b)
|
||||
{ return *reinterpret_cast<const T *>(a) < *reinterpret_cast<const T *>(b); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct QLessThanOperatorForType <T, false>
|
||||
{
|
||||
static constexpr QMetaTypeInterface::LessThanFn lessThan = nullptr;
|
||||
};
|
||||
|
||||
template<typename S>
|
||||
class QMetaTypeForType
|
||||
{
|
||||
@ -2765,6 +2739,8 @@ QMetaTypeInterface QMetaTypeForType<T>::metaType = {
|
||||
/*.copyCtr=*/ getCopyCtr<T>(),
|
||||
/*.moveCtr=*/ getMoveCtr<T>(),
|
||||
/*.dtor=*/ getDtor<T>(),
|
||||
/*.equals=*/ QEqualityOperatorForType<T>::equals,
|
||||
/*.lessThan=*/ QLessThanOperatorForType<T>::lessThan,
|
||||
/*.legacyRegisterOp=*/ getLegacyRegister<T>()
|
||||
};
|
||||
|
||||
@ -2792,6 +2768,8 @@ public:
|
||||
/*.copyCtr=*/ nullptr,
|
||||
/*.moveCtr=*/ nullptr,
|
||||
/*.dtor=*/ nullptr,
|
||||
/*.equals=*/ nullptr,
|
||||
/*.lessThan=*/ nullptr,
|
||||
/*.legacyRegisterOp=*/ nullptr
|
||||
};
|
||||
};
|
||||
|
@ -123,11 +123,10 @@ bool QPropertyBindingPrivate::evaluateIfDirtyAndReturnTrueIfValueChanged()
|
||||
QVariant resultVariant(metaType.id(), nullptr);
|
||||
evalError = evaluationFunction(metaType, resultVariant.data());
|
||||
if (evalError.type() == QPropertyBindingError::NoError) {
|
||||
int compareResult = 0;
|
||||
bool updateAllowed = true;
|
||||
if (hasStaticObserver && staticGuardCallback)
|
||||
updateAllowed = staticGuardCallback(staticObserver, resultVariant.data());
|
||||
if (updateAllowed && (!QMetaType::compare(propertyDataPtr, resultVariant.constData(), metaType.id(), &compareResult) || compareResult != 0)) {
|
||||
if (updateAllowed && !metaType.equals(propertyDataPtr, resultVariant.constData())) {
|
||||
changed = true;
|
||||
metaType.destruct(propertyDataPtr);
|
||||
metaType.construct(propertyDataPtr, resultVariant.constData());
|
||||
|
@ -3738,21 +3738,14 @@ bool QVariant::convert(const int type, void *ptr) const
|
||||
The result of the function is not affected by the result of QVariant::isNull,
|
||||
which means that two values can be equal even if one of them is null and
|
||||
another is not.
|
||||
|
||||
\warning To make this function work with a custom type registered with
|
||||
qRegisterMetaType(), its comparison operator must be registered using
|
||||
QMetaType::registerComparators().
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool operator!=(const QVariant &v1, const QVariant &v2)
|
||||
|
||||
\relates QVariant
|
||||
|
||||
Returns \c false if \a v1 and \a v2 are equal; otherwise returns \c true.
|
||||
|
||||
\warning To make this function work with a custom type registered with
|
||||
qRegisterMetaType(), its comparison operator must be registered using
|
||||
QMetaType::registerComparators().
|
||||
*/
|
||||
|
||||
/*! \fn bool QVariant::operator==(const QVariant &v) const
|
||||
@ -3764,10 +3757,6 @@ bool QVariant::convert(const int type, void *ptr) const
|
||||
check for equality. QVariant will try to convert() \a v if its
|
||||
type is not the same as this variant's type. See canConvert() for
|
||||
a list of possible conversions.
|
||||
|
||||
\warning To make this function work with a custom type registered with
|
||||
qRegisterMetaType(), its comparison operator must be registered using
|
||||
QMetaType::registerComparators().
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -3775,10 +3764,6 @@ bool QVariant::convert(const int type, void *ptr) const
|
||||
|
||||
Compares this QVariant with \a v and returns \c true if they are not
|
||||
equal; otherwise returns \c false.
|
||||
|
||||
\warning To make this function work with a custom type registered with
|
||||
qRegisterMetaType(), its comparison operator must be registered using
|
||||
QMetaType::registerComparators().
|
||||
*/
|
||||
|
||||
static bool qIsNumericType(uint tp)
|
||||
@ -3928,12 +3913,9 @@ bool QVariant::cmp(const QVariant &v) const
|
||||
{
|
||||
auto cmp_helper = [](const QVariant::Private &d1, const QVariant::Private &d2) {
|
||||
Q_ASSERT(d1.type() == d2.type());
|
||||
if (d1.type().id() >= QMetaType::User) {
|
||||
int result;
|
||||
if (QMetaType::equals(QT_PREPEND_NAMESPACE(constData(d1)),
|
||||
QT_PREPEND_NAMESPACE(constData(d2)), d1.type().id(), &result))
|
||||
return result == 0;
|
||||
}
|
||||
auto metatype = d1.type();
|
||||
if (metatype.id() >= QMetaType::User)
|
||||
return metatype.equals(QT_PREPEND_NAMESPACE(constData(d1)), QT_PREPEND_NAMESPACE(constData(d2)));
|
||||
return handlerManager[d1.type().id()]->compare(&d1, &d2);
|
||||
};
|
||||
|
||||
|
@ -139,7 +139,7 @@ static int registerComplexDBusType(const QByteArray &typeName)
|
||||
[](QtPrivate::QMetaTypeInterface *self) {
|
||||
delete static_cast<QDBusRawTypeHandler *>(self);
|
||||
},
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
|
||||
},
|
||||
name(name)
|
||||
{}
|
||||
|
@ -249,9 +249,6 @@ QPageSetupWidget::QPageSetupWidget(QWidget *parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
if (!QMetaType::hasRegisteredComparators<QPageSize>())
|
||||
QMetaType::registerEqualsComparator<QPageSize>();
|
||||
|
||||
QVBoxLayout *lay = new QVBoxLayout(m_ui.preview);
|
||||
m_pagePreview = new QPagePreview(m_ui.preview);
|
||||
m_pagePreview->setPagePreviewLayout(1, 1);
|
||||
|
@ -411,6 +411,8 @@ void tst_QMetaType::registerGadget(const char *name, const QList<GadgetPropertyT
|
||||
[](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 };
|
||||
QMetaType gadgetMetaType(typeInfo);
|
||||
dynamicGadgetProperties->m_metatype = gadgetMetaType;
|
||||
@ -1277,7 +1279,7 @@ void tst_QMetaType::typedConstruct()
|
||||
[](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, nullptr };
|
||||
QMetaType metatype(typeInfo);
|
||||
dynamicGadgetProperties->m_metatype = metatype;
|
||||
int podTypeId = metatype.id();
|
||||
@ -2252,6 +2254,9 @@ bool operator==(const CustomEqualsOnlyType &lhs, const CustomEqualsOnlyType &rhs
|
||||
bool operator!=(const CustomEqualsOnlyType &lhs, const CustomEqualsOnlyType &rhs)
|
||||
{ return !operator==(lhs, rhs); }
|
||||
|
||||
static_assert(QTypeTraits::has_operator_equal_v<CustomEqualsOnlyType>);
|
||||
static_assert(!QTypeTraits::has_operator_less_than_v<CustomEqualsOnlyType>);
|
||||
|
||||
Q_DECLARE_METATYPE(CustomConvertibleType);
|
||||
Q_DECLARE_METATYPE(CustomConvertibleType2);
|
||||
Q_DECLARE_METATYPE(CustomDebugStreamableType);
|
||||
@ -2497,9 +2502,7 @@ void tst_QMetaType::convertCustomType()
|
||||
|
||||
void tst_QMetaType::compareCustomEqualOnlyType()
|
||||
{
|
||||
int metaTypeId = qRegisterMetaType<CustomEqualsOnlyType>();
|
||||
QMetaType::registerEqualsComparator<CustomEqualsOnlyType>();
|
||||
int result;
|
||||
QMetaType type = QMetaType::fromType<CustomEqualsOnlyType>();
|
||||
|
||||
CustomEqualsOnlyType val50(50);
|
||||
CustomEqualsOnlyType val100(100);
|
||||
@ -2517,52 +2520,26 @@ void tst_QMetaType::compareCustomEqualOnlyType()
|
||||
QCOMPARE(variant100, variant100);
|
||||
|
||||
// check QMetaType::compare works/doesn't crash for equals only comparators
|
||||
bool wasSuccess = QMetaType::compare(variant50.constData(), variant50.constData(),
|
||||
metaTypeId, &result);
|
||||
QCOMPARE(result, 0);
|
||||
QVERIFY(wasSuccess);
|
||||
wasSuccess = QMetaType::compare(variant100.constData(), variant100x.constData(),
|
||||
metaTypeId, &result);
|
||||
QCOMPARE(result, 0);
|
||||
QVERIFY(wasSuccess);
|
||||
auto cmp = type.compare(variant50.constData(), variant50.constData());
|
||||
QVERIFY(!cmp);
|
||||
bool equals = type.equals(variant50.constData(), variant50.constData());
|
||||
QVERIFY(equals);
|
||||
|
||||
wasSuccess = QMetaType::compare(variant50.constData(), variant100.constData(),
|
||||
metaTypeId, &result);
|
||||
QVERIFY(!wasSuccess);
|
||||
cmp = type.compare(variant100.constData(), variant100x.constData());
|
||||
QVERIFY(!cmp);
|
||||
equals = type.equals(variant100.constData(), variant100x.constData());
|
||||
QVERIFY(equals);
|
||||
|
||||
// check QMetaType::equals works for equals only comparator
|
||||
wasSuccess = QMetaType::equals(variant50.constData(), variant50.constData(),
|
||||
metaTypeId, &result);
|
||||
QCOMPARE(result, 0);
|
||||
QVERIFY(wasSuccess);
|
||||
wasSuccess = QMetaType::equals(variant100.constData(), variant100.constData(),
|
||||
metaTypeId, &result);
|
||||
QCOMPARE(result, 0);
|
||||
QVERIFY(wasSuccess);
|
||||
wasSuccess = QMetaType::equals(variant100x.constData(), variant100x.constData(),
|
||||
metaTypeId, &result);
|
||||
QCOMPARE(result, 0);
|
||||
QVERIFY(wasSuccess);
|
||||
wasSuccess = QMetaType::equals(variant100.constData(), variant100x.constData(),
|
||||
metaTypeId, &result);
|
||||
QCOMPARE(result, 0);
|
||||
QVERIFY(wasSuccess);
|
||||
wasSuccess = QMetaType::equals(variant50.constData(), variant100.constData(),
|
||||
metaTypeId, &result);
|
||||
QCOMPARE(result, -1);
|
||||
QVERIFY(wasSuccess);
|
||||
wasSuccess = QMetaType::equals(variant50.constData(), variant100x.constData(),
|
||||
metaTypeId, &result);
|
||||
QCOMPARE(result, -1);
|
||||
QVERIFY(wasSuccess);
|
||||
cmp = type.compare(variant50.constData(), variant100.constData());
|
||||
QVERIFY(!cmp);
|
||||
equals = type.equals(variant50.constData(), variant100.constData());
|
||||
QVERIFY(!equals);
|
||||
|
||||
//check QMetaType::equals for type w/o equals comparator being registered
|
||||
CustomMovable movable1;
|
||||
CustomMovable movable2;
|
||||
wasSuccess = QMetaType::equals(&movable1, &movable2,
|
||||
qRegisterMetaType<CustomMovable>(), &result);
|
||||
QVERIFY(!wasSuccess);
|
||||
|
||||
type = QMetaType::fromType<CustomMovable>();
|
||||
equals = type.equals(&movable1, &movable2);
|
||||
}
|
||||
|
||||
struct MessageHandlerCustom : public MessageHandler
|
||||
|
@ -1826,6 +1826,12 @@ struct MyType
|
||||
{
|
||||
++instanceCount;
|
||||
}
|
||||
MyType &operator=(const MyType &other)
|
||||
{
|
||||
number = other.number;
|
||||
text = other.text;
|
||||
return *this;
|
||||
}
|
||||
~MyType()
|
||||
{
|
||||
--instanceCount;
|
||||
@ -1833,6 +1839,8 @@ struct MyType
|
||||
int number;
|
||||
const char *text;
|
||||
};
|
||||
bool operator==(const MyType &a, const MyType &b) { return a.number == b.number && a.text == b.text; }
|
||||
static_assert(QTypeTraits::has_operator_equal_v<MyType>);
|
||||
|
||||
Q_DECLARE_METATYPE(MyType)
|
||||
Q_DECLARE_METATYPE(MyType*)
|
||||
@ -2837,28 +2845,43 @@ void tst_QVariant::invalidDate() const
|
||||
|
||||
struct WontCompare
|
||||
{
|
||||
int x,y,z,q,w,e,r,t;
|
||||
int x;
|
||||
};
|
||||
Q_DECLARE_METATYPE(WontCompare);
|
||||
|
||||
struct WillCompare
|
||||
{
|
||||
int x;
|
||||
};
|
||||
bool operator==(const WillCompare &a, const WillCompare &b) { return a.x == b.x; }
|
||||
Q_DECLARE_METATYPE(WillCompare);
|
||||
|
||||
void tst_QVariant::compareCustomTypes() const
|
||||
{
|
||||
qRegisterMetaType<WontCompare>("WontCompare");
|
||||
{
|
||||
WontCompare f1{0};
|
||||
const QVariant variant1(QVariant::fromValue(f1));
|
||||
|
||||
WontCompare f1 = {};
|
||||
f1.x = 0;
|
||||
const QVariant variant1(QVariant::fromValue(f1));
|
||||
WontCompare f2{1};
|
||||
const QVariant variant2(QVariant::fromValue(f2));
|
||||
|
||||
WontCompare f2 = {};
|
||||
f2.x = 1;
|
||||
const QVariant variant2(QVariant::fromValue(f2));
|
||||
/* No comparison operator exists. */
|
||||
QVERIFY(variant1 != variant2);
|
||||
QVERIFY(variant1 != variant1);
|
||||
QVERIFY(variant2 != variant2);
|
||||
}
|
||||
{
|
||||
WillCompare f1{0};
|
||||
const QVariant variant1(QVariant::fromValue(f1));
|
||||
|
||||
/* We compare via memcmp. */
|
||||
QVERIFY(variant1 != variant2);
|
||||
QCOMPARE(variant1, variant1);
|
||||
QCOMPARE(variant2, variant2);
|
||||
WillCompare f2 {1};
|
||||
const QVariant variant2(QVariant::fromValue(f2));
|
||||
|
||||
QVERIFY(variant1 != variant2);
|
||||
QCOMPARE(variant1, variant1);
|
||||
QCOMPARE(variant2, variant2);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QVariant::timeToDateTime() const
|
||||
{
|
||||
const QVariant val(QTime::currentTime());
|
||||
|
Loading…
Reference in New Issue
Block a user