Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct
[SOLVED] Signal parameter of type std::unique_ptr
Is it possible to use a std::unique_ptr in a signal? I'm trying to embrace the new language features of C++11 and have been using unique_ptr and shared_ptr where possible.
Now I want to emit a signal of the form:
@void newThing(std::unique_ptr<Thing> thing);@
When I emit the signal, I do it like this:
@auto newThing = std::unique_ptr<Thing>(new Thing());
I get compiler errors in the moc file, so I'm wondering if I'm on a wild goose chase here that Qt 4.8.5 at least doesn't support this.
t3685 last edited by
You need to register the type so that moc knows what it is.
So in your case you need to declare
in a header file and call @qRegisterMetaType<std::unique_ptr<Thing>>();@ before your signal and slots are used.
By the way, Qt 4.8.5 is compiled with GCC 4.4 which does not support all C++11 features just so you know (unless you compiled Qt yourself of course :))
I've seen references to Q_DECLARE_METATYPE but I understood it to only be required when using a queued connection. Thanks for pointing me in the right direction.
I have to support Windows and Linux and have been developing on Linux so far. I discovered that I couldn't compile my code using C++ features on Windows because the Qt SDK installed GCC 4.4, so I downloaded the latest MinGW Builds build which includes GCC 4.8.1. I rebuild Qt with this compiler. On Ubuntu 12.10 I'm using GCC 4.7 and I assume the Qt library was built with that version as well...
Thanks for the help!
Now I get the same error on the Q_DECLARE_METATYPE line:
@/usr/include/qt4/QtCore/qmetatype.h:142: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&)@
I can't see how the meta type registration will have any influence, as I understand it is needed when transferring the parameter in a QVariant.
Going back to the emit of the signal...
The qt_static_metacall() method contains the following case:
@case 1: _t->newThing((reinterpret_cast< std::unique_ptr<Thing>()>(_a))@
I suppose the problem is that the std::move is not used in the generated method call.
I've changed the parameter to std::shared_ptr, which works. At least I can make the code work, but I would still like too be able to use unique_ptr when it is the most appropriate smart pointer for the circumstance. So, I'm keeping it open.
t3685 last edited by
From the documentation:
"Creating a Custom Type Before we begin, we need to ensure that the custom type we are creating meets all the requirements imposed by QMetaType. In other words, it must provide:
a public default constructor, a public copy constructor, and a public destructor."
So your custom type (in this case std::unique_ptr) needs to meet those requirements. However, as you can see from your error that the copy constructor was "deleted" (google the C++11 keyword delete in header files).
Which is logical if you think about it in hindsight :), when a signal is emitted, multiple slots can be connected to it: how can multiple slots have the same std::unique_ptr? I probably should have realized this before I pointed you to the documentation (my bad!).
std::shared_ptr works because well, it can be shared :).
I missed the simple issue of sending the unique_ptr to multiple destinations completely! In my case I was thinking of the single slot provider and didn't think of the implications of having multiple slots breaking the unique_ptr contract! Hey, that's how you learn...