How does one downcast a std::shared_ptr?
This ought to work:
if (ptr->IsChildOne())
{
SomeClientExpectingAChildOne(std::static_pointer_cast<ChildOne>(ptr));
}
The shared_ptr
equivalent of static_cast
is static_pointer_cast
, and the shared_ptr
equivalent of dynamic_cast
is dynamic_pointer_cast
.
Starting from C++11, §20.10.2.2.9 ([util.smartptr.shared.cast]) of the C++ standard specifies the equivalents of static_cast
, const_cast
and dynamic_cast
for std::shared_ptr
to be as follows:
std::static_pointer_cast
:
template <class T, class U>
shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) noexcept;
static_pointer_cast
requires static_cast<T *>(r.get())
to be well formed. If r
is empty, an empty shared_ptr<T>
is returned, otherwise returns a pointer w
sharing ownership with r
where w.get() == static_cast<T *>(r.get())
and w.use_count() == r.use_count()
.
std::const_pointer_cast
:
template <class T, class U>
shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) noexcept;
const_pointer_cast
has similar requirements and semantics to static_pointer_cast
, except that const_cast
is used instead of static_cast
.
std::dynamic_pointer_cast
:
template <class T, class U>
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) noexcept;
dynamic_pointer_cast
is a bit different as it requires dynamic_cast<T *>(r.get())
to be well formed and have well defined semantics. If dynamic_cast<T *>(r.get())
is a non-zero value, returns a pointer w
sharing ownership with r
where w.get() == dynamic_cast<T *>(r.get())
and w.use_count() == r.use_count()
, otherwise an empty shared_ptr<T>
is returned.
std::reinterpret_pointer_cast
:
For C++17, N3920 (adopted into Library Fundamentals TS in February 2014) also proposed a std::reinterpret_pointer_cast
similar to the above, which would only require reinterpret_cast<T *>((U *) 0)
to be well formed and returns shared_ptr<T>(r, reinterpret_cast<typename shared_ptr<T>::element_type *>(r.get()))
. Note N3920 also changed the wording for the other shared_ptr
casts and extended shared_ptr
to support arrays.