diff options
-rw-r--r-- | src/corelib/kernel/qproperty.h | 34 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp | 13 |
2 files changed, 47 insertions, 0 deletions
diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h index 4a144911771..f4e7942e947 100644 --- a/src/corelib/kernel/qproperty.h +++ b/src/corelib/kernel/qproperty.h @@ -360,6 +360,17 @@ class QProperty : public QPropertyData<T> return false; } + template <typename U, typename = void> + struct has_operator_equal_to : std::false_type{}; + + template <typename U> + struct has_operator_equal_to<U, std::void_t<decltype(bool(std::declval<const T&>() == std::declval<const U&>()))>> + : std::true_type{}; + + template <typename U> + static constexpr bool has_operator_equal_to_v = + !std::is_same_v<U, T> && has_operator_equal_to<U>::value; + public: using value_type = typename QPropertyData<T>::value_type; using parameter_type = typename QPropertyData<T>::parameter_type; @@ -388,6 +399,23 @@ public: QT_DECLARE_EQUALITY_OPERATORS_HELPER(QProperty, T, /* non-constexpr */, noexcept(false), template <typename Ty = T, std::enable_if_t<QTypeTraits::has_operator_equal_v<Ty>>* = nullptr>) QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(QProperty, T, /* non-constexpr */, noexcept(false), template <typename Ty = T, std::enable_if_t<QTypeTraits::has_operator_equal_v<Ty>>* = nullptr>) + QT_DECLARE_EQUALITY_OPERATORS_HELPER(QProperty, U, /* non-constexpr */, noexcept(false), template <typename U, std::enable_if_t<has_operator_equal_to_v<U>>* = nullptr>) + QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(QProperty, U, /* non-constexpr */, noexcept(false), template <typename U, std::enable_if_t<has_operator_equal_to_v<U>>* = nullptr>) + + // Explicitly delete op==(QProperty<T>, QProperty<U>) for different T & U. + // We do not want implicit conversions here! + // However, GCC complains about using a default template argument in a + // friend declaration, while Clang and MSVC are fine. So, skip GCC here. +#if !defined(Q_CC_GNU) || defined(Q_CC_CLANG) +#define QPROPERTY_DECL_DELETED_EQ_OP \ + Q_DECL_EQ_DELETE_X("Call .value() on one of the properties explicitly.") + template <typename U, std::enable_if_t<!std::is_same_v<T, U>>* = nullptr> + friend void operator==(const QProperty &, const QProperty<U> &) QPROPERTY_DECL_DELETED_EQ_OP; + template <typename U, std::enable_if_t<!std::is_same_v<T, U>>* = nullptr> + friend void operator!=(const QProperty &, const QProperty<U> &) QPROPERTY_DECL_DELETED_EQ_OP; +#undef QPROPERTY_DECL_DELETED_EQ_OP +#endif // !defined(Q_CC_GNU) || defined(Q_CC_CLANG) + parameter_type value() const { d.registerWithCurrentlyEvaluatingBinding(); @@ -520,6 +548,12 @@ private: return lhs.value() == rhs; } + template <typename U, std::enable_if_t<has_operator_equal_to_v<U>>* = nullptr> + friend bool comparesEqual(const QProperty &lhs, const U &rhs) + { + return lhs.value() == rhs; + } + void notify() { d.notifyObservers(this); diff --git a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp index 53a477edc22..aadcea9b9e8 100644 --- a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp +++ b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp @@ -84,6 +84,7 @@ private slots: void compatPropertySignals(); void compareAgainstValueType(); + void compareAgainstDifferentType(); void noFakeDependencies(); #if QT_CONFIG(thread) @@ -1771,6 +1772,18 @@ void tst_QProperty::compareAgainstValueType() QCOMPARE_NE(vl, o.varList); } +void tst_QProperty::compareAgainstDifferentType() +{ + QTestPrivate::testEqualityOperatorsCompile<QProperty<qsizetype>, int>(); + QTestPrivate::testEqualityOperatorsCompile<QProperty<qsizetype>, double>(); + + QProperty<qsizetype> p1{1}; + QCOMPARE_EQ(p1, 1); + QCOMPARE_EQ(1, p1); + QCOMPARE_NE(p1, 2.0); + QCOMPARE_NE(2.0, p1); +} + class FakeDependencyCreator : public QObject { Q_OBJECT |