[Development] QMetaType and non-const references

Ulf Hermann ulf.hermann at qt.io
Tue Jul 19 23:50:32 CEST 2022

> Right now, if moc detects the  QML macros in the class definition, it forces
> the method parameters to be fully defined, not just forward declarations. But
> in your case here, the derived class without the macro or the parent will not
> get such a treatment and any type that is only forward declared will be
> missing a metatype. I'm not changing this.

That is unfortunate. We will probably be able to detect and complain 
about such types in qmllint and/or qmlcachegen, though.

>> b, You can separate the QML registration from the type declaration with
>> QML_FOREIGN. The QML_FOREIGN can live in a different library, and can
>> even be written in the future.
> Can you explain a little more what this is for?

Sure. Quite often we want to expose types to QML that we don't want to 
modify in their original place. See for example qtmultimedia. There we 
have a base library that shouldn't depend on QML and that shouldn't 
contain QML-specific macros. In addition we have a QML-integration 
library that needs to handle types from the base library in various ways.

If it's only a matter of instantiating the types, you can get away with 
inheriting from them and adding the QML macros in the derived types. 
However, if the types from the base library have factory functions or 
properties that supply instances of the _base_ types, then you don't 
have a QML name for those if you only register the derived types. 
Consequently, you can't assign them to any of your QML-typed properties. 
You can fix that again, with a lot of boiler plate to wrap properties 
and methods, but at that point QML_FOREIGN is much more convenient.

> QVariant will not change: it will require default-constructible, copyable and
> destructible types. Any acceptance of a metatype that isn't one of those is a
> bug.

"will not change" apparently means "I'm not doing it right now". I'm 
aware that it would be a new feature, but I can imagine someone adding 
support for move-only types to QVariant eventually. We may not actually 
need it though. Your point below, about QMetaType being enough to handle 
move-only types in QML, is valid.

> By the way, do you need the metatype for the QObject-derived class, or do you
> need the metatype for the pointer to that class? There's a mighty difference
> (QObjects can't be copied, sometimes they don't have accessible default
> constructors), including because the extraction in QMetaType flag is
> "IsPointerTOQObject", not "IsQObject".

We generally pass QObject-derived classes as pointers in QML. So we 
usually need the metatype of the pointer. However, those are the less 
interesting metatypes. The more interesting ones are the metatypes of 
QML value types. QML value types are pretty much everything except 
QObjects and namespaces, and we pass those by value. So we do have to 
construct/copy/destruct them and sometimes it would be quite handy to 
move them, too.

>> Furthermore, if I have the metatypes available, I can come up with more
>> interesting functionality in the future (for example making QML's value
>> type references actual references). So, if it's not horribly
>> complicated, I would indeed like as many metatypes as possible to be
>> available.
> Ok, thanks. What about rvalue references?

I currently don't have any plans for them, but we need more syntax for 
value types in QML anyway. Depending on how we phrase this, we might 
support moving them, explicitly or implicitly. If we could then know 
that a method takes an rvalue ref as parameter, that would be 
beneficial. However, all of this is quite far in the future.

>>> - reject non-default constructible, non-copyable or non-destructible types
>>> in QVariant but not QMetaType -- this includes non-const references
>> Right now this is probably the correct thing to do. However, once we
>> allow moving into and out of QVariant, we should revise this.
> Movable but not copyable or not default constructible?

Non-default-constructible but movable is an interesting API challenge 
for QVariant, but I wouldn't rule it out just yet. We don't have to 
implement all of this right away, but we shouldn't take decisions now 
that make such a thing impossible in the future.

> QMetaType could support them directly. The construct/create operations are
> independent from destroy/destruct, or from each other. If a type today is not
> default constructible, but is copyable, QMetaType *can* copy it onto a new
> void* array of yours. That same does not extend to QVariant today.

QMetaType being able to deal with all the cases may in fact be good 
enough. There are ways to avoid QVariant.

best regards,

More information about the Development mailing list