[Development] QProperty and library coding guide
Ulf Hermann
ulf.hermann at qt.io
Fri Jul 17 15:01:31 CEST 2020
>>>> QAction *action = ~~~;
>>>> auto prop = action->text;
>> This already gives you the string. You cannot retrieve the property
>> itself. You can alternatively do action->text() or action->text.value().
>> They all do the same thing.
>
> Uhm... sorry, no, this doesn't really compute for me. Ignore the copy
> semantics for a second (use const auto &, if necessary), what's
> decltype(prop)? If it's QString, then you can't write .value() after it.
OK, I got you wrong, and I was confused about the cast operators in
QProperty and the property wrappers. Sorry. Indeed "auto prop =
action->text;" would give you a useless object that pokes random memory
whenever you invoke any method of it. That needs to be fixed indeed. You
should not be able to copy the property wrapper out of the object. For
properties on QObject that would be easy as QObject itself is not
copyable. We could just =delete the copy ctor and assignment operators.
We might also prevent external construction of the struct by having some
"secret" extra argument, kind of like QPrivateSignal.
However, for Q_GADGET this would fall apart.
For reference, Q_PRIVATE_QPROPERTY looks like this:
#define Q_PRIVATE_QPROPERTY(accessor, type, name, setter, ...) \
struct _qt_property_api_##name { \
type value() const; \
type operator()() const { return value(); } \
void setValue(type &&); \
void setValue(type const &); \
void operator=(type const &v) { setValue(v); } \
void operator=(type &&v) { setValue(std::move(v)); } \
QPropertyBinding<type> setBinding(const
QPropertyBinding<type> &); \
QPropertyBinding<type>
setBinding(QPropertyBinding<type> &&); \
QPropertyBinding<type> operator=(const
QPropertyBinding<type> &b) { return setBinding(b); } \
QPropertyBinding<type> operator=(QPropertyBinding<type>
&&b) { return setBinding(std::move(b)); } \
bool setBinding(const QUntypedPropertyBinding &); \
template <typename Functor> \
QPropertyBinding<type> setBinding(Functor f, \
const
QPropertyBindingSourceLocation &location =
QT_PROPERTY_DEFAULT_BINDING_LOCATION) \
{ \
return setBinding(Qt::makePropertyBinding(f,
location)); \
} \
bool hasBinding() const; \
QPropertyBinding<type> binding() const; \
QPropertyBinding<type> takeBinding(); \
}; \
void setter(type const& value);
So, in fact we need to rework this and provide only methods instead of a
struct. Now we need a naming convention for all those methods and some
way of avoiding name clashes.
If QNotifiedProperty didn't need members of the private object as
template parameters, we could just have one extra method that retrieves
a reference to the underlying Q(Notified)Property (or rather two: const
and non-const).
> No, actually this makes perfect sense, but was contradicted before:
>> We are not casting these structs to or from anything though, do we?
That statement was wrong. We do need to cast the structs. Another
argument for eliminating them.
best,
Ulf
More information about the Development
mailing list