Is there a way to disconnect Qt
connections that are made to lambda functions without storing connection objects?
I know it's possible to do if I store the QMetaObject::Connection
returned from the connect function, but I don't really want to do that because there would be a ton of them. I mainly connect to lambda functions to avoid creating a bunch of one-off methods and objects, and it seems like if I need to do all that bookkeeping that SLOTs
would be more preferable.
Assuming a connection:
Then you can easily disconnect by:
This would disconnect all of
this's
slots forSender::mySignal
; however, it is quite common to have only one such slot, so the end result is the disconnection is performed simply and with no side effect.This is the only way as of writing this:
See the documentation for reference about the disconnect method.
In the end of the day, you will still do the book keeping with slots, too, only that lambda seems to be more localized if you really need it localized, so it is up to your personal preference, I assume.
Here are two approaches to hide the bookkeeping issues.
First, we maintain a
std::vector
which, on destruction, disconnects us from the source:Then we connect as follows:
when the vector is destroyed, the connection objects are also destroyed.
This is similar to how other signal/slot systems are handled, where the listener keeps track of a token, then returns it. But here, I keep the disconnection object in an opaque type that cleans up the connection on destruction.
Note that copying that vector will extend the lifetime of the connection. If the message is going to a particular instance of a class, store a
connections
instance in the class, and you won't get messages after the instance is destroyed.A second approach, based off what @lpapp found, is if you have a lambda that you want to call only once in response to a signal, then disconnect:
here we
one_shot_connect( bob, &Bob::mySignal, [](QString str) { std::cout << "Hello\n" } );
, and the next time the signal fires we get the message, and then the connection is disconnected.I disconnect before processing your lambda, just in case the lambda causes the signal to fire or something.
You can use a dummy object:
When the obj is destroyed, the connection is disconnected because you passed the obj on the connect.