std::unique_ptr
имеет конструктор удаленной копии, что означает, что если у вас есть unique_ptr
в вашем классе Foo
как член данных, тогда вы должны написать свой собственный конструктор копирования для Foo
и вручную глубоко скопировать член (даже если создатель, созданный компилятором, будет хорош для всех остальных членов).
Чтобы иметь возможность копировать полиморфным способом, можно использовать шаблон метода clone()
. Пусть предположим, что у наших объектов есть метод клонирования:
class Base {
virtual std::unique_ptr<Base> clone() = 0;
};
Теперь Foo выглядит следующим образом:
class Foo {
public:
...
Foo(Foo const& other)
: b(other.b->clone())
, // init 10 more members that could otherwise be auto-copied just fine
// with the automatically generated copy constructor
{}
...
private:
std::unique_ptr<Base> b;
//10 more data members
};
Теперь я нашел способ авто-клонирования Foo::b
, написав обертку поверх unique_ptr
, которая определяет конструктор и назначение копии, вызывая clone
.
template <typename T>
class auto_cloned_unique_ptr
{
private:
std::unique_ptr<T> up;
public:
// copy constructor
auto_cloned_unique_ptr(auto_cloned_unique_ptr<T> const& other)
: up(other.up->clone()) {}
// copy assignment
auto_cloned_unique_ptr<T>& operator =(auto_cloned_unique_ptr<T> const& other)
{
this->up = other.up->clone();
return *this;
}
auto_cloned_unique_ptr(std::unique_ptr<T> _up)
: up(std::move(_up)) {}
// Delegate everything else to unique_ptr
auto_cloned_unique_ptr(auto_cloned_unique_ptr<T>&& other)
: up(std::move(other.up)) {}
auto_cloned_unique_ptr<T>& operator =(auto_cloned_unique_ptr<T>&& other)
{
this->up = std::move(other.up);
return *this;
}
auto operator *() const {return *up;}
auto operator->() const {return up.operator->();}
auto get() -> const {return up.get();}
};
Теперь, если мы используем это, нам не нужно определять наш собственный конструктор копирования:
class Foo2 {
public:
...
private:
auto_cloned_unique_ptr<Base> b;
//10 more data members
};
Является ли такой подход очень неодобрительным (для использования нестандартной обертки над unique_ptr
)?