summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qproperty.h34
-rw-r--r--tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp13
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