New QObject::connect syntax isn’t as type-safe as I thought
Qt 5 introduced a new syntax for connect
; instead of this:
connect(
, SIGNAL(signalName(type1, type2)),
senderObject, SLOT(slotName(type1, type2))); receiverObject
one can now write this:
connect(
, &Sender::signalName,
senderObject, &Receiver::slotName); receiverObject
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(
->pushButton, &QPushButton::clicked,
uithis, &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)