Everything,
When I create an instance of the widget array using the format of the initializer list, a bare pointer that points to the widget instance of the member variable, but after changing to std :: unique_ptr <> gcc gives a compilation error regarding the remote function.
$ uname -a
Linux .. 3.5.0-21-generi # 32-Ubuntu SMP Tue Dec 11 18:51:59 UTC 2012 x86_64 x86_64 x86_64 GNU / Linux
$ g ++ --version
g ++ (Ubuntu / Linaro 4.7.2-5ubuntu1) 4.7.2
This code gives the following compiler error:
#include <stdlib.h> #include <memory> class Widget { public: Widget() {} }; class W1 : public Widget { public: W1() {} }; class W2 : public Widget { public: W2() {} }; class WFactory { public: WFactory(const int i) : _w(new W1()) {} WFactory(const char* s) : _w(new W2()) {} ~WFactory() { _w.reset(nullptr); } // ~WFactory() { delete _w; } <--- for naked ptr private: // NOTE: does not compile std::unique_ptr<Widget> _w; // NOTE: does compile // Widget* _w; }; int main() { std::unique_ptr<Widget> a(new W1()); // <--- compiles fine WFactory wf[] { 4, "msg" }; // <--- compiler error using unique_ptr<> }
Error:
$ g++ -o unique_ptr -std=c++11 -Wall unique_ptr.cpp unique_ptr.cpp: In function 'int main()': unique_ptr.cpp:36:30: error: use of deleted function 'WFactory::WFactory(const WFactory&)' unique_ptr.cpp:22:7: note: 'WFactory::WFactory(const WFactory&)' is implicitly deleted because the default definition would be ill-formed: unique_ptr.cpp:22:7: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Widget; _Dp = std::default_delete<Widget>; std::unique_ptr<_Tp, _Dp> = std::unique_ptr<Widget>]' In file included from /usr/include/c++/4.7/memory:86:0, from unique_ptr.cpp:2: /usr/include/c++/4.7/bits/unique_ptr.h:262:7: error: declared here unique_ptr.cpp:36:30: error: use of deleted function 'WFactory::WFactory(const WFactory&)' unique_ptr.cpp:36:14: warning: unused variable 'wf' [-Wunused-variable]
I find it difficult either: the mechanics behind the scenes, which gives the remote fcxn; or more simply, why the expressiveness of std :: unique_ptr <> is limited compared to naked ptr.
My question is:
- pilot error
- Compiler error?
- Can I make my intended code work with some changes?
Thanks.
Change 1
Based on your answers, which I appreciate, I can make the following changes to WFactory:
( marked as immoral code )
class WFactory { public: WFactory(const WFactory& wf) { (const_cast<WFactory&>(wf)).moveto(_w); } WFactory(const int i) : _w(new W1()) {} WFactory(const char* s) : _w(new W2()) {} ~WFactory() { _w.reset(nullptr); } void moveto(std::unique_ptr<Widget>& w) { w = std::move(_w); } private: std::unique_ptr<Widget> _w; };
and now the program compiles and runs. I appreciate that the people in charge of the standards wrote the specification for some reason, so I publish my result as a bona fide specialization for my business, where I really would like to emphasize the uniqueness of ptr.
Edit 2
Based on Jonathan's answers, the following code does not suppress the implicit ctor move:
class WFactory { public: WFactory(const int i) : _w(new W1()) {} WFactory(const char* s) : _w(new W2()) {} private: std::unique_ptr<Widget> _w; };
Note that there is no ~WFactory() {..} at all.
There may be ya-ans, but I found that using C ++ 11 wf [] style iteration in Main () returns a no-copy-ctor-for-WFactory error. I.e:
int Main() .. WFactory wf[] { 4, "msg" }; for ( WFactory iwf : wf ) <---- compiler error again
I assume it goes without saying that the new C ++ 11 style iteration makes a copy of the object.