Porting to Qt5 - issue with Q_PROPERTY(QVector<OwnClass>)



  • I have started porting my application to Qt5 and I stumbled upon an issue that did not show up with Qt 4.8

    In one of my class I define a Q_PROPERTY

    Q_PROPERTY(QVector<Rule> rules MEMBER rules)
    

    and this is the compile error I get

    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\xutility(2737): error C2678: binary '==' : no operator found which takes a left-hand operand of type 'const Rule' (or there is no acceptable conversion)
    

    Rule is a pretty simple class, derive from QObject. I tried adding Q_DECLARE_METATYPE(Rule) but it doesn't help.
    I'm not sure why that "const" shows up in the error message. Do you have any clue what could be wrong?


  • Lifetime Qt Champion

    Hi,

    Then there's something that's fishy with your code. You shouldn't be able to create a QVector of QObject based objects.

    Did you by any chance implement the assignment and copy operators for your Rule class ?

    By the way, why do you need it to be a QObject ?



  • Thanks for taking time to answer.
    Pretty sure I have implemented assign/copy operators for this class, will check ASAP.
    That or the Q_NO_COPY macro are required in order to use QVector<QObject> right? Or is it just impossible? The code use to work without issue in Qt4.8
    One of the reasons Rule inherits from QObject it that QVector<Rule> is exposed to scripts using QtScript and QObjects are automagically exposed thanks to the Meta-Object system. Rule doesn't have slots/signal only Q_PROPERTY.
    Is it possible/recommended to use QGadget instead?



  • Please read http://doc.qt.io/qt-5/qobject.html#no-copy-constructor-or-assignment-operator
    if you don't use signals and slots switch to a plain class with the Q_GADGET macro



  • @VRonin said:

    Q_GADGET

    I will give it a try EDIT: it doesn't help, I have the exact same error message + qRegisterMetaType now fails
    Here is what the class look like (I'm still wondering why it was fine with Qt4)

    class Rule : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QString name MEMBER name)
        Q_PROPERTY(int diameter MEMBER diam)
        Q_PROPERTY(QVector<double> sBoundaries MEMBER sBoundaries)
        Q_PROPERTY(QVector<double> dBoundaries MEMBER dBoundaries)
        Q_PROPERTY(QVector<int> sCriteria MEMBER sCriteria)
        Q_PROPERTY(QVector<int> dCriteria MEMBER dCriteria)
    
    public:
        Rule(QObject* parent = 0) : QObject(parent), zoneName("name"), diam(50)
        {
            sBoundaries << 1 << 3;
            dBoundaries << 0 << 4;
            sCriteria << -1 <<  4 << 0;
            dCriteria << -1 << -1 << 2;
        }
        Rule &operator=(const Rule & other)
        {
            const QMetaObject* metaObject = other.metaObject();
            for( int i=metaObject->propertyOffset(); i<metaObject->propertyCount(); ++i )
                setProperty(metaObject->property(i).name(), other.property(metaObject->property(i).name()));
            return *this;
        }
        Rule(const Rule& other) {*this = other;}
    
        QString zoneName;
        int diam;
        QVector<double> sBoundaries, dBoundaries;
        QVector<int> sCriteria, dCriteria;
    };
    

  • Lifetime Qt Champion

    Why not use QVector<Rule *> ?

    If you need to copy that object, you can add a clone function.



  • That's what I plan to do but it's still unclear to me what changes in Qt5 broke my (probably bad) design.

    I'm also having linkage issues on custom classes that I expose to QtScript with qScriptRegisterMetaType. Does the class implementation has to be fully known for this to work? Again it was working fine with Qt4.8 by just including the header file. It seems that the linker is now looking for the moc_ file which I'm almost sure wasn't the case with Qt4.8
    Also it seems that some qScriptRegisterMetaType calls are now useless because I've removed some of them and I can still use those class in my scripts ... weird it's like calling qRegisterMetaType is enough now.

    Maybe I'm doing it wrong. All I want is to access from QtScript existing Q_Objects that live in my c++ code
    I don't need to be able to instanciate them in scripts, I don't need to copy them, etc.



  • Ok well it looks like Q_DECLARE_OPAQUE_POINTER() is what I need here, but again any recommendations of a better design (if possible) will be appreciated. Thanks for your help!


  • Qt Champions 2016

    @JulienMaille

    I don't need to be able to instanciate them in scripts, I don't need to copy them, etc.

    Then why are you defining a copy constructor and an assignment operator for QObjects when you were specifically told not to do it?

    Rule(const Rule& other) {*this = other;}    //< This, by the way, is wrong at the C++ level as well.
    Rule &operator=(const Rule & other);
    

    Additionally Q_DECLARE_METATYPE and qRegisterMetaType are not purposed to be used for QObject derived classes.



  • @kshegunov said:

    you're doing it wrong

    Well the problem is with Qt4.8 at least:

    Any class or struct that has a public default constructor, a public copy constructor, and a public destructor can be registered with Q_DECLARE_METATYPE

    So the trick is to only use it on pointers to QObjects?
    Or is it totally useless for QObject derived class?


  • Lifetime Qt Champion

    The usage description of Q_DECLARE_METATYPE is the same in Qt 5.

    But anyway, yes use a QVector<Rules *> that's how it's intended to be used.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.