Narek
Narek

Reputation: 39881

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

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>.

Upvotes: 8

Views: 13672

Answers (2)

Jonathan Wakely
Jonathan Wakely

Reputation: 171343

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.

Upvotes: 12

Jean-Bernard Jansen
Jean-Bernard Jansen

Reputation: 7872

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.

Upvotes: 8

Related Questions