add tag
Jonathan Mee
Given these toy structs:

    struct Foo {
        virtual void Identify() const { cout << "Foo\n"; }
    };
    
    struct Bar : Foo {
        void Identify() const override { cout << "Bar\n"; }
    };

I'd like to create a `std::vector` of polymorphic objects. `std::vector<Foo>` suffers from [Object Slicing](https://en.wikipedia.org/wiki/Object_slicing) this can be avoided by maintaining a seperate `std::vector` of enums indicating the type which the element's dereference should be cast to. `std::vector<Foo*>` requires me to:

 1. Maintain the objects in a separate `std::vector`
 1. Dynamically allocate the objects with `new` which must be managed any time objects are removed from the `std::vector`

 Does C++ provide me a way to have a polymorphic `std::vector` without me writing seperate support machinery?
Top Answer
Jonathan Mee
 What you're looking for is smart pointers. C++ provides 2: [`std::unique_ptr`](https://en.cppreference.com/w/cpp/memory/unique_ptr) and [`std::shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr). You'll want to make a `std::vector` of one of these.

 `std::vector<std::unique_ptr<Foo>> unique` is preferable because it is very light weight, but elements cannot be copied, so you couldn't do these things with `unique`:
 
 1. `unique.push_back(new Foo)` instead you'd have to do `unique.emplace_back(new Foo)`
 1. `const auto element = unique.front()` instead you'd have to do `const auto& element = unique.front()`
 1. `unique.push_back(unique.front())` instead you'd have to do `*unique.emplace_back(dynamic_cast<Bar*>(unique.front().get()) == nullptr ? new Foo : new Bar) = *unique.front()`
 1. `const auto my_vec = unique` instead you'd need to write a function for copying these, something like:

```
std::vector<std::unique_ptr<Foo>> Copy(const std::vector<std::unique_ptr<Foo>>& rhs) {
    std::vector<std::unique_ptr<Foo>> result;

    for(const auto& i : rhs) {
        *result.emplace_back(dynamic_cast<Bar*>(i.get()) == nullptr ? new Foo : new Bar) = *i;
    }
    return result;
}
```

Because we're using `dynamic_cast` to do [Run Time Type Identification (RTTI)](https://en.wikipedia.org/wiki/Run-time_type_information) the above code and that of **3** can balloon. This is an unfortunate cost of polymorphisim.

As far as `std::vector<std::shared_ptr<Foo>> shared`, this does not have any limitations upon copying elements. Thus RTTI need not be performed because the element itself is copied rather than recreated. Thus even though `std::shared_ptr` is heavier it is sometimes used in polymorphic `std::vectors`.

This room is for discussion about this question.

Once logged in you can direct comments to any contributor here.

Enter question or answer id or url (and optionally further answer ids/urls from the same question) from

Separate each id/url with a space. No need to list your own answers; they will be imported automatically.