c++ qt templates signals-slots

c++ - QT: Clase templada Q_OBJECT



templates signals-slots (4)

¿Es posible tener una clase de plantilla, que hereda de QObject (y tiene macro Q_OBJECT en su declaración)?

Me gustaría crear algo así como un adaptador para ranuras, lo que haría algo, pero la ranura puede tomar un número arbitrario de argumentos (el número de argumentos depende del argumento de la plantilla).

Solo traté de hacerlo, y obtuve errores de enlazador. Supongo que gmake o moc no recibirán una llamada en esta clase de plantilla. ¿Hay alguna forma de hacer esto? ¿Tal vez al crear instancias explícitas de plantillas?


No es posible mezclar la plantilla y Q_OBJECT, pero si tiene un subconjunto de tipos, puede enumerar las ranuras y señales como esta:

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 T> class Abstraction : public SignalsSlots {...


Teniendo en cuenta algunas restricciones: puedes. Primero, familiarícese (si no es así) https://doc.qt.io/archives/qq/qq16-dynamicqobject.html . - ayudará a imponerlo. Y sobre las restricciones: puede tener una plantilla clase QObject, es decir, clase de plantilla derivada de QObject, pero:

  1. No le diga al moc que lo compile.
  2. Q_OBJECT es solo una macro y debes reemplazarla por contenido real, que es una interfaz virtual y algo más :)
  3. Implemente la activación de QMetaObject (interfaz virtual mencionada anteriormente y tenga cuidado con los datos de información del objeto, que también proviene de Q_OBJECT) y alguna otra funcionalidad, y tendrá la plantilla QObject (incluso con ranuras de plantilla)
  4. Pero como logré atrapar el retroceso, no es posible usar simplemente esta clase como base para otra clase.
  5. Hay algunos otros inconvenientes, pero creo que la investigación detallada los mostrará.

Espero que esto sea útil.


Todavía no es posible mezclar plantillas y Q_OBJECT, pero dependiendo de su caso de uso, puede usar la nueva sintaxis ''connect''. Esto permite al menos el uso de ranuras de plantilla.

Enfoque clásico no laboral:

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

Uso deseado pero no compilable:

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

Error: clases de plantilla no admitidas por Q_OBJECT (para MySlotClass).

Solución usando new la sintaxis ''connect'':

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

Ahora podemos instanciar objetos ''MySlotClass'' deseados y conectarlos a emisores de señal apropiados.

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

Conclusión: es posible usar slots de plantilla. La emisión de señales de plantilla no funciona, ya que se producirá un error de compilación debido a que falta Q_OBJECT.


Traté de crear instancias explícitas de plantillas, y obtuve esto:

core_qta_qt_publisheradapter.hpp: 96: Error: clases de plantilla no admitidas por Q_OBJECT

Supongo que eso contesta a mi pregunta.

EDITAR

En realidad, si coloco toda la definición de clase de plantilla en el encabezado, entonces el preprocesador qt no lo procesa, y luego recibo errores del enlazador. Por lo tanto, debe ser posible hacerlo, si agrego métodos faltantes.

EDIT # 2

Esta biblioteca hizo exactamente lo que yo quería: usar un mecanismo personalizado de señal / ranura, donde la ranura no tiene definida la firma.