To connect Qt5 calls to a signal in my classes I usually use a lambda which calls the Qt functions. All calls to Qt must be in the GUI thread so I use the Qt::QueuedConnection to invoke a function. What I discovered is strange to me. This is what I normally do:
template<class TObj, class TFunc>
auto injectToQt(TObj obj, TFunc fn) {
return [=](auto &&... params){
QMetaObject::invokeMethod(obj, [=](){
fn(params...);
}, Qt::QueuedConnection);
};
}
This returns a functor which I can connect to my signal which must return void. It is clear to me why this is working because the return type is something callable with the () operator. A call to this will directly push something inside the GUI loop.
I came up with the idea to wrap that in a class which defines the () operator too but that operator does push work to the GUI thread instead it returns a functor which is doing that. The signals2 library seems to accept that and it is working like the injectToQt function. How is that even possible? I tried to dig into the signals2 library but is is a bit hard to read and I didn't spend much time in that. Do you guy know why this is accepted by the library?
template<class TObj, class TFunc>
class QtInjector {
public:
QtInjector(TObj obj, TFunc fn) : obj(obj), fn(fn) {
}
template<class ... TParams>
auto operator()(TParams ... params) {
return [=](auto &&... params){
QMetaObject::invokeMethod(obj, [=](){
fn(params...);
}, Qt::QueuedConnection);
};
}
TFunc fn;
TObj obj;
};