Disconnecting signal inside lambda function

  • Hello everyone,

    I've been using Qt for a while, and I think it really makes C++ more enjoyable as a language.
    I've been making an application which uses a web view and executes some code when the loading is finished, but needs to do so only once (I need different functions depending on which page is loading).

    I can disconnect the signal inside the called slot function with the old style signals and slots and it works fine. However, using the new and very convenient syntax with a lambda, the call to disconnect always returns false.

    @QMetaObject::Connection signal = connect(webView->page()->mainFrame(), &QWebFrame::loadFinished, [&](bool ok) {
    bool a = disconnect(signal);
    QMessageBox::information(mainWindow, "Output from Disconnect", QString("%1").arg(a));

    I know I'm technically in the connected function when calling this, however, is there any way to make this work while keeping the function inline?

    I know I could work around using the old syntax, but I'd like to learn about if it is possible, if is there something I'm doing wrong, or if this is technically impossible.


  • Just to verify this, did you try to disconnect the slot outside of the lambda (right after connect for example), if that works and returns true?

    also does did you check if it is still connected to the lambda, maybe it just returns false but the disconnect still worked?

    some other ideas:
    if you don't have any other connections you can try and disconnect everything from the object:
    this->disconnect(); // capture the this pointer

    on the other hand you save the Connection in a local variable, I have no idea what happens in the destructor of that class or if it will be called in your case (if you capture a local variable inside of the lambda the lifetime should be extended, but who knows?)

  • Moderators

    Be careful about object lifetimes when capturing values by reference in lambdas. You're capturing both - signal and "this" pointer by reference. As always with references if they go out of scope and you use them it's undefined behavior.

    I find that using "by value" captures is a lot easier and more predictable than references, at least for Qt connects. So either use the [=] capture or by name [this, signal].

  • Thanks for the replies, Xander84 and Chris Kawa.

    The disconnect works fine outside the lambda, and no it doesn't work when returning false. It didn't disconnect.
    Capturing this and using this->disconnect() does not disconnect.

    I'll switch to using [=] and only reference when needed.

    I think these might be a bit of an "edge case"... I thought it'd be fine, as the program first of all assigns the variable, but the function run to get the variable has a lambda as parameter... I'm not totally sure what happens inside the compiler at that point, what is the order of execution. Seems like there are side effects, but not totally obvious ones like "foo(a++)".

    I'll probably switch back to the old syntax for cases like these. Or modify my code so i don't need to disconnect the slot in the signal :)

Log in to reply