100

Let's say I have this signal:

signals:
    void progressNotification(int progress);

I only recently learned about the emit keyword in Qt. Until now, I used to execute signals by just calling them like a regular function. So instead of:

emit progressNotification(1000 * seconds);

I would write:

progressNotification(1000 * seconds);

Calling them like that seemed to work, and all the connected slots would execute, so does using the emit keyword cause a different behaviour, or is it just syntactic sugar?

sashoalm
  • 63,456
  • 96
  • 348
  • 677
  • 17
    +1 Never knew `emit` is not needed. It's strange though, that you learned about `emit` long after calling signals directly, as the signal-slot system is one of the first things to be learned about Qt. – Christian Rau Apr 15 '12 at 10:23

3 Answers3

93

emit is just syntactic sugar. If you look at the pre-processed output of function that emits a signal, you'll see emit is just gone.

The "magic" happens in the generated code for the signal emitting function, which you can look at by inspecting the C++ code generated by moc.

For example a foo signal with no parameters generates this member function:

void W::foo()
{
    QMetaObject::activate(this, &staticMetaObject, 0, 0);
}

And the code emit foo(); is pre-processed to simply foo();

emit is defined in Qt/qobjectdefs.h (in the open-source flavor of the source anyway), like this:

#ifndef QT_NO_EMIT
# define emit
#endif

(The define guard is to allow you to use Qt with other frameworks that have colliding names via the no_keywords QMake config option.)

Mat
  • 188,820
  • 38
  • 367
  • 383
  • 14
    Do you know if there was ever an implementation (or a planned implementation) of an `emit` that actually did more than nothing? I find that having the 'syntactic sugar' in this case just confuses the novice (or at least me when I was a novice Qt user) - it appears that something magical or important is happening with the `emit` pseudo-keyword, when it does nothing at all - all the magic happens in a regular old function that `moc` creates (`moc` is the magic for Qt signals and slots). `emit` is needless decoration that does nothing but seem important. – Michael Burr Apr 15 '12 at 08:35
  • 14
    Emit is _not_ "just decoration". `emit` tells the person reading the call that magic is about to happen (i.e. this is going to trigger code in objects this class potentially never heard of, and these calls might be synchronous or asynchronous), which is essentially totally lost if you omit the keyword. Use it. It's auto-documenting. "Novices" should read docs & tutorials, and `emit` is always there (in the official docs anyway). Discovering that you can just call the function should happen after you've "seen the light" - you're not a novice any more at that point. – Mat Apr 15 '12 at 08:43
  • 19
    Hmm, I'm not sure I agree with you on how valuable the `emit` 'keyword' is. I think I would have preferred that a naming convention be used if there's a need to make clear that a function call is a signal. – Michael Burr Apr 15 '12 at 08:58
  • 2
    Well, I radically disagree with that :) Forcing a naming convention is something you can do yourself in your projects/workplace, Qt doesn't prevent that. Qt doesn't force you to use the "keyword", and even allows you to turn it off if it clashes with other parts of your code. In my opinion, the keyword approach is better - the compiler can't help you enforce naming policies, but it will catch a misspelled `emit`. – Mat Apr 15 '12 at 09:03
  • 15
    To be clear - I wasn't advocating that a naming convention be used - just that *if* the reason for an `emit` psuedo-keyword-comment was to make clear that a signal is being invoked, then a naming convention could do the same, with no mystery and with similar benefits. The naming convention couldn't be enforced by Qt (actually, `moc` could enforce it - but I'm not advocating that either), but Qt can't enforce the use of `emit` either. And while you can 'turn off' `emit` if there's a name clash, that doesn't help much if you have a bunch of source files that are using it (needlessly, to boot). – Michael Burr Apr 15 '12 at 09:20
  • Such convention is quite stupid, technically. Since the C++ preprocessor does not allow customization on juxtaposition of preprocession tokens, this identifier can't be handled by C++ without some extra preprocessor (e.g. `moc`) portably besides the ignorance. It should have been `emit(...)` if readability is needed, albeit it is still susceptible by losing the uniform notion about "callable objects" in C++. – FrankHB Dec 19 '20 at 04:13
3

After 18 months ... I started with comments under @Mat's answer, and was running out of room quickly. Thus the answer.

IMO emit is neither syntactic sugar nor a simple keyword in the sense that

  1. It generates code (as explained by @Mat above),
  2. It helps the connect mechanism recognize that indeed it is a signal, and
  3. It makes your signal part of a "bigger" system, where signals and responses (slots) can be executed synchronously or asynchronously, or queued, depending on where and how the signal got emitted. This is an extremely useful feature of the signal/slot system.

The entire signal/slot system is a different idiom than a simple function call. I believe it stems from the observer pattern. There is also a major difference between a signal and a slot: a signal does not have to be implemented, whereas a slot must be!

You are walking down the street and see a house on fire (a signal). You dial 911 (connect the fire signal with the 911 response slot). The signal was only emitted, whereas the slot was implemented by the fire department. May be imprecise, but you get the idea. Let's look at the example of OP.

Some backend object knows how much progress has been made. So it could simply emit progressNotification(...) signal. It is up to the class that displays the actual progress bar, to pick up this signal and execute on it. But how does the view connect to this signal? Welcome to Qt's signal/slot system. One can now conceive of a manager class (typically a widget of sorts), which consists of a view object and a data computation object (both being QObjects), may perform connect (m_myDataEngine, &DataEngine::progressNotification, m_myViewObj, &SimpleView::displayProgress).

Let's not get into the design aspects of the manager class, but suffice it to say that this is where signal/slot system shines. I can focus on designing a very clean architecture for my application. Not always, but often times, I find that I merely emit signals but implement slots.

If it is possible to use/call a signal method without ever emitting it, then it necessarily implies that you never needed that function as a signal in the first place.

NameRakes
  • 427
  • 4
  • 12
  • 8
    No, `emit` is indeed only a empty macro and purely optional. Not so are the keywords `signal` and `slot` which are processed by the moc. `signal` is used to provide the implementation of the function, `slot` is used to create the meta object entry so it is found with the `SLOT(MySlot())` macro or in QML. `emit` is syntactic suggar. Nothing will ever complain if you write `emit i++;` (but maybe your co-workers) and you still can't connect to `i++`. – derM Apr 03 '18 at 08:39
  • It is true that the pattern is different to C++ function calls, but there needs no difference to function invocation in general. Even the C++ abstraction machine allows asynchronous calls under the hood by the as-if rules, just no compilers generate the code implicitly in practice. (However, explicit policies are proposed, c.f. C++ executors.) Qt signals do nothing more, essentially. It is even worse that the scheduling mechanism is totally implied by the framework (rather than the compiler), but not extensible by programmers. – FrankHB Dec 19 '20 at 04:29
  • There is practically no chance to tune the implementation because both the programmer and the compiler know nothing about the implementation details hidden in the framework. If I really need to call asynchronously, I'd implement the calls in a saner way (with some homebrew metadata management), rendering the signals and slots no more useful than multicasting events or callable object containers (like boost.signal[2]). There is no room for a special `emit` anywhere, then. – FrankHB Dec 19 '20 at 04:31
-4

The second option would imply that you always know what the function name and the function parameters are and that the object which are you sending it to is known by that particular function. Those two cases are not always true, so that are the two main things why slots and signals have been made. "under-the-hood" the signal and slot mechanism is just a table with pointers to every function that is connected.

Also, look at this pdf which explains very clearly the nature of the signals and slots mechanism: http://www.elpauer.org/stuff/a_deeper_look_at_signals_and_slots.pdf

Evert
  • 524
  • 4
  • 13
  • Both ways require knowing the signal name and its parameters - you're emitting it, how could you emit something you don't know? Both have the same semantics too, they are identical. – Mat Apr 15 '12 at 08:25
  • 1
    Maybe you're messing up a signal call with a direct slot call? But I have to admit that I also wondered about the question title at first, since I never knew `emit` was just a no-op. But even in this case reading the question body should have cleared things up, so -1. – Christian Rau Apr 15 '12 at 10:22