Home > OS >  How to connect slot with mutable argument to signal with const argument
How to connect slot with mutable argument to signal with const argument

Time:09-22

I need to connect binaryMessageReceived signal of QWebSocket to my slot which modifies the QByteData

The QByteData may be large so it might be really costly to copy it again in mutable variable each time. I want to reuse the existing QByteData

when I try to compile with following slot

void route(QByteArray& msg);

I get compilation error

/usr/include/qt/QtCore/qobject.h:255:9: error: static assertion failed: Signal and slot arguments are not compatible.
  255 |         Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
      |         ^~~~~~~~~~~~~~~~~
/usr/include/qt/QtCore/qobject.h:255:9: note: ‘(((int)QtPrivate::CheckCompatibleArguments<QtPrivate::List<const QByteArray&>, QtPrivate::List<QByteArray&> >::value) != 0)’ evaluates to false

but if I change the slot to

void route(const QByteArray& msg);

it compiles just fine

I'm connecting slot like this:-

connect(this, &QWebSocket::binaryMessageReceived, this, &WSManager::route);

CodePudding user response:

You probably don't want to do that.

The signal argument is not meant to be modified if passed as const &. You are not even sure of the lifetime of the binary data in the emitter object (QWebSocket).

The QByteData is emitted from here : https://code.woboq.org/qt5/qtwebsockets/src/websockets/qwebsocketdataprocessor.cpp.html#181
Nested in multiple classes hidden from the API, it's very dangerous to rely on this kind of attribute/data.


QByteArray uses the implicit-sharing Qt mecanism which avoid deep copy.
https://doc.qt.io/qt-5/implicit-sharing.html

That means you can pass the object around without concern about the performances. And if at some point you need to modify it, you might end up working on the only actual instance of the data thanks to the move operator.

CodePudding user response:

I think you could connect to lambda and use const_cast inside the lambda function:

connect(this, &QWebSocket::binaryMessageReceived, this, [this](const QByteArray &message) {
    this->route(const_cast<QByteArray &>(message));
});

Update: even you can cast constness away this way it doesn't mean it's a good idea to do that :) As it was pointed out in the other answer no data copying is done for unchanged QByteArray because of Qt implicit sharing mechanism.

  • Related