I want to make a container which manages big objects. which performs deep copies on copy construction and copy assignment. I also like the interface of the std containers, so I wanted to implement it using public inheritance:template <class TBigObject>class Container : public std::vector< std::shared_ptr<TBigObject> >{public:    Container(int nToAllocate){ /* fill with default constructed TBigObjects */}    Container(const Container& other){ /* deep copy */ }    Container(Container&&) = default;    Container& operator = (const Container& population){ /* deep copy */ }    Container& operator = (Container&&) = default;};I heard of the Thou shalt not inherit from std containers maxim and the reasons behind it. So I decided to make an alternative:template <class T>using Container = std::vector< std::shared_ptr<T> >;template <class T>Container<T> defaultAllocate(int nItems);template <class T>Container<T> deepCopy(const Container<T>& other);This looks more expressive, but using the code feels strange and verbose:class Big;Container<Big> someContainer = defaultAllocate(12);Container<Big> copy = deepCopy(someContainer);instead of:class Big;Container<Big> someContainer(12);Container<Big> copy = someContainer;I am a beginner programmer and I don't want to make errors early on. I would like to ask your advice on which choice to make. Or even better, if there is a third option.
How to design interface of deep-copy behaving pointer containers?
c++;c++11
I think you are going about it the wrong way.Containers already perform copy on copy construction/assignment because they are designed for value objects not pointers. What you really want is a wrapper object for pointers that performs a deep copy when that object is copied.This has the added advantage of working with all containers.If you define the move operators then it also works well with re-size operations as the move semantics will be applied to the wrapper when the the container is re-sized.The other advantage here is you can make the wrapper behave like the underlying type. So you get easy access to all the algorithms.template<typename T>class Deep{   T*     value;   public:       Deep():                      value(NULL)         {}       // Take ownership in this case.       Deep(T const* value):        value(value)        {}       Deep(T const& value):        value(new T(value)) {}       ~Deep()                      {delete value;}       Deep(Deep&& move)            {std::swap(value, move.value);}       Deep(Deep const& copy)       {T* tmp = new T(*(copy.value));swap(tmp,value);delete tmp;}       // Note this does do a deep copy via copy and swap       Deep& operator=(Deep copy)   {std::swap(value, copy.value);return *this;}       Deep& operator=(Deep&& move) {std::swap(value, move.value);return *this;}       // Note: undefined behavior if used when value is NULL.       //       You may want to add logic here depending on use case.       operator T&()                {return *value;}       operator T const&() const    {return *value;}       T* release()                 {T* tmp = value;value = NULL;return tmp;}};int main(){    std::vector<Deep<int>>   deep(5,7);}