QT : Templated Q_OBJECT class

匿名 (未验证) 提交于 2019-12-03 08:30:34

问题:

Is it possible to have a template class, which inherit from QObject (and has Q_OBJECT macro in it's declaration)?

I would like to create something like adapter for slots, which would do something, but the slot can take arbitrary number of arguments (number of arguments depends on the template argument).

I just tried doing it, and got linker errors. I guess gmake or moc is not getting called on this template class. Is there a way to do this? Maybe by explicitly instantiating templates?

回答1:

It is not possible to mix template and Q_OBJECT but if you have a subset of types you can list the slots and signals like this:

    class SignalsSlots : public QObject     {         Q_OBJECT      public:         explicit SignalsSlots(QObject *parent = 0) :             QObject(parent) {}      public slots:         virtual void writeAsync(int value) {}         virtual void writeAsync(float value) {}         virtual void writeAsync(double value) {}         virtual void writeAsync(bool state) {}         virtual void writeAsync(svga::SSlideSwitch::SwitchState state) {}         signals:         void readAsynkPolledChanged(int value);         void readAsynkPolledChanged(float value);         void readAsynkPolledChanged(double value);         void readAsynkPolledChanged(bool state);         void readAsynkPolledChanged(svga::SSlideSwitch::SwitchState state);     }; ... template  class Abstraction : public SignalsSlots {... 


回答2:

Taking into account some restrictions: you can. First please became familiar (if already not) https://doc.qt.io/archives/qq/qq16-dynamicqobject.html. - it will help to imlement it. And about restrictions: you can have a template QObject class i.e. template class derived from QObject, but:

  1. Do not tell the moc to compile it.
  2. Q_OBJECT is just a macro and you have to replace it by it real content which is virtual interface and something else :)
  3. Implement QMetaObject activation (above mentioned virtual interface and be caution with object info data, which is also come from Q_OBJECT) and some else functionality and you will have template QObject (even with template slots)
  4. But as I managed to catch the one draw back - it is not possible to simply use this class as a base for another class.
  5. There are some other drawbacks - but I think the detail investigation will show you them.

Hope this will helpful.



回答3:

I tried explicitly instantiating templates, and got this :

core_qta_qt_publisheradapter.hpp:96: Error: Template classes not supported by Q_OBJECT

I guess that answers my question.

EDIT

Actually, if I place whole template class definition in the header, then the qt preprocessor doesn't process it, and then I get linker errors. Therefore it must be possible to do it, if I add missing methods.

EDIT #2

This library did exactly what I wanted - to use a custom signal/slot mechanism, where the slot has not-defined signature.



回答4:

It is still not possible to mix templates and Q_OBJECT but depending on your use case you may use the new 'connect'-syntax. This allows at least the usage of template-slots.

Classical non-working approach:

class MySignalClass : public QObject {   Q_OBJECT public:  signals:   void signal_valueChanged(int newValue); };        template class MySlotClass : public QObject {   Q_OBJECT public slots:   void slot_setValue(const T& newValue){ /* Do sth. */} }; 

Desired usage but not compilable:

MySignalClass a; MySlotClass b;  QObject::connect(&a, SIGNAL(signal_valueChanged(int)),                  &b, SLOT(slot_setValue(int))); 

Error: Template classes not supported by Q_OBJECT (For MySlotClass).

Solution using new the 'connect'-syntax:

// Nothing changed here class MySignalClass : public QObject {   Q_OBJECT public:  signals:   void signal_valueChanged(int newValue); };   // Removed Q_OBJECT and slots-keyword template class MySlotClass : public QObject {  // Inheritance is still required public:   void slot_setValue(const T& newValue){ /* Do sth. */} }; 

Now we can instantiate desired 'MySlotClass'-objects and connect them to appropriate signal emitters.

  MySignalClass a;   MySlotClass b;    connect(&a, &MySignalClass::signal_valueChanged,           &b, &MySlotClass::slot_setValue); 

Conclusion: Using template-slots is possible. Emitting template signals is not working since a compiler error will occur due to missing Q_OBJECT.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!