Qt MetaType and Circular Dependency
-
Hi!
i have two qt classes which i intend to use in templates using the Grantlee library, the problem is the two classes use each other like in the code bellow that was working untill using grantlee if you are not familiar with grantlee it just fill template from qt objects like Django,jinja/file a.h class B; Q_DECLARE_METATYPE(QList<B*>) class A : public QOBject{ QOBJECT Q_PROPERTY(QList<B*> bList...) }; // file b.h class A; class B : public QOBject{ QOBJECT Q_PROPERTY(A* a...) };
the core problem is that to properly use 'a' and 'bList' in grantLee the Classes A&B need to be fully declared so i get this error QMetaProperty::read: Unable to handle unregistered datatype 'QList' for property 'A::bList'
i tried using Q_DECLARE_METATYPE(QList) and same for 'a' but Q_DECLARE_METATYPE require the class to be fully described so i tried with Q_DECLARE_OPAQUE_POINTER(B) i get this error grantlee.customtype: Don't know how to handle metatype B
is there a way to go around this circular dependency + qt properties problem ? or a change in the architecture is a must
-
@yassser said in Qt MetaType and Circular Dependency:
Hi!
Hi.
the core problem is that to properly use 'a' and 'bList' in grantLee the Classes A&B need to be fully declared so i get this error QMetaProperty::read: Unable to handle unregistered datatype 'QList' for property 'A::bList'
Where is
QMetaProperty::read
called? Where do you get the error?i tried using Q_DECLARE_METATYPE(QList) and same for 'a' but Q_DECLARE_METATYPE require the class to be fully described so i tried with Q_DECLARE_OPAQUE_POINTER(B) i get this error grantlee.customtype: Don't know how to handle metatype B
Q_DECLARE_METATYPE
is used with the actual type,QList
by itself isn't a "type" in the sense it's a template. To be compiled instantiantion needs to be performed, for which the template parameter must be known. Can you do something like this:typedef QList<B *> BList; Q_DECLARE_METATYPE(BList)
Does this produce an error?
is there a way to go around this circular dependency + qt properties problem ?
To me it's not exactly clear where the problem lies, so let's take it a step at a time.
-
Where is QMetaProperty::read called? Where do you get the error?
considering an instance 'aObj' given to grantlee engine to be rendered
and we want to get the property 'a' of the first Bobject in the blist
the error happened here {{ aObject.blist.0.a }} //0:first element
in normal circumstances it would work providing that you use #include 'b.h' in A and
#include 'a.h' in B to be able to render "aObject.blist.0" and "0.a"
but that would cause circular dependency
so is there some macro that register the type without having to include the file ?typedef QList<B *> BList;
Q_DECLARE_METATYPE(BList)
Does this produce an error?C2338: Type argument of Q_DECLARE_METATYPE(T*) must be fully defined
this is the error that it produces, note that the error dosnt show up when you include the header files instead of predefining the class. even when you use Q_DECLARE_METATYPE(QList<B*>) -
@VRonin
you are right ,when you are using just qt to access the property(getters/setters...) it would work whithout having to declare it, but grantlee require you to register the type to QVariant so it can use it in templates, like to access the first element and inspect it's properties {{ blist.0.propertyofb }} -
@yassser said in Qt MetaType and Circular Dependency:
you are right ,when you are using just qt to access the property(getters/setters...) it would work whithout having to declare it, but grantlee require you to register the type to QVariant so it can use it in templates, like to access the first element and inspect it's properties {{ blist.0.propertyofb }}
You can't register
QObject
s as metatypes and can't putQObject
s inQVariant
because they are can't be copied. By definition (a.k.a. metatype requirements) aQObject
derived class isn't and can't be a meta-type. The only thing you could possibly do is to have aQObject *
put into aQVariant
, but that's rather different.
That said, I still don't understand the problem, though, I have no idea what this library expects nor where (and by "where" I mean a concrete piece of c++ code) this error occurs. -
@kshegunov
Hi!You can't register QObjects as metatypes and can't put QObjects in QVariant because they are can't be copied. By definition (a.k.a. metatype requirements)
correct me if i'm wrong but does the copying part mean that you cant copy the properties to variant using QVariant::fromValue(QObject*) because it is working some QObject Derived classes in the Project , or you mean add the QObject subclass to the Qt Standard Types as in this exemple CustomTypes there is 3 requirement
Before we begin, we need to ensure that the custom type we are creating meets all the requirements imposed by QMetaType. In other words, it must provide:
a public default constructor,
a public copy constructor, and
a public destructor.or the
as for declaring QList<B*> i will switch to the typedef solution as it is more safe like you said although the other one(declar_type(QList<B*>)) is working somehow
but the core problem i'm facing is the requirement of Q_DECLARE_METATYPE(B*) that B should be fully defined(defining the class using #include'b.h' instead of 'class B') as i cant include the header files because it will cause circular dependency because A it self require the same process
-
@yassser said in Qt MetaType and Circular Dependency:
correct me if i'm wrong but does the copying part mean that you cant copy the properties to variant using QVariant::fromValue(QObject*) because it is working some QObject Derived classes in the Project , or you mean add the QObject subclass to the Qt Standard Types as in this exemple CustomTypes there is 3 requirement
Both. When adding a
QObject *
to aQVariant
you copy nothing, you just transfer a reference, and if that reference disappears in the mean time, well that's cause for concern.@yassser said in Qt MetaType and Circular Dependency:
as for declaring QList<B*> i will switch to the typedef solution as it is more safe like you said although the other one(declar_type(QList<B*>)) is working somehow
For what it's worth, declaration of metatypes should happen where the type is defined, not somewhere else. So even ideologically:
class B; Q_DECLARE_METATYPE(QList<B*>)
is wrong. That metatype declaration should've gone where
B
is defined, aside from it being needed or not.but the core problem i'm facing is the requirement of Q_DECLARE_METATYPE(B*) that B should be fully defined(defining the class using #include'b.h' instead of 'class B')
Still talking hypotheticals. I don't see any concrete error that one gets from the compiler, nor a specific piece of cpp code that's the cause of said error.
as i cant include the header files because it will cause circular dependency because A it self require the same process
Where does it require that and why? Please post a snippet, I'm getting rather frustrated here. Consider this in the meantime:
class B; typedef QList<B *> BList; class A { public: void setBList(const BList &); //< This doesn't require a definition of BList, and by extension a definition of B isn't required BList bList() const; //< Nor does this };