Search code examples
c++inheritancec++17move-semanticsemplace

Emplace object derived from non-copyable into vector


I have objects that holds pointers and shares them with others. Moving them is fine, but copying not. I would like to store them in vectors and maps. The following code works only when A has no destructor. However I would need a destructor to clean up my pointers.

#include <vector>

struct OnlyMove
{
    OnlyMove(const OnlyMove&) = delete;
    OnlyMove& operator=(const OnlyMove&) = delete;
    OnlyMove(OnlyMove&&) = default;
    OnlyMove& operator=(OnlyMove&&) = default;

protected:
    OnlyMove() = default;
};

struct A : OnlyMove
{
    A(int){}
    ~A(){} // makes compilation fail
};

int main()
{
    std::vector<A> y;
    y.emplace_back(1);
}

The error when I have a destructor:

/usr/local/include/c++/8.2.0/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = A; _Args = {A}]': … error: use of deleted function 'OnlyMove::OnlyMove(const OnlyMove&)'

I don't understand why. What role does the destructor play here?

Live Demo


Solution

  • You need:

    struct A : OnlyMove
    {
        A(int){}
        A(A&&) = default;  // need this
        ~A() {} 
    }; 
    

    When you introduce the desctructor, the move constructor disappears. Without the move constructor or a copy constructor, it can't be placed in a vector.

    EDIT: the move constructor is best if it is noexcept, otherwise std::vector::resize and std::vector::push_back have no guarantees when exceptions are thrown.