QT : Templated Q_OBJECT class
Solution 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 T>
class Abstraction : public SignalsSlots
{...
Solution 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:
- Do not tell the moc to compile it.
- Q_OBJECT is just a macro and you have to replace it by it real content which is virtual interface and something else :)
- 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)
- 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.
- There are some other drawbacks - but I think the detail investigation will show you them.
Hope this will helpful.
Solution 3
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 T>
class MySlotClass : public QObject {
Q_OBJECT
public slots:
void slot_setValue(const T& newValue){ /* Do sth. */}
};
Desired usage but not compilable:
MySignalClass a;
MySlotClass<int> 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 T>
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<int> b;
connect(&a, &MySignalClass::signal_valueChanged,
&b, &MySlotClass<int>::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.
Solution 4
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.

BЈовић
Drink milk, it is healthier then oil! If you want to see how I see the Presenter first's implementation in Qt, take a look into my pet project.
Updated on July 15, 2022Comments
-
BЈовић 10 months
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?
-
g24l over 7 yearsSimple separation of notions...!
-
Greg Kramida over 7 yearsGood work-around. Moreover, if the signal definitions need to access the template parameter, they can be simply declared as virtual abstract in the SignalsSlots equivalent and defined in the class template.
-
bweber about 7 yearsCan you explain that? The
SignalsSlots
class is not a template class, so how am I able to use a Template parameter in the signature of the signal? For example if I wanted to do something like this:void someSignal(T value)
. -
Jonas W about 7 yearsYou can use the subset only with the template, that is in the example; int, float, double, bool, SwitchState. Add all types you need support for. I think that version 5 of QT can mix template and Q_OBJECT, but I have not tried it.
-
Will Bickford over 6 years@JonasW Qt 5.6 still does not support templates with the Q_OBJECT macro.
-
Lisa about 3 yearsWithout deep investigation into this, it really feels like a maintenance nightmare to go down this path and attempt to reimplement Q_OBJECT macro just so I can use signals and slots in a templated class. Do you have an example of how you've done this successfully?
-
Lisa about 3 yearsYou mean emitting a signal is still not working, right? (thanks for this)
-
TSG about 3 yearsI would appreciate a few more lines in the Abstraction class example. Do you create regular methods with the same name as the slots you are overriding? The last 10% is confusin
-
TSG about 3 yearsFor anyone else interested, you have to emit a signal within Abstraction using "emit SingalsSlots::readAsynkPolledChange(X)" - yes you must reference the base signals and slots class.
-
Dean Johnson over 2 yearsThere is an example within the Qt sources that uses a very similar pattern for a templated QObject: QFutureWatcher<T>. It has a non-templated base class of QFutureWatcherBase that defines the signals/slots and has the Q_OBJECT macro. source link. Note that you still can't use the template type in signals/slots.
-
smsware about 2 years@Anonymous I was really happy about this but I'm getting "Error: Class declaration lacks Q_OBJECT macro" - did it change since 2017?
-
dqbydt over 1 yearBut how do you define slot overrides in the template class (e.g. for one of the
writeAsync
slots above)? Still getError: Class declaration lacks Q_OBJECT macro.
if I define one there.