4
votes

How do you add different derived objects on to a vector of unique_ptr. with a vector of pointers i would create the item then a base pointer the to object and pass the pointer to be added, but make_unique dosn't take a pointer and i dont want to make overloaded functions for each type of derived objs.

class Base{...};

class Item:public Base{...};

Add_Item(Base* thing)
{   
    vec.push_back(thing);
}

//Problem with this is i have multiple derived objs and would rather have 1 Add_Item instead of multiple Add_Item functions.(if possible)
Add_Item(Item thing)
{   //this runs,but i lose anything that was in Item class
    vec.push_back(make_unique<Base>(thing));
}

/----------------------------------

follow up question, can you have a vector of unique_ptr inside another. i have tried this, (both ways you guys have shown me, with template Add_Item function and item Add_Item function). but both produced errors.

class Item: public Item
{  vector<unique_ptr<Base>>inv }

Item bag;
Item n_bag;
bag.Add_Item<I>(n_bag);

follow up follow up, no you cant, any recommendation for what kind of smart pointer to use

3
Thank you all for the help, I have a follow up question, is it possible to have a vector of unique_ptr inside another vector of unique_ptr? - user3085497

3 Answers

6
votes

unique_ptr<T> has a constructor that moves from a unique_ptr<U> of a different type U as long as the pointer to the second type is implicitly convertible to the pointer to the first type and U is not an array type. So just use vec.push_back(make_unique<Item>(thing));. See demo.

To accept everything derived from Base, use a template:

template <typename D>
void AddItem(const D& thing) {
    vec.push_back(make_unique<D>(thing));
}

If D is not derived from Base, you get a compile error at the push_back.

2
votes

You want to make your AddItem() method a template method, so that you do not have to write a different function for each derived class. Modifying your existing implementation:

template <typename DERIVED>
void
AddItem (const DERIVED &thing)
{
    vec.push_back(make_unique<DERIVED>(thing));
}
0
votes

The std::make_unique() helper function creates a new object of the given type. In your case this is a Base object, which is not what you want.

Instead, you can manually construct the desired std::unique_ptr:

vec.push_back(std::unique_ptr<Base>(new Item(thing)));

This creates a new Item, and then constructs a unique_ptr<Base> from that.

Alternatively you could also simple create a unique_ptr<Item> and let implicit conversion convert it to a base pointer when you add it to the vector:

vec.push_back(std::make_unique<Item>(thing));