Auto-cloning unique_ptr

c++, c++11, clone, copy-constructor, unique-ptr

Solution

Let me first paraphrase what you want to do: You want that each instance of `Foo` has its own instance of `Base` in `b`; in particular, if you copy a `Foo`, the copy will have its own new `Base`, initially with the same "value". In other words, `Base` should behave like a value.

At the same time, you can't store `Base` directly in `Foo` because it is an abstract class. In other words, you want `b` to be `polymorphic`.

There you have it: you want a polymorphic value. Other people have recognized this need and proposed for C++20 as `polymorphic_value<Base>`. From the documentation:

The class template, polymorphic_value, confers value-like semantics on a free-store allocated object. A polymorphic_value may hold an object of a class publicly derived from T, and copying the polymorphic_value will copy the object of the derived type.

It has a reference implementation that you can use as of now. Very simply put, it is an wrapper around `std::unique_ptr` similar to what you propose.

Problem

`std::unique_ptr` has a deleted copy constructor, which means that if you have a `unique_ptr` in your class `Foo` as a data member then you must write your own copy constructor for `Foo` and manually deep-copy that member (even if the compiler-generated copy constructor would be fine for all other members). In order to be able to copy in a polymorphic way, the `clone()` method pattern can be used. Let's assume our objects have a clone method like this: ``` class Base { virtual std::unique_ptr<Base> clone() = 0; }; ``` Foo looks like this now: ``` 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 }; ``` Now, I found a way to auto-clone `Foo::b`, by writing a wrapper over `unique_ptr` that defines the copy constructor and assignment by calling `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();} }; ``` Now if we use this we don't need to define our own copy constructor: ``` class Foo2 { public: ... private: auto_cloned_unique_ptr<Base> b; //10 more data members }; ``` Is such an approach very much frowned upon (for using a non-standard wrapper over `unique_ptr`)?

Original source