如何将带有可变参数的插槽连接到带有常量参数的信号
How to connect slot with mutable argument to signal with const argument
我需要将 QWebSocket 的 binaryMessageReceived 信号连接到我修改 QByteData 的插槽
QByteData 可能很大,因此每次在可变变量中再次复制它可能真的很昂贵。我想重用现有的 QByteData
当我尝试使用以下插槽进行编译时
void route(QByteArray& msg);
我遇到编译错误
/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
但如果我将插槽更改为
void route(const QByteArray& msg);
它编译得很好
我是这样连接插槽的:-
connect(this, &QWebSocket::binaryMessageReceived, this, &WSManager::route);
我认为您可以连接到 lambda 并在 lambda 函数中使用 const_cast:
connect(this, &QWebSocket::binaryMessageReceived, this, [this](const QByteArray &message) {
this->route(const_cast<QByteArray &>(message));
});
更新:即使您可以通过这种方式摆脱 constness,但这并不意味着这样做是个好主意 :) 正如在另一个答案中指出的那样,由于 Qt implicit,不会对未更改的 QByteArray 进行数据复制共享机制。
你可能不想那样做。
如果作为 const &
传递,则信号参数不应被修改。您甚至不确定发射器对象 (QWebSocket) 中二进制数据的生命周期。
QByteData 从这里发出:https://code.woboq.org/qt5/qtwebsockets/src/websockets/qwebsocketdataprocessor.cpp.html#181
嵌套在多个类中隐藏在API中,依赖这种attribute/data是非常危险的。
QByteArray
使用 隐式共享 Qt 机制避免深度复制。
https://doc.qt.io/qt-5/implicit-sharing.html
这意味着您可以传递对象而不用担心性能。如果在某个时候您需要修改它,由于移动运算符,您最终可能会处理唯一的实际数据实例。
我需要将 QWebSocket 的 binaryMessageReceived 信号连接到我修改 QByteData 的插槽
QByteData 可能很大,因此每次在可变变量中再次复制它可能真的很昂贵。我想重用现有的 QByteData
当我尝试使用以下插槽进行编译时
void route(QByteArray& msg);
我遇到编译错误
/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
但如果我将插槽更改为
void route(const QByteArray& msg);
它编译得很好
我是这样连接插槽的:-
connect(this, &QWebSocket::binaryMessageReceived, this, &WSManager::route);
我认为您可以连接到 lambda 并在 lambda 函数中使用 const_cast:
connect(this, &QWebSocket::binaryMessageReceived, this, [this](const QByteArray &message) {
this->route(const_cast<QByteArray &>(message));
});
更新:即使您可以通过这种方式摆脱 constness,但这并不意味着这样做是个好主意 :) 正如在另一个答案中指出的那样,由于 Qt implicit,不会对未更改的 QByteArray 进行数据复制共享机制。
你可能不想那样做。
如果作为 const &
传递,则信号参数不应被修改。您甚至不确定发射器对象 (QWebSocket) 中二进制数据的生命周期。
QByteData 从这里发出:https://code.woboq.org/qt5/qtwebsockets/src/websockets/qwebsocketdataprocessor.cpp.html#181
嵌套在多个类中隐藏在API中,依赖这种attribute/data是非常危险的。
QByteArray
使用 隐式共享 Qt 机制避免深度复制。
https://doc.qt.io/qt-5/implicit-sharing.html
这意味着您可以传递对象而不用担心性能。如果在某个时候您需要修改它,由于移动运算符,您最终可能会处理唯一的实际数据实例。