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

Wrapper with signals for primitive types



  • Hi,
    I'd like to create a wrapper for primitive types, that would emit a signal when the value is changed and have a slot to change the value.The obvious way would be to use a template class:

    template<typename Type>
    class QValueWrapper : public QObject
    {
        Q_OBJECT
    
    signals:
        void valueChanged(Type newValue);
    
    public:
        void setValue(const Type &newValue)
        {
            if(value_ != newValue)
                emit valueChanged(newValue);
            value_ = newValue;
        }
    
    private: 
        Type value_;
    };
    

    But Qt signals does not support template classes. So how would you do it? I'd like to avoid creating a wrapper for each value type, if possible
    Thanks



  • But Qt signals does not support template classes.

    this is not strictly correct. It's MOC that can't cope with templates.

    You have 3 alternatives that I can think of:

    #include <wobjectdefs.h>
    #include <wobjectimpl.h>
    template<typename Type>
    class QValueWrapper : public QObject
    {
        W_OBJECT(QValueWrapper )
    public:
        QValueWrapper(QObject* parent = nullptr) :QObject(parent){};
        QValueWrapper(const Type & val,QObject* parent = nullptr) : QObject(parent), value_(val){}
        void valueChanged(Type newValue);
        W_SIGNAL(valueChanged, newValue)
        const Type & value() const {return value_;}
        void setValue(const Type &newValue)
        {
            if(value_ != newValue)
                emit valueChanged(newValue);
            value_ = newValue;
        }
        W_SLOT(setValue)
    private: 
        Type value_;
    };
    W_OBJECT_IMPL(QValueWrapper <Type>, template <typename Type>)
    
    • move the signal to a template-less qobject
    class QValueWrapperHelper : public QObject
    {
        Q_OBJECT
    public:
    QValueWrapperHelper(QObject* parent = nullptr) :QObject(parent){};
    signals:
        void valueChanged();
    };
    
    template<typename Type>
    class QValueWrapper : public QValueWrapperHelper 
    {
    public:
    QValueWrapper(QObject* parent = nullptr) :QValueWrapperHelper(parent){};
    QValueWrapper(const Type & val,QObject* parent = nullptr) :QValueWrapperHelper(parent), value_(val){};
    const Type & value() const {return value_;}
        void setValue(const Type &newValue)
        {
            if(value_ != newValue)
                emit valueChanged();
            value_ = newValue;
        }
    private: 
        Type value_;
    };
    


  • The first thing that comes to my mind is to use a QVariant to store the value you want. QVariant supports all primitive types.



  • But Qt signals does not support template classes.

    this is not strictly correct. It's MOC that can't cope with templates.

    You have 3 alternatives that I can think of:

    #include <wobjectdefs.h>
    #include <wobjectimpl.h>
    template<typename Type>
    class QValueWrapper : public QObject
    {
        W_OBJECT(QValueWrapper )
    public:
        QValueWrapper(QObject* parent = nullptr) :QObject(parent){};
        QValueWrapper(const Type & val,QObject* parent = nullptr) : QObject(parent), value_(val){}
        void valueChanged(Type newValue);
        W_SIGNAL(valueChanged, newValue)
        const Type & value() const {return value_;}
        void setValue(const Type &newValue)
        {
            if(value_ != newValue)
                emit valueChanged(newValue);
            value_ = newValue;
        }
        W_SLOT(setValue)
    private: 
        Type value_;
    };
    W_OBJECT_IMPL(QValueWrapper <Type>, template <typename Type>)
    
    • move the signal to a template-less qobject
    class QValueWrapperHelper : public QObject
    {
        Q_OBJECT
    public:
    QValueWrapperHelper(QObject* parent = nullptr) :QObject(parent){};
    signals:
        void valueChanged();
    };
    
    template<typename Type>
    class QValueWrapper : public QValueWrapperHelper 
    {
    public:
    QValueWrapper(QObject* parent = nullptr) :QValueWrapperHelper(parent){};
    QValueWrapper(const Type & val,QObject* parent = nullptr) :QValueWrapperHelper(parent), value_(val){};
    const Type & value() const {return value_;}
        void setValue(const Type &newValue)
        {
            if(value_ != newValue)
                emit valueChanged();
            value_ = newValue;
        }
    private: 
        Type value_;
    };
    


  • Thanks to both of you. I think I will use your third solution, @VRonin
    I'll mark this topic as solved as soon as I try it


Log in to reply