Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is this code safe? cast a std::vector<Derived*> to std::vector<Base*>

Basically I've a class A and a class B : public A.

And I'd like to cast a std::shared_ptr<std::vector<A*> to a std::shared_ptr<std::vector<B*>

The problem is std::vector<B> doesn't inherit from std::vector<A>, and the smart_ptr neither. So I do a horrible cast:

  std::shared_ptr<VectorA> vector_a = * ((std::shared_ptr<VectorA>*)&vector_b);

The code compiles and runs there, but it is safe? http://liveworkspace.org/code/3dQTz1$0

like image 412
ablm Avatar asked Dec 13 '25 13:12

ablm


2 Answers

This is a horrible solution. When you cast a vector of objects of one type to the other you can expect all kind of incorrect/undefined behaviour.

You should use vector of std::shared_ptr<A> from the beginning and initialize them with pointers to objects of type B there.

If it is not possible you can create a new vector holding std::weak_ptr<A> to avoid managing these objects twice.

like image 81
Rafał Rawicki Avatar answered Dec 15 '25 02:12

Rafał Rawicki


Don't do that.

Consider that a vector of (pointers to) B is not a vector of (pointers to) A, or to be more precise, is not a universally valid substitution for a vector of (pointers to) A; thus, there is a good reason why you cannot perform such a conversion.

Although it is true that all you have in a vector of B is indeed a set of objects which are (also( instances of A, consider the following algorithm:

void f(vector<A>& v)
{
    A a;
    v.push_back(a);
}

Now imagine you invoke f() with a vector of B. That would be an attempt to add an instance of a class that is not B to a collection which is supposed to contain only elements of type B.

The solution here is to make the code which accepts only a vector<A> flexible enough to work also on a vector<B>. In other words, you need to make it a template. For instance, your template could accept as arguments only vectors of a type which is derived from A. This is quite easy to enforce with some SFINAE techniques and type traits such as std::is_base_of.

like image 34
Andy Prowl Avatar answered Dec 15 '25 03:12

Andy Prowl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!