[Solved] Qt5 qMetaTypeConstructHelper ? (object factory)



  • Is qMetaTypeConstructHelper deprecated in Qt 5. I am trying to use

    @template <>
    void *qMetaTypeConstructHelper<MyModule>(const MyModule *)
    {
    return new MyModule();
    }

    int MyModule::s_moduleID = qRegisterMetaType<MyModule>("MyModule");
    @

    i get the following errors during compilation :

    MyModule.cpp:17: error: C2143: syntax error : missing ';' before '<'
    MyModule.cpp:17: error: C2988: unrecognizable template declaration/definition
    MyModule.cpp:17: error: C2059: syntax error : '<'

    How to get this working ?



  • From Qt 5 "qmetatype.h":http://code.woboq.org/qt5/qtbase/src/corelib/kernel/qmetatype.h.html i found that there is a definition like

    @namespace QtMetaTypePrivate {
    template <typename T, bool Accepted = true>
    struct QMetaTypeFunctionHelper {
    static void Delete(void t)
    {
    delete static_cast<T
    >(t);
    }

    static void *Create(const void *t)
    {
        if (t)
            return new T(*static_cast<const T*>(t));
        return new T();
    }
    
    static void Destruct(void *t)
    {
        Q_UNUSED(t) // Silence MSVC that warns for POD types.
        static_cast<T*>(t)->~T();
    }
    
    static void *Construct(void *where, const void *t)
    {
        if (t)
            return new (where) T(*static_cast<const T*>(t));
        return new (where) T;
    }
    

    ....
    }
    @

    But its defined in a struct which is under QtMetaTypePrivate namespace, How should i use this ?



  • You shouldn't.

    Why do you want to use it in the first place?



  • In the above example "MyModule" class is derived from QFrame, and for my application i need to use a copy constructor , but since the copy constructor is DISABLED in the private section , it always returned "error: C2248: 'QFrame::QFrame' : cannot access private member declared in class 'QFrame'

    so in order to use that in Qt 4 i tried to use

    @template <>
    void *qMetaTypeConstructHelper<MyModule>(const MyModule *)
    {
    return new MyModule();
    }

    int MyModule::s_moduleID = qRegisterMetaType<MyModule>("MyModule");@

    but somehow while porting to Qt 5 the above template is not available i need to find an alternate solution to this.



  • The copy constructor is disabled for a reason (and the template specialization for qMetaTypeConstructHelper does not work as copy constructor; it just creates a <code>new MyModule</code> using the default constructor).

    So let's go back another step - why do you need a copy constructor in the first place?
    What is the problem you are trying to solve?

    If you are out for registering a non-copyable type with the meta type system don't, as the meta type system relies on a publicly available copy constructor (which is false for any QObject subclass). If you need to create a QObject by its name use a factory.



  • [quote author="Lukas Geyer" date="1358775900"]
    If you are out for registering a non-copyable type with the meta type system don't, as the meta type system relies on a publicly available copy constructor (which is false for any QObject subclass). If you need to create a QObject by its name use a factory.[/quote]

    You got it right, I actually want to create a QObject by its name, I too agree with using the facory implementation. Now I need to put the factory in place and test.

    Thanks for the reply.



  • I did some search and got an implementation of factory pattern :

    @#include <QMap>
    #include <QString>

    template<class Base> Base* new_object(const QString&);

    template<class Base>
    class Factory
    { // singleton class, one each base class
    Factory() {}
    Factory(const Factory&);
    Factory& operator=(const Factory&);
    ~Factory() { qDeleteAll(creators); }
    friend Base* new_object<>(const QString&);
    public:
    Base* create(const QString& nm) const
    {
    return (creators.contains(nm) ? creators[nm]->create() : NULL);
    }

    class Creator 
    { 
    public:
        virtual ~Creator() {}
        virtual Base* create() const = 0;
    };
    
    static Factory& instance() 
    {
        static Factory p_instance;
        return p_instance;
    }
    
    void unregisterCreator(const QString& nm) 
    {
        if (creators.contains(nm)) 
        {
            delete creators[nm];
            creators.remove(nm);
        }
    }
    void registerCreator(const QString& nm, const Creator* c) 
    {
        unregisterCreator(nm);
        creators.insert(nm, c);
    }
    

    private:
    QMap<QString, const Creator*> creators;
    };

    template<class Base> Base* new_object(const QString& nm)
    {
    return Factory<Base>::instance().create(nm);
    }

    template<class Derived, class Base> class Register
    {
    typedef Derived* (*CreateFn) ();

    class Creator : public Factory&lt;Base&gt;::Creator 
    { 
    public:
        Creator(CreateFn fn) : createFn(fn) {}
        virtual Derived* create() const 
        {
            return (createFn ? createFn() : new Derived(NULL));
        }
        CreateFn createFn;
    };
    

    public:
    Register(const QString& nm, CreateFn fn = NULL)
    {
    Factory<Base>::instance().registerCreator(nm, new Creator(fn));
    }
    };@

    To create an instance we can use

    @Factory<QObject>::instance().create("RegisterMe")@

    or

    @QObject *o = new_object<QObject>("RegisterMe");@

    See "Simple-yet-powerful-object-factory":http://www.qtcentre.org/threads/8714-Simple-yet-powerful-object-factory

    There is another implementation provided by you at "Elegant factory design":http://qt-project.org/forums/viewthread/21540 discussion.


Log in to reply
 

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