[SOLVED] Signal parameter of type std::unique_ptr
-
wrote on 2 Oct 2013, 16:25 last edited by
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());
...
emit newThing(std::move(newThing));@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.
-
wrote on 2 Oct 2013, 17:16 last edited by
You need to register the type so that moc knows what it is.
http://qt-project.org/doc/qt-4.8/custom-types.html
So in your case you need to declare
@Q_DECLARE_METATYPE(std::unique_ptr<Thing>);@
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 :))
-
wrote on 2 Oct 2013, 17:35 last edited by
Thanks t3685!
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!
-
wrote on 2 Oct 2013, 18:38 last edited by
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[1]))@I suppose the problem is that the std::move is not used in the generated method call.
-
wrote on 3 Oct 2013, 10:55 last edited by
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.
-
wrote on 3 Oct 2013, 16:24 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 :).
-
wrote on 4 Oct 2013, 05:58 last edited by
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...
Thanks!
1/7