Search code examples
c++copysmart-pointersunique-ptrdeep-copy

deep copy of objects containing unordered_map of unique_ptr


I have the following situation:

I need to create a deep (!) copy of a variable from type A. This variable contains a vector of type B. Class B is not copyable, because it contains a std::unordered_map whos value is a unique_ptr (which is not copyable). I would like to avoid making B copyable via a copy constructor or copy assignment operator.

One problem is that the type of the unique_ptr is just the base type. The actual objects are derived from C and contain different members and have different constructors.

class A{
public:
    A(const A&);            // how should I implement this?
    A& operator=(const A&); // how should I implement this?
private:
    vector<B> vectorOfB;
}

class B{
private:
    std::unordered_map<std::string, std::unique_ptr<C> mapOfDerivedTypesOfC;
}

class C{}

class C_1: public C{
public:
    C_1(double x)
}

class C_2: public C{    
public:
    C_2(double y, double z)
}

Background: The purpose of class A is to read a lot of large text files with data and create many objects. Afterwards I have to run monte-carlo simulations with this objects. For every simulation I need a fresh copy of A. I do not want to read in all the text files every time because it is time consuming. Therefore it is necessary to make a deep copy of A. During one simulation I want to avoid copying B because it makes no sence that this object should ever be copied. I think using a sharded_ptr does not help because I need a deep copy and the simulations run in parallel using openMP.

Edit: I think the overall question is how should I copy the unordered_map


Solution

  • I think the technique is known as "virtual copy constructor":

    // in baseclass
    public:
    unique_ptr<Base> clone() const
    {
        unique_ptr<Base> other(this->do_clone());
        assert(typeid(*this) == typeid(*other));
        return other;
    }
    private:
    virtual Base* do_clone() const = 0;
    
    // in derived class
    private:
    virtual Derived* do_clone() const
    {
        return new Derived(*this);
    }
    

    The idea is that a type eventually has info how to clone instances of itself, so you delegate cloning to it via a virtual function. The assertion makes sure that the derived class correctly implements/overrides the baseclass implementation.