[Interest] [Development] Qt 5 connect to static function: Suggestion for new overload.
Olivier Goffart
olivier at woboq.com
Sat May 4 10:46:12 CEST 2013
> On sexta-feira, 3 de maio de 2013 11.50.14, Björn Piltz wrote:
> > Would it be possible to add an overload of QObject::connect() like this:
> >
> > static QMetaObject::Connection connect(const QObject *sender,
> > PointerToMemberFunction signal, const QObject *receiver, Functor
> > functor);
> >
> > in addition to
> >
> > static QMetaObject::Connection connect(const QObject *sender,
> > PointerToMemberFunction signal, Functor functor);
Hi,
I would say this is an instance of the XY problem:
http://meta.stackoverflow.com/questions/66377/what-is-the-xy-problem
Why would you want to have a 'receiver' when there is no really a receiver?
Another question i often see is why don't we accept non-QObject receiver.
Appart from being the object which owns the member function, the QObject
receiver also get used for those features:
- The connection is automatically disconnected when the receiver is
destroyed.
- The thread affinity of the object is used to possibly perform a queued
connection in the thread of the receiver
- The receiver's sender() and senderSignalIndex() are updated.
Those features are totally valid use case you may want for lambda functions,
and I agree we should support that. I had that in mind with several ways to
solve it, but it was not implemented in Qt 5.0 because i left that for later.
Here are some way to solve it:
1) add new overloads of QObject::connect with 5 arguments that takes functor
as parametters with a receiver.
Code would look like this:
connect(obj1, &Foo::theSignal, obj2, [&]() { obj3->doSomething(obj2); });
This is easy to do with C++11 variadic template, a bit more difficult if you
only have decltype and C++11 revisited SFINAE, and even more difficult if you
can't use C++11 at all.
But here the problem is semantic. With a lambda function, we dont have a
"receiver" anymore. Also, why are we limited to one receiver?
2) Since we now return a QObject::Connection, we can add API on that class.
For example:
auto c = connect(obj1, &Foo::theSignal, [&]() { obj3->doSomething(obj2); });
c.addDeleteWatcher(obj2);
c.addDeleteWatcher(obj3);
c.queueInThread(obj2.thread());
Implementation of this would be trivial.
Other syntaxes are possible:
connect(obj, ..., [&]() { ... } ).setReceiver(obj2);
The challenge is thread safety. (what if the signal is emitted in another
thread before we set the receiver?)
3) for deletion purpose, maybe having a kind of scoped pointer around
QObject::Connection
obj2->m_connections.track(connect(obj1, ..., [] {...} ));
it could also be an API in QObject itself
obj2->trackConnection(connect(obj1, ..., [] {...} ));
I'm tempted to say that the new QObject::connect overloads are not that bad
after all.
--
Olivier
Woboq - Qt services and support - http://woboq.com - http://code.woboq.org
More information about the Interest
mailing list