Search code examples
c++qtqvariant

Add private sub class to Q_DECLARE_METATYPE


How to add MySubClass to Q_DECLARE_METATYPE.

This is sample code and please ignoring business of code.

#include <QMetaType>
#include <QVariant>
#include <QDebug>

namespace MyNS {
    class MyClass : public QObject {
    public:
        MyClass() : value(0) { }
        MyClass(int value) : value(value) { }
        MyClass(const MyClass &other) { value = other.value; }
        ~MyClass() { }
        int getValue() const {
            MySubClass msc(value);
            QVariant v = QVariant::fromValue(msc);
            int tempV = v.value<MySubClass>().getSubValue();
            return tempV;
        }
    private:
        class MySubClass
        {
        public:
            MySubClass() : subValue(0) {}
            MySubClass(int v) : subValue(v)
            {

            }
            int getSubValue()
            {
                return subValue;
            }
        private:
            int subValue;
        };
//        Q_DECLARE_METATYPE(MySubClass);  error : 'QMetaTypeId<MyNS::MyClass::MySubClass>': cannot specialize template in current scope
        int value;
    };

//    Q_DECLARE_METATYPE(MySubClass);  error : 'MySubClass': undeclared identifier
}

Q_DECLARE_METATYPE(MyNS::MyClass);

int main(int argc, char *argv[])
{
    MyNS::MyClass m(15);
    QVariant v = QVariant::fromValue(m);
    qDebug() << v.canConvert<MyNS::MyClass>();
    qDebug() << v.value<MyNS::MyClass>().getValue();
}

Consider MyClass works well without subcalss, but my problem with subclass. I want to use MySubClass with QVariant in my code, but MySubClass is private.


Solution

  • For the use of QMetaType for your MySubClass, it needs to be publically accessible.

    Think about why you want to insert MySubClass into Qt's meta type system?

    If you want to be able to send MySubClass via signal/slot, or (de)serialize / stream it, that would make MySubClass be of public interest. The docs tell you so:

    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.
    

    If you just want to store MySubClass instances in QVariant, you can write your own conversion methods

    QVariant toVariant() const
    

    and

    (static) MySubClass fromVariant(QVariant const &v)
    

    To be type-safe you could create some public dummy type and register it with QMetaType so you'd get a unique ID, but basically you'd convert your MySubClass to a QVariantMap and back, provided that all contained data is storable in a QVariant.