Revamping some old code where I was manually handling lifetimes of a vector of raw pointers to concrete instances of an abstract base class (ABC).
So the vector's owner had a virtual dtor which manually went through and deleted the contents of the vector, etc.
Since the vector's owner owns the elements in it, it makes a lot of sense to change this to a vector of unique_ptr's.
Sadly, it seems this is impossible? Because a vector<unique_ptr<type>>
must be able to have a static dtor for type
but because in this case type is an ABC, that is not available, hence the vector
won't compile...
Or am I missing something?
e.g.:
struct ABC
{
ABC() = default;
virtual ~ABC() { } // need a vtable entry so that concrete subclasses will be deleted through the base dtor
virtual std::unique_ptr<ABC> Clone() = 0;
virtual void Foo() = 0;
std::vector<std::unique_ptr<ABC>> elements;
};
EDIT2: here's a complete example that fails:
#include <iostream>
#include <memory>
#include <vector>
struct ABC
{
virtual ~ABC() { } // need a vtable entry so that concrete subclasses will be deleted through the base dtor
virtual std::unique_ptr<ABC> Clone() = 0;
virtual void Foo() = 0;
std::vector<std::unique_ptr<ABC>> elements;
};
struct Child : ABC
{
std::unique_ptr<ABC> Clone() override { return std::make_unique<Child>(*this); }
void Foo() override { };
};
struct Derived : Child
{
std::unique_ptr<ABC> Clone() override { return std::make_unique<Derived>(*this); }
};
int main()
{
std::unique_ptr<ABC> x;
std::unique_ptr<ABC> c = std::make_unique<Child>();
std::vector<std::unique_ptr<ABC>> elements;
elements.emplace_back(std::make_unique<Derived>());
return 0;
}
The error occurs when you try to copy an instance of Base
or an instance of a type derived from Base
. The default copy constructor will attempt to copy Base::elements
, which attempts to copy each of it's elements into the new vector
. Since these elements are unique_ptr<Base>
this copy is not allowed.
This example reproduces the problem :
#include <memory>
#include <vector>
struct Base
{
using PBase = std::unique_ptr<Base>;
using VBase = std::vector<PBase>;
VBase elements;
};
int main()
{
Base x;
auto y = x; // This line causes the error
return 0;
}
You will likely need to implement your own copy constructor and copy assignment operator, or forbid copying by deleting these functions. Using shared_ptr
instead might work, if shallow copies will work for your application.