Skip to content

Commit

Permalink
Don't test for equality if types can't be compared
Browse files Browse the repository at this point in the history
For types that don't have an operator==(), always trigger the binding
and the changed notification.

Task-number: QTBUG-85578
Change-Id: I41374f6d13c88106f4de83864e82172f3a248150
Reviewed-by: Fabian Kosmale <[email protected]>
  • Loading branch information
vohi committed Jul 15, 2020
1 parent 5f3f234 commit 1245908
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 6 deletions.
6 changes: 4 additions & 2 deletions src/corelib/kernel/qproperty.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
12 changes: 8 additions & 4 deletions src/corelib/kernel/qpropertyprivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,19 @@ struct QPropertyValueStorage
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;
}
Expand Down
72 changes: 72 additions & 0 deletions tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ private slots:
void notifiedProperty();
void notifiedPropertyWithOldValueCallback();
void notifiedPropertyWithGuard();
void typeNoOperatorEqual();
};

void tst_QProperty::functorBinding()
Expand Down Expand Up @@ -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);

Expand Down

0 comments on commit 1245908

Please sign in to comment.