peter55555
peter55555

Reputation: 1475

How to copy vector<unique_ptr<T>> to independent vector<T*>

I have a std::vector<std::unique_ptr<T>> vec1 where T is an abstract type. I'd like to create std::vector<T*> vec2 where objects pointed by pointers from 2nd vector are copy of objects pointed by pointers of 1st vector.

So for example: *(vec1[0]) == *(vec2[0]) and vec1[0].get() != vec2[0] ... etc...

How to do that?

Upvotes: 1

Views: 1041

Answers (2)

milleniumbug
milleniumbug

Reputation: 15834

Using std::transform

std::vector<T*> vec2;
vec2.reserve(vec1.size()); // optimization to avoid reallocations, it isn't necessary, and without it the code still works correctly
std::transform(vec1.begin(), vec1.end(), std::back_inserter(vec2), [](const std::unique_ptr<T>& p){ return YourCloneFunction(*p); }

One way to write a clone function is to make all your descendant classes have defined virtual clone function, which is abstract in T. The code of such method is simple, but needs to be defined for every Derived class.

class T
{
    virtual std::unique_ptr<T> clone() const = 0;
    virtual ~T(){}
};

class Derived : public T
{
    std::unique_ptr<T> clone() const override {
        return std::unique_ptr<T>(new Derived(*this));
    }
};

With this, the code becomes

std::vector<T*> vec2;
vec2.reserve(vec1.size()); // optimization to avoid reallocations, it isn't necessary, and without it the code still works correctly
std::transform(vec1.begin(), vec1.end(), std::back_inserter(vec2), [](const std::unique_ptr<T>& p){ return p->clone().release(); }

Note that we have vec2 raw pointers pointing to objects not owned by any smart pointer. This is bad, unless you're passing vec2 into legacy function that takes ownership of these pointers.

Otherwise if you want only a std::vector<T*> view of the copies, clone into an intermediate std::vector<std::unique_ptr<T>>, and then copy result of .get() on each instance to std::vector<T*>

Upvotes: 6

Jarod42
Jarod42

Reputation: 218333

The manual way:

std::vector<std::unique_ptr<T>> vec1;
std::vector<T*> vec2;
vec2.reserve(vec1.size()); // optimization to avoid reallocations

for (const auto& e : vec1) {
    vec2.push_back(e->clone());
}

with virtual T* T::clone() const

Upvotes: 0

Related Questions