[Development] QMetaType and non-const references
thiago.macieira at intel.com
Tue Jul 19 00:13:30 CEST 2022
tl;dr: QMetaTypes currently allow T&, but the implementation looks b0rked.
Need input from people who may want that (read: QML) to know what to do.
I was doing some work on QMetaObject that spilled over to fixing some things in
QMetaType. I realised that since 6.0 we *do* allow meta types for types that
aren't default-constructible or copiable, which includes references. This is
due to the rewrite by Olivier in 6.0 times, which effectively made
Q_DECLARE_METATYPE a no-op (yes, you've read me right: the macro is
unnecessary). But as a result we've introduced subtle issues where a non-const
reference was used as a metatype where it maybe shouldn't (and
QMetaType::fromType allowed it, which is what the change above fixes).
For example, for the purposes of the metatype system -- as used in the signal-
slot connection -- a const T& is interpreted as a T and normalizeType performs
that change. But a T& is not and has never been the same as a T, and you can't
make that connection with invokeMethod+Q_ARG either.
In https://codereview.qt-project.org/c/qt/qtbase/+/422132, I'm making
QMetaType::from<T&> explicitly fail.
So the question to the dev community is what we should do to non-const
references as metatypes. And as a side question, if we should support non-
default-constructible, non-destructible and/or non-copyable types as metatypes
in the first place, or reject them like Qt 4 & 5 did.
My personal feeling is that we should:
- reject them in QMetaType::fromType, since they're usually not what you
wanted. See https://codereview.qt-project.org/c/qt/qtquick3d/+/422197
- reject non-default constructible, non-copyable or non-destructible types in
QVariant but not QMetaType -- this includes non-const references
=> corollary: need a way to form them, but not QMetaType::fromType.
- do use them in QMetaObject for reporting purposes
- add a way to link a T& metatype back to T's
However, please note I cannot guarantee all of the tasks above can be done in
time for 6.5. I actually want some of the bug-fixing in 6.4, like the change at
the top of this email. So what's mandatory as a unit?
There's a question on what to do to rvalue references, but please address that
separately, as we don't support them at all right now, not even for signal-
slot connections in the new syntax I believe.
The QMetaType code has accumulated a hairy mess of templates developed by
different people at different times (Harry back in Qt 4 days when we supported
pre-C++98 compilers, Stephen in early 5.x days for pre-C++11, additional work
by some others for late 5.x with C++11, Olivier for 6.0 with C++17) to the
point that I as the maintainer cannot follow what goes where and the sequence
of SFINAE detections. Even after 6.0 some changes assumed that
Q_DECLARE_METATYPE was required, when it isn't, so QMetaType behaves subtly
different whether you use it or not. The code needs to be cleaned to the point
that I understand it before I will allow any new feature work for it.
Thiago Macieira - thiago.macieira (AT) intel.com
Cloud Software Architect - Intel DCAI Cloud Engineering
More information about the Development