summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qmetatype.h
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2020-06-29 14:26:36 +0200
committerLars Knoll <lars.knoll@qt.io>2020-07-08 14:13:59 +0200
commit986d89c2eefd37ee0da8e07d7794716000608610 (patch)
tree5e709f713cacdf0bfac7ddb95d14e1ed8553a9f3 /src/corelib/kernel/qmetatype.h
parent0e2cfdedf261a9d29d7466bd26545549479d9f8a (diff)
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>
Diffstat (limited to 'src/corelib/kernel/qmetatype.h')
-rw-r--r--src/corelib/kernel/qmetatype.h150
1 files changed, 64 insertions, 86 deletions
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 335b958c18..a39c22b780 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -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
};
};