New QObject::connect syntax isn’t as type-safe as I thought

    •     ,

Qt 5 introduced a new syntax for connect; instead of this:

connect(
    senderObject, SIGNAL(signalName(type1, type2)),
    receiverObject, SLOT(slotName(type1, type2)));

one can now write this:

connect(
    senderObject, &Sender::signalName,
    receiverObject, &Receiver::slotName);

It has both pros and cons, but for me, the main advantage is that everything is checked at the compile time. With the old syntax, I could make a typo in a signal’s name, and it would compile just fine. Not so with the new syntax.

By extension, I also thought that the new syntax is more type-safe: since the types of signal/slot arguments are checked at the compile time now, I would find out immediately if I were to use a slot with an incorrect arguments, right?

Not quite. Recently, I was showing the new syntax to a colleague, and we ended up with the following code:

// this.h
private slots:
    void test(int);

// this.cpp
connect(
    ui->pushButton, &QPushButton::clicked,
    this, &This::test);

clicked has a bool argument, while our test expects an int — clearly this won’t compile! Yet it did.

Confused, I suggested that connect might be casting function pointers to void*, making them pass type-checking even though they don’t match. The reality turned out to be much more mundane: this is just your ordinary C++ with its implicit type conversion. The docs try to paint that as an advantage of the new syntax, but I’m not entirely convinced. It does make signals and slots blend better with C++; I’m just skeptical that blending with that particular side of C++ is a good idea :)

Luckily I’m not the only skeptic out there. Qt 5.8 introduced a QT_NO_NARROWING_CONVERSIONS_IN_CONNECT macro that disables some of the dumbest conversions, like int to bool and int to double. Better than nothing, I guess.

Your thoughts are welcome by email
(here’s why my blog doesn’t have a comments form)