I have two shared_ptrs of the classes U and T where T is the base of U.
It is no problem to do an implicit conversion from shared_ptr<U>
to shared_ptr<T>
.
But is is also possible to do a conversion from shared_ptr<T>
to shared_ptr<U>
?
I tried the sugested solution:
class T {
public:
virtual ~T() {}
protected:
void fillData() = 0;
};
class Timpl : public T
{
public:
virtual ~Timpl() {}
protected:
virtual void fillData() = 0;
};
class U : public Timpl {
public:
virtual ~U() {}
protected:
virtual void fillData() {...} // fill
};
typedef shared_ptr<T> TPtr
typedef shared_ptr<U> UPtr
TPtr tp = std::make_shared<U>();
UPtr up = std::static_pointer_cast<U>(tp); //<-- error here :
error: no matching function for call to 'static_pointer_cast(TPtr)'
note: template std::__shared_ptr<_Tp1, _Lp> std::static_pointer_cast(const std::__shared_ptr<_Tp2, _Lp>&)
note: template argument deduction/substitution failed:
note: 'TPtr {aka boost::shared_ptr}' is not derived from 'const std::__shared_ptr<_Tp2, _Lp>'
Solution for this issue:
mixing of std::shared_ptr
with boost::shared_ptr
is no good idea.
In short, you can easily and efficiently convert a std::unique_ptr to std::shared_ptr but you cannot convert std::shared_ptr to std::unique_ptr .
By moving the shared_ptr instead of copying it, we "steal" the atomic reference count and we nullify the other shared_ptr . "stealing" the reference count is not atomic, and it is hundred times faster than copying the shared_ptr (and causing atomic reference increment or decrement).
A null shared_ptr does serve the same purpose as a raw null pointer. It might indicate the non-availability of data. However, for the most part, there is no reason for a null shared_ptr to possess a control block or a managed nullptr .
All the instances point to the same object, and share access to one "control block" that increments and decrements the reference count whenever a new shared_ptr is added, goes out of scope, or is reset. When the reference count reaches zero, the control block deletes the memory resource and itself.
Yes, use static_pointer_cast
:
#include <memory>
struct T { virtual ~T() {} };
struct U : T {};
std::shared_ptr<T> pt = std::make_shared<U>(); // *pt is really a "U"
auto pu = std::static_pointer_cast<U>(pt);
There's also a matching std::dynamic_pointer_cast
which returns a null pointer if the conversion isn't possible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With