Hi,

Reviving an old thread as I am currently working on QMetaType.

QMetaType is a low level API of Qt, normally a developer shouldn't use it much in its application, and the goal for Qt6 is that there is even less to know about it. In short, the goal was to remove the use for Q_DECLARE_METATYPE, qRegisterMetaType, and other particularities, while also making it faster to use properties and method from QML.

The idea is that the moc generated code would put already the QMetaType in its data structure (by calling the equivalent of qMetaTypeId())

But that means that the type need to be fully defined in the moc generated file.

let's imagine:

class MyType; // forward declared

class MyObject : public QObject { Q_OBJECT
 Q_PROPERTY(MyType *prop ...)
signals:
 void mySignal(MyType *);
slots:
 void mySlot(MyType *);
  // ...
};


That will not be working anymore if the MyType is only worward declared.
The user will have to do one of these:
 1. #include "MyType.h"  in the header
 2. Q_DECLARE_OPAQUE_POINTER(MyType *)
3. Q_MOC_INCLUDE("MyType.h") : that's not yet implemented but would make moc include the file in the generated file.

That's a source incompatible change, and the question is if we really want it.
For the property types, i'd say yes: the types need to be registered for the properties to be useful anyway. For the types in the signals an and slot, maybe not. If you do not use QueuedConnection, you do not need to register the types. (well, actually, we still need to compare their name for the string based connection syntax) however, to be called from QML, then the type need to be register. I'm tempted to say that they should be registered. as well.


Now another question is what exactly do we want to automatically register.
Of course, we will register the way to construct, copy, and destruct the types.
Now, should we also register automatically the other things that we can do:

 - operator==
 - QDataStream operators
 - QDebug operator

Ideally we also want this to be automatic, but i've run into an issue.
I naively tought it would be simple enough to just use SFINAE to detect if the type has the operator==, with something like that.

template<typename T, typename=bool> struct HasEqualityOperator : false_type {};
template<typename T> struct HasEqualityOperator<T,
        decltype(declval<T>() == declval<T>())> : true_type {};

But the problem is that this will return true_type if the operator exists, not if it compile.

Say I have a  `struct CustomType { int x; };` that cannot be compared.
This can registered as a QMetaType and the operator== will not be registered.
But now what about `QVector<CustomType>`? If one tries to register that as an QMetaType, it will register the operator== because QVector has one. The problem is that when trying to actually compile it, the compilation will fail :-( So that means QVector<CustomType> cannot be registered without causing a compilation error, or one need to explicitly delete the `operator==(QVector<CustomType>, QVector<CustomType>)`

Same problem with the stream operators and debug operators.

Also registering them automatically implies that the operator need to be visible so qdatastream and qdebug need to be included everywhere.

So the question is if this breaking change is worth it?

Do we want to automatically register the operators?
Do we want to automatically register the types used in signal/slots, or just the properties?

--
Olivier
_______________________________________________
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development

Reply via email to