Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::static_pointer_cast vs static_cast<std::shared_ptr<A>>

Tags:

c++

c++11

I have a class hierarchy and in it B is derived from A like this:

class A : public std::enable_shared_from_this<A>
{

};

class B : public A
{
   void f()
   {
        // the code below compiles
        std::shared_ptr<B> copyOfThis = std::static_pointer_cast<B>(shared_from_this()); 
        // the code below does not
        std::shared_ptr<B> copyOfThis = static_cast<std::shared_ptr<B>>(std::make_shared<A>(shared_from_this()));
}
};

So actually I want to understand why I cannot use static_castto cast a shared_ptr of parent class to child class when it is actually contains this of child.

EDIT: Look at this question: Polymorphic smart pointer usage Here I have asked why shared pointer of child can be casted on shared pointer of parent. And the answer is there is a template constructor. See details in the question. So why this constructor does not help for casting even if there is no relationship between shared_ptr<A> and shared_ptr<B>.

like image 598
Narek Avatar asked Dec 02 '15 17:12

Narek


2 Answers

You can't cast shared_ptr<A> to shared_ptr<B> because there is no inheritance relationship between the types. For the same reason you can't cast vector<A> to vector<B>.

Instantiating a class template with related types does not make the template instantiations also related.

The shared_ptr<T>(const shared_ptr<Y>&) constructor doesn't help because it is only usable if Y* is implicitly convertible to T*, i.e. it is there to support the same pointer conversions as would happen implicitly, like B* to A*, not A* to B*.

What you can do is this:

shared_ptr<A> thisA = shared_from_this();
shared_ptr<B> thisB(thisA, static_cast<B*>(thisA.get()));

This creates a shared_ptr<B> that shares ownership with thisA, and holds the pointer static_cast<B*>(thisA.get())

That is exactly what static_pointer_cast<B>(thisA) does, but the aliasing constructor used above was added to shared_ptr later, so didn't exist when static_pointer_cast was invented, and it is also much less clear what it is doing. static_pointer_cast is much more expressive. If you want to perform a static cast on the pointer types, use static_pointer_cast.

like image 77
Jonathan Wakely Avatar answered Nov 09 '22 11:11

Jonathan Wakely


Long story short: std::shared_ptr<A> is not a parent of std::shared_ptr<B>. That is the whole point of static_pointer_cast existence.

like image 6
Jean-Bernard Jansen Avatar answered Nov 09 '22 11:11

Jean-Bernard Jansen