Happened to stumble upon this clazy check while searching on a completely 
different issue.
Seems to explain the reasoning pretty well.

https://github.com/KDE/clazy/blob/master/docs/checks/README-connect-3arg-lambda.md

-Max


On 2/15/2020 12:40 AM, Max Paperno wrote:

On 2/14/2020 11:19 PM, Tony Rietwyk wrote (in part):
I thought the whole point of the [=] in the lambda is to capture a shallow copy of the state required by the code within the lambda.

May I ask why you think that, or what you mean?  I can't find any reference to [=] capturing 
anything about a "state," though  I'm not really sure what you mean by "state."
What it _can_ capture (and to some extent how) depends on the "reaching scope" 
but that seems different to what you're saying. I'm re-reading the rather extensive docs
at cppreference.com... so it's quite possible I'm just missing what you mean.  
Other sources I've looked at don't seem to go into as much detail.

In the shorter overload, I would assume that the context is simply the current 
thread object.

What do you mean by "current thread object?"  An implicit `this`?

  Both overloads have the following warning:

No they don't... Looking at doc.qt.io for 5.14 anyway. Only the one with 
`context` has the part about the context being destroyed (emphasis mine):

"The connection will automatically disconnect if the sender **or the context** is 
destroyed."

To me this says that you specifically want the connection to be destroyed when 
the `context` object goes away, in case the sender and receiver/context
objects aren't the same for some reason. For example I connect a UI element 
which may somehow have a different lifetime than the `this` object.
If the lambda code only affects stuff in the sender object (or stuff unrelated 
to any object), then it probably doesn't matter.

Seems clear that for objects in different threads the sender and 
receiver/context wouldn't be the same, hence the connection type parameter in 
that overload.
But they could also be different regardless of threading, and the connection 
should be removed when either objects is destroyed.

Of course maybe I have it all wrong... but "seems to work for me" :)

Cheers,
-Max



On 2/14/2020 11:19 PM, Tony Rietwyk wrote:

On 15/02/2020 7:01 am, Matthew Woehlke wrote:
On 07/02/2020 19.10, Tony Rietwyk wrote:
Does it work if you don't pass 'this' as the third argument to connect?
I never use that particular overload of connect. I usually pass the
lambda as the third argument.
That scares me. The third argument is the context in which the slot
runs, i.e. the "receiver". If your lambda contains any state, not
passing a context risks the slot being called after whatever owns that
state has ceased to exist, which will likely lead to UB. (It also risks
the lambda running in the wrong thread.)

Basically, if your lambda has *any state at all*, you should *always*
pass a context. The context should be a QObject which owns that state
and whose thread can safely use the state.

The context should only be omitted if your lambda is stateless, and even
then I'd avoid doing so unless you really need to, or are making a
deliberate choice that no one should "own" the connection.

That's strange - I thought the whole point of the [=] in the lambda is to capture a 
shallow copy of the state required by the code within the lambda.  Whereas [&] 
copies references to the state variables.  Of course, whether these copies or 
references work in whatever thread when the code is actually executed is up to you 
to guarantee - via QSharedPointers or whatever.  I haven't used lambdas across 
threads - in those cases I've used the receiver/pointer-to-method overload.

The third parameter context solely determines which thread's event loop the 
lambda runs in.  In the shorter overload, I would assume that the context is 
simply the current thread object. Both overloads have the following warning:

    "The connection will automatically disconnect if the sender or the context is 
destroyed. However, you should take care that any objects used within the functor are 
still alive when the signal is emitted."

In my experience, coding in particular ways "because it scares you" often leads 
to poor results.  A C++ lambda is basically a temporary object with the copied or 
referenced state, and a call operator()(...) { /* lambda code */ }.

Regards, Tony



_______________________________________________
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


_______________________________________________
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest

Reply via email to