1

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

user7431005
  • 3,899
  • 4
  • 22
  • 49

2 Answers2

2

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.

Ulrich Eckhardt
  • 16,572
  • 3
  • 28
  • 55
1

Long story short, you would need to write a virtual function in C for each inheriting class to override. Something like

virtual std::unique_ptr<C> anotherOnePlease() = 0;

Then you can use this function on each C *, and create a new map. Kind of sucks, but at least you can write a somewhat simple function for copying the map if you implement this function for each derived C.

N00byEdge
  • 1,106
  • 7
  • 18
  • If I do so my return type from `C_1` would need to be `C_1` not `C`. Is this possible? – user7431005 Apr 08 '18 at 15:49
  • You can cast a `C_1 *` to a `C *` since it's a pointer to the base class. This is fine as long as `C_1` is derived from `C`. Note that this is only true for pointers, not values. This is the same reason you can store them in the map together. – N00byEdge Apr 08 '18 at 15:52
  • Of course you also should use `std::unqiue_ptr` too instead of `C *` here, I'm just writing it like that since it's shorter. – N00byEdge Apr 08 '18 at 15:53
  • ok, I think I understand your approach. I will try to implement it like this. – user7431005 Apr 08 '18 at 15:58