Compiler error when a destructor is declared in a body class with uniqueptr as a member of the same class

The following is a minimal code problem:

struct B { B () = default; //~B () {}; // error: use of deleted function 'B& B::operator=(const B&)' std::unique_ptr<int> m_pB = nullptr; }; int main () { std::vector<B> vB; vB.erase(vB.begin()); } 

The above code compiles fine if the destructor is not uncommented. For my requirement, I need an explicit definition of the body ~B() .

How can I define a destructor body with unique_ptr coexisting in the same class?

Note I tried the definition = default of the copy and move constructor versions to no avail. In my real code, unique_ptr<int> has unique_ptr<forward_declared_class> . This problem could not be found in SO, although I am sure that it should be present. Feel free to flag as cheating.

+7
c ++ c ++ 11 destructor compiler-errors unique-ptr
source share
3 answers

It seems that your code requires B copy the construct and copy the assignment for std::vector (at least for the visual C ++ that I tested).

Copy constructor and copy assignment operators can be = delete due to std::unique_ptr (declarations declared = default should also call a function), and by implementing the destructor you disable the default implementation of the move constructor and move the assignment operator.

So, you need to explicitly declare a move assignment operator. Try:

 #include <memory> #include <vector> struct B { B () = default; ~B () {} B& operator=(B&&) = default; std::unique_ptr<int> m_pB = nullptr; }; int main () { std::vector<B> vB; vB.erase(vB.begin()); } 
+5
source share

You can declare and implement the move-assign statement requested by the compiler. Of course, he complains about the purpose of the copies, but a reasonable copy seems impossible to your structure.

The error message is probably a little misleading, since the implementation of std::vector::erase contains the code _data[i-1] = _data[i] in the code that translates vector elements to the places of deleted elements. Therefore, the compiler needs any assignment operator, and we provide it with moving ones.

For example, this works fine (gcc 4.8.3):

 struct B { B () = default; B& operator=(B&& op) { m_pB = std::move(op.m_pB); return *this; } ~B () {}; // no more errors. std::unique_ptr<int> m_pB = nullptr; }; int main () { std::vector<B> vB; vB.erase(vB.begin()); } 
+3
source share

Vector code - red herring.

If the class U has a member of type unique_ptr and T is declared forward, the destructor definition must be in the cpp file when U is no longer an incomplete type.

You must have ~ U (); in the header and in the cpp file have U :: ~ U () {} or U :: ~ U () = default;

0
source share

All Articles