0

there are two types of signal/slot connection semantics in Qt:

connect(sender, SIGNAL(mySignal()), receiver, SLOT(mySlot())); // 1
connect(sender, &MySender::mySignal, receiver, &MyReceiver::mySlot); // 2

2 is usually preferable and supports connections to lambda functions. When object type is not defined at compile-time, 1 is the only option. Working with QtQuick objects from c++ is exactly this case.

Is there a way to connect signal by name to lambda function? Something like

connect(sender, SIGNAL(mySignal()), receiver, [] { ... });
Andrei R.
  • 2,374
  • 1
  • 13
  • 27
  • right now I use a workaround: define a proxy signal in available object; connect qml signal to proxy signal with `1` and connect proxy signal to lambda with `2` – Andrei R. Jul 21 '17 at 04:49
  • I don't think that is possible, but why exactly do you need it this way? I don't see why you can't use a normal slot instead of the lambda if you need a workaround? – xander Jul 21 '17 at 06:01
  • @xander, lambda capture is much more convenient and readable than adding several class fields to be used in a slot. – Andrei R. Jul 21 '17 at 06:05
  • @Andrei R yeah, but capture hides behavior, sometimes causes unexpected behavior if it is not thought through in according to architecture. Capture might be source of nasty and untraceable UB or bugs. And, if you asked question about this, you didn't studied how Qt classes are designed, that would prove to cause problems. Lambda functions are meant as a crutch that allows avoid changing or overcomplicating architecture, not as a architecture building tool. – Swift - Friday Pie Jul 21 '17 at 06:21
  • 2
    maybe this helps: https://stackoverflow.com/questions/15624800/connect-qml-signal-to-c11-lambda-slot-qt-5?rq=1 – xander Jul 21 '17 at 06:29
  • @xander QML signals are quite different fish.. that's essentially calling a slot from a java script. Oh, and native (C++) part also may support queued calling of slot, if caller and callable are in different QThreads (it might be put into event queue instead of being called directly). I have no idea how lambda even MAY be supported by connect() in that case. You'd run into time of life issues. – Swift - Friday Pie Jul 21 '17 at 06:30
  • @xander, I was looking for elegant solution. Link you provided has nice workaround – Andrei R. Jul 21 '17 at 06:59
  • @Swift, behavior of lambda capture is well-defined, just mind lifetime of objects. – Andrei R. Jul 21 '17 at 07:02
  • yes, but certain Qt objects cannot be copied (semantically), other do not trace their refences or do not own data they manipulate – Swift - Friday Pie Jul 21 '17 at 12:35

1 Answers1

-1

No that's not possible with way how signal-slot is implemented in Qt. Connect can be called from anywhere where two objects and signal and slot are available. Meta object (defined in file generated by moc) must be able to get pointer to the function declared as slot, to add pointer to table of events. Actually even capturing Qt objects in lambda function may be detrimental, unless you capture them by reference. Qt not designed around C++11 ideology, more of, the containers of Qt library have implementation that is essentially an UB (undefined behaviour): comments like "this works most of time" are hinting on that.

You may try to use QObject::connect function to connect to lambda:

QObject::connect(callerObject, &callerObject::signal, [ ] {...})

But beware which version of Qt and in which scope you're using it, older Qt 5.x versions leaked on that: see Qt leaks on connecting to lambda. And that only can connect to a lambda that captures global scope objects, or scope that is assured to live longer than callerObject.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42