Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Using template on a QWidget constructor



  • Hello everyone. I have created a QWidget class that should take a template pointer as an input. Doing so with a method works fine, however when I try to use it on the QWidget's constructor I get an error. Here's the code:

    #ifndef GADGET_H
    #define GADGET_H
    
    #include <QObject>
    
    
    struct P2D {
        Q_GADGET
        Q_PROPERTY(P2D p2d READ getP2D )
        Q_PROPERTY(float m_x READ getX WRITE setX)
        Q_PROPERTY(float m_y READ getY WRITE setY)
    
        P2D getP2D() {return *this;}
        float getX() {return this->m_x;}
        void setX(float x) {this->m_x = x;}
        float getY() {return this->m_y;}
        void setY(float y) {this->m_y = y;}
    
    public:
        float m_x;
        float m_y;
    }; Q_DECLARE_METATYPE(P2D)
    
    #endif
    

    Here's my main:

    #include "mainwindow.h"
    #include "gadget.h"
    
    #include <QApplication>
    #include <QDebug>
    #include <QMetaObject>
    #include <QMetaProperty>
    #include <QVariant>
    #include <QWidget>
    #include "objectintrospector.h"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        qRegisterMetaType<P2D>();
        P2D point;
        point.m_x = 10;
        point.m_y = 25;
    
        objectIntrospector *oi = new objectIntrospector(nullptr, "P2D", &point);
        oi->show();
        return a.exec();
    }
    

    And here is my QWidget:

    #ifndef OBJECTINTROSPECTOR_H
    #define OBJECTINTROSPECTOR_H
    
    #include <QWidget>
    
    class objectIntrospector : public QWidget
    {
        Q_OBJECT
    public:
        template <class T>objectIntrospector(QWidget *parent = nullptr, const char* typeName =  nullptr, T *ptr = nullptr);
        ~objectIntrospector();
    
    private:
        Ui::objectIntrospector *ui;
    };
    

    I get the following error:

    undefined reference to `objectIntrospector::objectIntrospector<P2D>(QWidget*, char const*, P2D*)'
    

    Is there a way to use a template on QWidget's constructor?

    Thanks for your time.


  • Lifetime Qt Champion

    @raphasauer said in Using template on a QWidget constructor:

    Is there a way to use a template on QWidget's constructor?

    You would also get this function when you don't derive from QWidget since you nowhere define and instantiate objectIntrospector<P2D >::objectIntrospector(QWidget* const char* T*).



  • @Christian-Ehrlicher is it a problem with instantiating? Because I can get functions like this to run just fine:

    template <class T>
    const QMetaObject* metaConverter(T* ptr)
    {
        const QMetaObject *mo = &ptr->staticMetaObject;
        return mo;
    }
    

    I was thinking that I could use the template on the constructor in a similar way.


  • Lifetime Qt Champion

    @raphasauer said in Using template on a QWidget constructor:

    I was thinking that I could use the template on the constructor in a similar way.

    You can but you do not in your example.



  • @Christian-Ehrlicher What would be the proper way to do it? I am resorting to templates because the constructor should receive a generic pointer to an object that contains a Q_GADGET. Or is there a better approach?


  • Lifetime Qt Champion

    As for any other template - make the implementation visible to the compiler when it instantiates the template as you did in your second example.



  • @Christian-Ehrlicher by implementation you are referring to objectIntrospector::objectIntrospector<P2D>(QWidget*, char const*, P2D*) ?
    I wasn't using an explicit implementation because "P2D" could be any element that has a Q_GADGET on it.


  • Lifetime Qt Champion

    I never said you should do this. I said the compiler must see the code when it instantiates the template. Basic c++ stuff.



  • @Christian-Ehrlicher thanks! My C++ is a bit rusty, but I understand what you are saying now.

    Basically I should declare the logic with the header, this way the compiler sees that there is an implementation.


  • Lifetime Qt Champion

    Correct.