summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/global/qtypeinfo.h10
-rw-r--r--src/corelib/kernel/qproperty.h42
-rw-r--r--src/corelib/kernel/qpropertyprivate.h2
-rw-r--r--tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp29
4 files changed, 70 insertions, 13 deletions
diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h
index 30db5c4487..c0617a41f2 100644
--- a/src/corelib/global/qtypeinfo.h
+++ b/src/corelib/global/qtypeinfo.h
@@ -324,6 +324,16 @@ struct expand_operator_less_than_tuple<std::variant<T...>> : expand_operator_les
}
+template<typename T, typename = void>
+struct is_dereferenceable : std::false_type {};
+
+template<typename T>
+struct is_dereferenceable<T, std::void_t<decltype(std::declval<T>().operator->())> >
+ : std::true_type {};
+
+template <typename T>
+constexpr bool is_dereferenceable_v = is_dereferenceable<T>::value;
+
template<typename T>
struct has_operator_equal : detail::expand_operator_equal<T> {};
template<typename T>
diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h
index acaf74f9af..ff61596fb6 100644
--- a/src/corelib/kernel/qproperty.h
+++ b/src/corelib/kernel/qproperty.h
@@ -192,8 +192,15 @@ struct QPropertyBasePointer;
template <typename T>
class QProperty
{
+ class DisableRValueRefs {};
+ static constexpr bool UseReferences = !(std::is_arithmetic_v<T> || std::is_enum_v<T> || std::is_pointer_v<T>);
+
public:
using value_type = T;
+ using parameter_type = std::conditional_t<UseReferences, const T &, T>;
+ using rvalue_ref = typename std::conditional_t<UseReferences, T &&, DisableRValueRefs>;
+ using arrow_operator_result = std::conditional_t<std::is_pointer_v<T>, const T &,
+ std::conditional_t<QTypeTraits::is_dereferenceable_v<T>, const T &, void>>;
QProperty() = default;
explicit QProperty(const T &initialValue) : d(initialValue) {}
@@ -218,7 +225,7 @@ public:
#endif
~QProperty() = default;
- T value() const
+ parameter_type value() const
{
if (d.priv.hasBinding())
d.priv.evaluateIfDirty();
@@ -226,32 +233,49 @@ public:
return d.getValue();
}
- operator T() const
+ arrow_operator_result operator->() const
+ {
+ if constexpr (QTypeTraits::is_dereferenceable_v<T>) {
+ return value();
+ } else if constexpr (std::is_pointer_v<T>) {
+ value();
+ return this->val;
+ } else {
+ return;
+ }
+ }
+
+ parameter_type operator*() const
{
return value();
}
- void setValue(T &&newValue)
+ operator parameter_type() const
+ {
+ return value();
+ }
+
+ void setValue(rvalue_ref newValue)
{
d.priv.removeBinding();
if (d.setValueAndReturnTrueIfChanged(std::move(newValue)))
notify();
}
- void setValue(const T &newValue)
+ void setValue(parameter_type newValue)
{
d.priv.removeBinding();
if (d.setValueAndReturnTrueIfChanged(newValue))
notify();
}
- QProperty<T> &operator=(T &&newValue)
+ QProperty<T> &operator=(rvalue_ref newValue)
{
setValue(std::move(newValue));
return *this;
}
- QProperty<T> &operator=(const T &newValue)
+ QProperty<T> &operator=(parameter_type newValue)
{
setValue(newValue);
return *this;
@@ -263,12 +287,6 @@ public:
return *this;
}
- QProperty<T> &operator=(QPropertyBinding<T> &&newBinding)
- {
- setBinding(std::move(newBinding));
- return *this;
- }
-
QPropertyBinding<T> setBinding(const QPropertyBinding<T> &newBinding)
{
QPropertyBinding<T> oldBinding(d.priv.setBinding(newBinding, &d));
diff --git a/src/corelib/kernel/qpropertyprivate.h b/src/corelib/kernel/qpropertyprivate.h
index d5ee9f29c2..4d8a457e32 100644
--- a/src/corelib/kernel/qpropertyprivate.h
+++ b/src/corelib/kernel/qpropertyprivate.h
@@ -136,7 +136,7 @@ public:
QPropertyValueStorage(QPropertyValueStorage &&other) : value(std::move(other.value)), priv(std::move(other.priv), this) {}
QPropertyValueStorage &operator=(QPropertyValueStorage &&other) { value = std::move(other.value); priv.moveAssign(std::move(other.priv), &value); return *this; }
- T getValue() const { return value; }
+ T const& getValue() const { return value; }
bool setValueAndReturnTrueIfChanged(T &&v)
{
if constexpr (QTypeTraits::has_operator_equal_v<T>) {
diff --git a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
index 74a81cc93b..20565080ff 100644
--- a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
+++ b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
@@ -69,6 +69,7 @@ private slots:
void setBindingFunctor();
void multipleObservers();
void propertyAlias();
+ void arrowAndStarOperator();
void notifiedProperty();
void notifiedPropertyWithOldValueCallback();
void notifiedPropertyWithGuard();
@@ -753,6 +754,34 @@ void tst_QProperty::propertyAlias()
QCOMPARE(value2, 22);
}
+void tst_QProperty::arrowAndStarOperator()
+{
+ QString str("Hello");
+ QProperty<QString *> prop(&str);
+
+ QCOMPARE(prop->size(), str.size());
+ QCOMPARE(**prop, str);
+
+ struct Dereferenceable {
+ QString x;
+ QString *operator->() { return &x; }
+ const QString *operator->() const { return &x; }
+ };
+ static_assert(QTypeTraits::is_dereferenceable_v<Dereferenceable>);
+
+ QProperty<Dereferenceable> prop2(Dereferenceable{str});
+ QCOMPARE(prop2->size(), str.size());
+ QCOMPARE(**prop, str);
+
+ QObject *object = new QObject;
+ object->setObjectName("Hello");
+ QProperty<QSharedPointer<QObject>> prop3(QSharedPointer<QObject>{object});
+
+ QCOMPARE(prop3->objectName(), str);
+ QCOMPARE(*prop3, object);
+
+}
+
struct ClassWithNotifiedProperty
{
QList<int> recordedValues;