Probably I've missed something, but I can't find any information that signals can't take rvalue references.
So, I have a class with the following signal declaration:
signals:
void messageDecoded(HTDataMsg &&msg);
When I try to compile it, I got errors:
moc_htcodec.cpp: In static member function ‘static void HTCodec::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)’:
moc_htcodec.cpp:71:77: error: cannot bind ‘HTDataMsg’ lvalue to ‘HTDataMsg&&’
case 0: _t->messageDecoded((*reinterpret_cast< HTDataMsg(*)>(_a[1]))); break;
^
In file included from moc_htcodec.cpp:9:0:
../hterm_core/htcodec/htcodec.h:59:9: error: initializing argument 1 of ‘void HTCodec::messageDecoded(HTDataMsg&&)’
void messageDecoded(HTDataMsg &&msg);
^
make: *** [moc_htcodec.o] Error 1
And the code in generated moc-file is indeed wrong:
void HTCodec::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
HTCodec *_t = static_cast<HTCodec *>(_o);
switch (_id) {
case 0: _t->messageDecoded((*reinterpret_cast< HTDataMsg(*)>(_a[1]))); break;
default: ;
}
} else if (_c == QMetaObject::IndexOfMethod) {
int *result = reinterpret_cast<int *>(_a[0]);
void **func = reinterpret_cast<void **>(_a[1]);
{
typedef void (HTCodec::*_t)(HTDataMsg && );
if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&HTCodec::messageDecoded)) {
*result = 0;
}
}
}
}
Is this behavior expected? Is it illegal for signals to take rvalue references?
If I change HTDataMsg &&msg
to, say, const HTDataMsg &msg
, then of course it works.
Is it illegal for signals to take rvalue references?
Yes. It makes no sense for them to take rvalue references, since the number of receivers is a non-negative integer. Rvalue references would only make sense for the special case of zero or one receiver, and even then, it'd require a C++11-only version of Qt.
If you think that such an optimization makes sense for common data types (measure and back your assertions by benchmarks!), it could be implemented for Qr 5.7 onwards, since it requires C++11 support by the platform. This would need support from moc
as well as from the library itself.
If you need to use memory move for case with one signal and only one slot you can pass object by simple reference not 'const' and then use move semantic inside slot. Here is some simple example:
class PcapPacket {
public:
PcapPacket();
std::vector<uint8_t>&& getData() {
return std::move(_vData);
}
private:
std::vector<uint8_t> _vData;
};
signals:
void packet(PcapPacket& pcapPacket);
// Register types for signals
qRegisterMetaType<PcapPacket>("PcapPacket&");
connect(pcapReader, &PcapReader::packet, controlItem, &SensorControlItem::processPcapPacket);
// connect(_pcapReader, SIGNAL(packet(PcapPacket&)), controlItem, SLOT(processPcapPacket(PcapPacket&)));
void SensorControlItem::processPcapPacket(PcapPacket& packet) {
_sensor->processPcapPacket(packet.getData());
}
void sensor::processPcapPacket(std::vector<uint8_t>&& data) {
// Do here with data what ever you want. It's yours without memory copy
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With