4

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

2
  • 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? Commented Jul 17, 2014 at 6:39
  • An important note to this question and the answers. It's important to make the base class destructor virtual. Normal compilation will not warn you if you forget. But it will result in a memory leak. Commented Jan 13, 2022 at 12:10

3 Answers 3

6

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.

Sign up to request clarification or add additional context in comments.

3 Comments

+1 but of course, one needs std::make_unique, which is not part of C++11.
@Cheersandhth.-Alf Well, the OP used that in their code, so I'm happy to assume that it's available.
@TC answer would be even better (as consultants say) if that clarifying comment was included, i.e. assumptions stated explicitly.
2

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));
}

Comments

0

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));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.