[Development] RFC: RAII for property changes

Alan Alpert 416365416c at gmail.com
Wed Apr 15 19:55:12 CEST 2015


On Wed, Apr 15, 2015 at 8:08 AM, Matthew Woehlke
<mw_triad at users.sourceforge.net> wrote:
> On 2015-04-15 10:43, Marc Mutz wrote:
>> On Wednesday 15 April 2015 11:49:56 André Somers wrote:
>>> void MyClass::setFoo(QString value)
>>> {
>>>    PropertyGuard guard(this, "foo");  //foo is the name of the Q_PROPERTY
>>>    Q_UNUSED(guard);
>>>
>>>    m_foo = value;
>>> }
>>
>> This is an interesting idea, though I don't think I have encountered the
>> problems with which you motivate PropertyGuard.

I have, it comes up a lot in objects used as an interface to QML
(where every fooChanged signal will probably trigger binding
re-evaluation or JS blocks). I don't think it's that hard to manage,
but PropertyGuard does look easier and saves some boilerplate code.

>> For use in a library, though, I fear the string-based mechanism is too
>> inefficient. For use within QtWidgets, say, I'd suggest a mechanism that works
>> on the member data directly.

I think it's fine to tie it to the property system, since conceptually
it needs a both a read and a notify on the datum.

For performance, allow passing in a metaproperty index instead of a
property name string. It will still invoke the getter, but they're
rarely that complicated (and when they are, you need to go off the
getter value*).

> FWIW I had the same thought; also, I'm not a fan of needing the
> Q_UNUSED, or using a macro to 'hide' it.
>
> What about something like this?
>
>   QPropertyGuard g{this};
>   g.addProperty("a"); // use QObject::property
>   g.addProperty("b", m_b); // take value member by reference
>   g.addProperty(m_c, &cChanged); // ...and also slot address
>
> It's slightly redundant because declaring the guard and adding a
> property are separate, but there is no unused object, and you can use
> the same guard for multiple properties.

The common case is one property I think, so keep that case to one
line. I'd envision using it in all my basic setters to save code at
the start of a project, and then when the features start to creep in
it's easier to add complexity into the setters.

Still, you could always leave in a convenience constructor or just
wrap it in a macro as before.

* Example of when you need to go off getter value instead of member is
usually sometime like implicit width, where the getter looks like
getWidth() {
    if (m_width == -1)
        return m_implicitWidth;
    return m_width;
}
In this case, if you have m_width = 80, m_implicitWidth = 80, and call
setWidth(-1), then you actually don't want to emit widthChanged even
though m_width is updated.

That was just an example, not how implicit width actually is
implemented in QtQuick.

--
Alan Alpert



More information about the Development mailing list