Home > Net >  How to cast a shared_ptr<vector<derived class>> to a shared_ptr<vector<base class&
How to cast a shared_ptr<vector<derived class>> to a shared_ptr<vector<base class&

Time:10-10

As the title,I have a odd requirement. Code examples:

class Base{
}
class Derived: Base{
}

//I want cast that.
shared_ptr<vector<Derived*>>  ->   shared_ptr<vector<Base*>>

Here is my way:

shared_ptr<vector<Derived*>> derived_vector_sp;

auto* base_vector_rawptr = (vector<Base*> *)derived_vector_sp.get();

shared_ptr<vector<Base*>> base_vector_sp = make_shared<<vector<Base*>>>(*base_vector_rawptr);

It works.But in this way I create anthor vector.And two shared_ptr manage two different vecotr.
So is there any way finish this case directly?such as:

//this way doesn't work.
shared_ptr<vector<Base*>> base_vector_sp = static_pointer_cast<vector<Base*>>(derived_vector_sp);

CodePudding user response:

You can't cast shared_ptr<vector<Derived*>> to shared_ptr<vector<Base*>> because vector<Derived*> and vector<Base*> are two distinct types that are not related to each other.

That Derived and Base are related to each other does not matter in that case. The type you create with std::vector<Derived*> and std::vector<Base*> are created from the class templated std::vector, so it is only the inheritance given by the std::vector class template that is relevant here.

But in this way I create another vector. And two shared_ptr manage two different vecotr.

You could think about creating a view on your original vector<Derived*> container.

CodePudding user response:

A cast is not possible, because even though Derived inherits Base, the classes vector<Derived*> and vector<Base*> are completely separate classes with no relationship at all.

If you want a vector<Base*> from a vector<Derived*>, it is possible but you need to convert the pointers yourself. And you get a separate vector of course.

std::vector<Derived*> source;

// Don't use this, use the version below
auto result = std::vector<Base*>(source.size());
for (std::size_t idx = 0; idx < source.size();   idx) {
    result[idx] = source[idx];
}
return result;

Or in more idiomatic C , we would simply let the constructor do the job:

auto result = std::vector<Base*>(begin(source), end(source));

Random sidenote:

  • The cast:

    (vector<Base*> *)derived_vector_sp.get(); // don't do this!
    

    This is completely illegal. There is no vector<Base*> at that location, so attempting to use one is undefined behavior. It might look like it works, then you upgrade your compiler and it crashes.

  • Using a shared_ptr in general is a code smell. It has a few good use cases, but most of the time you should be using the objects directly, or unique_ptr.

  • Especially when we talk about a std::vector which is already itself a set of pointers.

  • Related