Q(ObjectBindable)Property: Properly support comparisons
Before, it was possible to do some comparisons due to the implicit conversion to T. However, that does not work in all contexts. Fix this by explicitly declaring the comparison operators. We need to a) use the helper macro directly, as the operartors are only available if the underlying type has them and b) mark the operator as noexcept(false), as capturing a property in a binding might allocate. Fixes: QTBUG-134921 Change-Id: I2855964ba481b9e7778a4a7076528593549910fe Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
This commit is contained in:
parent
dc45850c1e
commit
e115c60b6d
@ -1277,6 +1277,9 @@ QString QPropertyBindingError::description() const
|
||||
\inmodule QtCore
|
||||
\brief The QProperty class is a template class that enables automatic property bindings.
|
||||
\since 6.0
|
||||
\compares equality
|
||||
\compareswith equality T
|
||||
\endcompareswith
|
||||
|
||||
\ingroup tools
|
||||
|
||||
@ -1486,6 +1489,9 @@ QString QPropertyBindingError::description() const
|
||||
automatic property bindings for property data stored in QObject derived
|
||||
classes.
|
||||
\since 6.0
|
||||
\compares equality
|
||||
\compareswith equality T
|
||||
\endcompareswith
|
||||
|
||||
\ingroup tools
|
||||
|
||||
|
@ -384,6 +384,10 @@ public:
|
||||
#endif
|
||||
~QProperty() = default;
|
||||
|
||||
QT_DECLARE_EQUALITY_OPERATORS_HELPER(QProperty, QProperty, /* 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, 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>)
|
||||
|
||||
parameter_type value() const
|
||||
{
|
||||
d.registerWithCurrentlyEvaluatingBinding();
|
||||
@ -504,6 +508,18 @@ public:
|
||||
|
||||
const QtPrivate::QPropertyBindingData &bindingData() const { return d; }
|
||||
private:
|
||||
template <typename Ty = T, std::enable_if_t<QTypeTraits::has_operator_equal_v<Ty>>* = nullptr>
|
||||
friend bool comparesEqual(const QProperty &lhs, const QProperty &rhs)
|
||||
{
|
||||
return lhs.value() == rhs.value();
|
||||
}
|
||||
|
||||
template <typename Ty = T, std::enable_if_t<QTypeTraits::has_operator_equal_v<Ty>>* = nullptr>
|
||||
friend bool comparesEqual(const QProperty &lhs, const T &rhs)
|
||||
{
|
||||
return lhs.value() == rhs;
|
||||
}
|
||||
|
||||
void notify()
|
||||
{
|
||||
d.notifyObservers(this);
|
||||
@ -1068,6 +1084,10 @@ public:
|
||||
explicit QObjectBindableProperty(Functor &&f);
|
||||
#endif
|
||||
|
||||
QT_DECLARE_EQUALITY_OPERATORS_HELPER(QObjectBindableProperty, QObjectBindableProperty, /* non-constexpr */, noexcept(false), template <typename Ty = T, std::enable_if_t<QTypeTraits::has_operator_equal_v<Ty>>* = nullptr>)
|
||||
QT_DECLARE_EQUALITY_OPERATORS_HELPER(QObjectBindableProperty, 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(QObjectBindableProperty, T, /* non-constexpr */, noexcept(false), template <typename Ty = T, std::enable_if_t<QTypeTraits::has_operator_equal_v<Ty>>* = nullptr>)
|
||||
|
||||
parameter_type value() const
|
||||
{
|
||||
qGetBindingStorage(owner())->registerDependency(this);
|
||||
@ -1208,6 +1228,18 @@ public:
|
||||
return *storage->bindingData(const_cast<ThisType *>(this), true);
|
||||
}
|
||||
private:
|
||||
template <typename Ty = T, std::enable_if_t<QTypeTraits::has_operator_equal_v<Ty>>* = nullptr>
|
||||
friend bool comparesEqual(const QObjectBindableProperty &lhs, const QObjectBindableProperty &rhs)
|
||||
{
|
||||
return lhs.value() == rhs.value();
|
||||
}
|
||||
|
||||
template <typename Ty = T, std::enable_if_t<QTypeTraits::has_operator_equal_v<Ty>>* = nullptr>
|
||||
friend bool comparesEqual(const QObjectBindableProperty &lhs, const T &rhs)
|
||||
{
|
||||
return lhs.value() == rhs;
|
||||
}
|
||||
|
||||
void notify(const QtPrivate::QPropertyBindingData *binding)
|
||||
{
|
||||
if (binding)
|
||||
|
@ -16,4 +16,5 @@ qt_internal_add_test(tst_qproperty
|
||||
tst_qproperty.cpp
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
Qt::TestPrivate
|
||||
)
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <qproperty.h>
|
||||
#include <private/qproperty_p.h>
|
||||
#include <private/qobject_p.h>
|
||||
#include <private/qcomparisontesthelper_p.h>
|
||||
|
||||
#if __has_include(<source_location>) && __cplusplus >= 202002L && !defined(Q_QDOC)
|
||||
#include <source_location>
|
||||
@ -82,6 +83,8 @@ private slots:
|
||||
void compatPropertyNoDobuleNotification();
|
||||
void compatPropertySignals();
|
||||
|
||||
void compareAgainstValueType();
|
||||
|
||||
void noFakeDependencies();
|
||||
#if QT_CONFIG(thread)
|
||||
void threadSafety();
|
||||
@ -1735,6 +1738,39 @@ void tst_QProperty::compatPropertySignals()
|
||||
QCOMPARE(arguments.at(0).toInt(), 42);
|
||||
}
|
||||
|
||||
struct CompareTestObject : QObject{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CompareTestObject(const QVariantList &l) { varList = l; }
|
||||
Q_OBJECT_BINDABLE_PROPERTY(CompareTestObject, QVariantList, varList)
|
||||
};
|
||||
|
||||
|
||||
void tst_QProperty::compareAgainstValueType()
|
||||
{
|
||||
{
|
||||
// compile time checks
|
||||
QTestPrivate::testEqualityOperatorsCompile<QProperty<QVariantList>>();
|
||||
QTestPrivate::testEqualityOperatorsCompile<QProperty<QVariantList>, QVariantList>();
|
||||
|
||||
using ObjectBindableProperty = decltype(std::declval<CompareTestObject>().varList);
|
||||
|
||||
QTestPrivate::testEqualityOperatorsCompile<ObjectBindableProperty>();
|
||||
QTestPrivate::testEqualityOperatorsCompile<ObjectBindableProperty, QVariantList>();
|
||||
}
|
||||
|
||||
QVariantList vl {1, QString(), QByteArray {}};
|
||||
QProperty<QVariantList> vlProp { vl };
|
||||
CompareTestObject o { vl };
|
||||
|
||||
QCOMPARE_EQ(vl, vlProp);
|
||||
QCOMPARE_EQ(vl, o.varList);
|
||||
|
||||
vl.pop_back();
|
||||
QCOMPARE_NE(vl, vlProp);
|
||||
QCOMPARE_NE(vl, o.varList);
|
||||
}
|
||||
|
||||
class FakeDependencyCreator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
Loading…
x
Reference in New Issue
Block a user