I'm working in Qt, I didn't mention it, because I thought it was just C++ problem.
I solved this problem with shared pointers, so don't give me solution. But it's question of comprehending, I want to understand why it's not working.
I was trying the following:
test.h:
#include <QObject>
#include "response.h"
#include <memory>
class Test : public QObject
{
Q_OBJECT
public:
explicit Test(QObject *parent = nullptr);
signals:
void signal(std::unique_ptr<Response> resp);
public slots:
};
test.cpp:
Test::Test(QObject *parent) : QObject(parent)
{
std::unique_ptr<Response> response(new Response(5));
emit signal(std::move(response));
}
Response class:
class Response
{
public:
Response(int data);
private:
int data;
};
I know that std::unique_ptr can't be copied and I use std::move here. But in spite of this I get an error:
moc_test.cpp:75:85: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Response; _Dp = std::default_delete<Response>]’
case 0: _t->signal((*reinterpret_cast< std::unique_ptr<Response>(*)>(_a[1]))); break;
In the following snippet of moc_test.cpp, which is product of Qt meta-object system:
void Test::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void `_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
auto *_t = static_cast<Test *>(_o);
Q_UNUSED(_t)
switch (_id) {
//------- !! This line!!
case 0: _t->signal((*reinterpret_cast< std::unique_ptr<Response>(*)>(_a[1]))); break;
default: ;
}
} else if (_c == QMetaObject::IndexOfMethod) {
int *result = reinterpret_cast<int *>(_a[0]);
{
using _t = void (Test::*)(std::unique_ptr<Response> );
if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&Test::signal)) {
*result = 0;
return;
}
}
}
}
Spent much time, but I couldn't figure it out why that error occurred and didn't find anything helpful in the internet.
Creating Custom Qt Types mentions the constraints imposed on a Qt meta-type, i.e the type requires a copy constructor (to be emit-able).
The reason that
constis mentioned in the error message is that we're trying to invoke the (deleted) copy constructor of theunique_ptr(as indicated by the message).I suspect that while the move is taking place when passed as parameter, you're still assigning the rvalue (e.g in the constructor).
Note, you haven't posted all the code, but my suspicion is that your code fails for the same reason as the code below:
The failure being:
The reason is that copy initialization is taking place (of
pointer_). You need to callmoveto move the (now lvaluepointer) into the member.I would suggest the code perform the initialization to be modified as follows:
Note that I did not pass
std::unique_ptrby value. In practice it would always be an rvalue, and perhaps the additional move constructor call would be elided (I'm not sure, but I just use an rvalue reference in these circumstances).Also note that it is not necessary to qualify
move, as it will looked up as result of ADL.