Unique_ptr as a class member and move semantics cannot compile with clang

I cannot get clang (Apple LLVM version 4.2 (clang-425.0.28)) to compile these classes:

struct A { int f(){return 2;} }; class Cl{ std::unique_ptr<A> ptr; public: Cl(){ptr = std::unique_ptr<A>(new A);} Cl(const Cl& x) : ptr(new A(*x.ptr)) { } Cl(Cl&& x) : ptr(std::move(x.ptr)) { } Cl(std::unique_ptr<A> p) : ptr(std::move(p)) { } void m_ptr(std::unique_ptr<A> p){ ptr = std::unique_ptr<A>(std::move(p)); } double run(){return ptr->f();} }; 

I would like to run the constructor as follows:

 std::unique_ptr<A> ptrB (new A); Cl C = Cl(ptrB); 

but if I do, I get the following compiler error: .. / src / C ++ 11-2.cpp: 66: 10: error: invoking an implicitly deleted copy of the constructor 'std :: unique_ptr' C.m_ptr (ptrB) ;

I can solve the compiler problem by running Cl(std::move(ptrB)) , but this does not actually transfer the ownership of A away from ptrB: I can still run ptrB->f() without causing a crash of time execution ... Secondly, the constructor is not very satisfying, since I want to hide the implementation of std::move in the class interface.

Thanks in advance.

+1
compiler-errors unique-ptr llvm-clang
source share
1 answer

Since ptrB is passed by value to the Cl cl constructor, a call to Cl (ptrB) attempts to create a copy of ptrB, which in turn calls the (explicitly disabled) instance of the unique_ptr copy. To avoid creating an additional copy of ptrB, do the following:

 Cl C = Cl(std::unique_ptr<A>(new A)); //A temporary is created on initialization, no extra copy steps performed 

Or:

 std::unique_ptr<A> ptrB (new A); Cl C = Cl(std::move(ptrB)); //Move semantics used. Again, no extra copy steps 

Or, use pass by reference (rvalue or lvalue) in your copy constructor:

 class Cl{ //... public: //... Cl(std::unique_ptr<A> &p) : ptr(std::move(p)) { } //... }; std::unique_ptr<A> ptrB (new A); Cl C = Cl(ptrB); 

PS Oh, and by the way: objects remain undefined, but the actual state is after std :: move (). I believe this means that you can still call ptrB-> f () anyway, and this is guaranteed to return 2 :)

+2
source share

All Articles