diff options
-rw-r--r-- | src/corelib/kernel/qproperty.h | 6 | ||||
-rw-r--r-- | src/corelib/kernel/qpropertyprivate.h | 12 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp | 72 |
3 files changed, 84 insertions, 6 deletions
diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h index 5d26c1c0f4..c2949c3022 100644 --- a/src/corelib/kernel/qproperty.h +++ b/src/corelib/kernel/qproperty.h @@ -155,8 +155,10 @@ class QPropertyBinding : public QUntypedPropertyBinding { PropertyType *propertyPtr = static_cast<PropertyType *>(dataPtr); PropertyType newValue = impl(); - if (newValue == *propertyPtr) - return false; + if constexpr (QTypeTraits::has_operator_equal_v<PropertyType>) { + if (newValue == *propertyPtr) + return false; + } *propertyPtr = std::move(newValue); return true; } diff --git a/src/corelib/kernel/qpropertyprivate.h b/src/corelib/kernel/qpropertyprivate.h index ad5ed59e88..dde6bb8d01 100644 --- a/src/corelib/kernel/qpropertyprivate.h +++ b/src/corelib/kernel/qpropertyprivate.h @@ -139,15 +139,19 @@ public: T getValue() const { return value; } bool setValueAndReturnTrueIfChanged(T &&v) { - if (v == value) - return false; + if constexpr (QTypeTraits::has_operator_equal_v<T>) { + if (v == value) + return false; + } value = std::move(v); return true; } bool setValueAndReturnTrueIfChanged(const T &v) { - if (v == value) - return false; + if constexpr (QTypeTraits::has_operator_equal_v<T>) { + if (v == value) + return false; + } value = v; return true; } diff --git a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp index 5f17bcb2b7..41cf60b55f 100644 --- a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp +++ b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp @@ -72,6 +72,7 @@ private slots: void notifiedProperty(); void notifiedPropertyWithOldValueCallback(); void notifiedPropertyWithGuard(); + void typeNoOperatorEqual(); }; void tst_QProperty::functorBinding() @@ -985,6 +986,77 @@ void tst_QProperty::notifiedPropertyWithGuard() } } +void tst_QProperty::typeNoOperatorEqual() +{ + struct Uncomparable + { + int data = -1; + bool changedCalled = false; + + Uncomparable(int value = 0) + : data(value) + {} + Uncomparable(const Uncomparable &other) + { + data = other.data; + changedCalled = false; + } + Uncomparable(Uncomparable &&other) + { + data = other.data; + changedCalled = false; + other.data = -1; + other.changedCalled = false; + } + Uncomparable &operator=(const Uncomparable &other) + { + data = other.data; + return *this; + } + Uncomparable &operator=(Uncomparable &&other) + { + data = other.data; + changedCalled = false; + other.data = -1; + other.changedCalled = false; + return *this; + } + bool operator==(const Uncomparable&) = delete; + bool operator!=(const Uncomparable&) = delete; + + void changed() + { + changedCalled = true; + } + }; + + Uncomparable u1 = { 13 }; + Uncomparable u2 = { 27 }; + + QProperty<Uncomparable> p1; + QProperty<Uncomparable> p2 = Qt::makePropertyBinding(p1); + + QCOMPARE(p1.value().data, p2.value().data); + p1.setValue(u1); + QCOMPARE(p1.value().data, u1.data); + QCOMPARE(p1.value().data, p2.value().data); + p2.setValue(u2); + QCOMPARE(p1.value().data, u1.data); + QCOMPARE(p2.value().data, u2.data); + + QProperty<Uncomparable> p3 = Qt::makePropertyBinding(p1); + p1.setValue(u1); + QCOMPARE(p1.value().data, p3.value().data); + + QNotifiedProperty<Uncomparable, &Uncomparable::changed> np; + QVERIFY(np.value().data != u1.data); + np.setValue(&u1, u1); + QVERIFY(u1.changedCalled); + u1.changedCalled = false; + QCOMPARE(np.value().data, u1.data); + np.setValue(&u1, u1); + QVERIFY(u1.changedCalled); +} QTEST_MAIN(tst_QProperty); |