[Development] QProperty and library coding guide

Volker Hilsheimer volker.hilsheimer at qt.io
Thu Jul 16 17:40:35 CEST 2020

> On 16 Jul 2020, at 17:19, Thiago Macieira <thiago.macieira at intel.com> wrote:
> On Thursday, 16 July 2020 03:43:58 PDT Volker Hilsheimer wrote:
>> The various macros involved provide this. Each property is represented by an
>> instance of a struct with no data members, but just methods that forward
>> calls to the accessor, which in Qt is typically the d-pointer (where the
>> QProperty itself lives as well).
> That's why I asked about 59*sizeof(void*) addition to QWidgetPrivate.
>> For pre-C++20 (where it’s possible to have zero-size structs), and for
>> compilers that don’t respect the [[no_unqiue_address]] attribute, all these
>> struct-instances are put into a union. In that case, a class using
>> QProperty will be larger (by the same amount no matter the number of
>> properties) than the same class in Qt 5. With C+++ 20 and compilers that do
>> respect [[no_unique_address]], the size and layout of these classes will be
>> the same.
> Hmm... design question then: if the address isn't relevant and the data inside 
> isn't relevant either (because it can't be), why do we need a member in the 
> first place? What information does it convey that is neither the address nor 
> the contents?

We need “text” to be a public member of QAction, otherwise we can’t do


That ‘text” member is a struct with a bunch of operators overloaded, so that we can do either

qDebug() << action->text();
qDebug() << action->text;


action->setText(“foo”); // no binding
action->text = document->title; // still no binding
action->text = Qt::makePropertyBinding(document->title); // yay binding!

These struct-methods are either inline forwards, or implemented by moc, and we need a differently named but identical struct for each property.

The struct has no data itself, so ideally would be of size zero. The moc-implementation redirects to whatever is passed into the Q_PRIVATE_QPROPERTY macro as the accessor, such as

Q_PRIVATE_QPROPERTY(QAction::d_func(), QString, text, setText);

moc generates the code to access d_func() in order to get to the data member, which is then a QProperty<QString> member of the QActionPrivate (or a QNotifedProperty in this case, but that’s unrelated).

So, for a class without d-pointer, this could just as well be

Q_PRIVATE_QPROPERTY(this, QString, text, setText);


PS: I don’t know why Q_PRIVATE_QPROPERTY is the name of the macro, I suppose it will be de-PRIVATE’ized at some point.

More information about the Development mailing list