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 return false; } + template + struct has_operator_equal_to : std::false_type{}; + + template + struct has_operator_equal_to() == std::declval()))>> + : std::true_type{}; + + template + static constexpr bool has_operator_equal_to_v = + !std::is_same_v && has_operator_equal_to::value; + public: using value_type = typename QPropertyData::value_type; using parameter_type = typename QPropertyData::parameter_type; @@ -388,6 +399,23 @@ public: QT_DECLARE_EQUALITY_OPERATORS_HELPER(QProperty, T, /* non-constexpr */, noexcept(false), template >* = nullptr>) QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(QProperty, T, /* non-constexpr */, noexcept(false), template >* = nullptr>) + QT_DECLARE_EQUALITY_OPERATORS_HELPER(QProperty, U, /* non-constexpr */, noexcept(false), template >* = nullptr>) + QT_DECLARE_EQUALITY_OPERATORS_REVERSED_HELPER(QProperty, U, /* non-constexpr */, noexcept(false), template >* = nullptr>) + + // Explicitly delete op==(QProperty, QProperty) 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 >* = nullptr> + friend void operator==(const QProperty &, const QProperty &) QPROPERTY_DECL_DELETED_EQ_OP; + template >* = nullptr> + friend void operator!=(const QProperty &, const QProperty &) 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 >* = 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, int>(); + QTestPrivate::testEqualityOperatorsCompile, double>(); + + QProperty 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