[Development] [Interest] Qt 5 connect to static function: Suggestion for new overload.

Olivier Goffart olivier at woboq.com
Sat May 4 10:45:14 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 Development mailing list