'reaseat shared_ptr<Derived> from function accepting shared_ptr<Derived>

I'm trying to reseat a shared_ptr of a derived class from a function that accept a shared_ptr of a base class.

This answer is relevant, but it does not cover the fact that I need to reseat the pointer so a const reference cannot be used.

Here is a MWE:

#include <memory>

class A {
};

class B : public A {
};

class C {
 public:
 void doSomethingWithA(std::shared_ptr<A>& a){
     a = std::make_shared<B>();
 }
    
};

int main()
{
  std::shared_ptr<B> b;
  C c;
  c.doSomethingWithA(b);
}

which gives the following compilation error:

 In function 'int main()':
21:23: error: no matching function for call to 'C::doSomethingWithA(std::shared_ptr<B>&)'
21:23: note: candidate is:
11:7: note: void C::doSomethingWithA(std::shared_ptr<A>&)
11:7: note:   no known conversion for argument 1 from 'std::shared_ptr<B>' to 'std::shared_ptr<A>&'

The reasoning behind the code is that there might be many derived classes and I know only at runtime which one is to be instantiated. The class C would decide to assign one of many derived types depending on what happens at runtime.

I didn't want to create several overloads of doSomethingWithA() and in general it is legal to assign a shared_ptr of a derived class to a shared_ptr of a base class, so I don't understand why the conversion is not possible.



Solution 1:[1]

You can convert between these types with std::static_pointer_cast e.g.

#include <memory>

class A {
};

class B : public A {
};

class C {
public:
    void doSomethingWithA(std::shared_ptr<A>& a) {
        a = std::make_shared<B>();
    }

};

int main()
{
    std::shared_ptr<B> b;
    C c;
    std::shared_ptr<A> a_ptr_from_b = std::static_pointer_cast<A>(b);
    c.doSomethingWithA(a_ptr_from_b);
}

There's also an std::dynamic_pointer_cast if you ever need that but in this case static will work.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1