# std::static_pointer_cast, std::dynamic_pointer_cast, std::const_pointer_cast, std::reinterpret_pointer_cast

From cppreference.com
< cpp‎ | memory‎ | shared ptr

Defined in header `<memory>` |  |
template< class T, class U > std::shared_ptr <T> static_pointer_cast( const std::shared_ptr <U>& r ) noexcept; | (1) | (since C++11)
template< class T, class U > std::shared_ptr <T> static_pointer_cast( std::shared_ptr <U>&& r ) noexcept; | (2) | (since C++20)
template< class T, class U > std::shared_ptr <T> dynamic_pointer_cast( const std::shared_ptr <U>& r ) noexcept; | (3) | (since C++11)
template< class T, class U > std::shared_ptr <T> dynamic_pointer_cast( std::shared_ptr <U>&& r ) noexcept; | (4) | (since C++20)
template< class T, class U > std::shared_ptr <T> const_pointer_cast( const std::shared_ptr <U>& r ) noexcept; | (5) | (since C++11)
template< class T, class U > std::shared_ptr <T> const_pointer_cast( std::shared_ptr <U>&& r ) noexcept; | (6) | (since C++20)
template< class T, class U > std::shared_ptr <T> reinterpret_pointer_cast( const std::shared_ptr <U>& r ) noexcept; | (7) | (since C++17)
template< class T, class U > std::shared_ptr <T> reinterpret_pointer_cast( std::shared_ptr <U>&& r ) noexcept; | (8) | (since C++20)

Creates a new instance of std::shared_ptr whose stored pointer is obtained from `r`'s stored pointer using a cast expression.

If `r` is empty, so is the new `shared_ptr` (but its stored pointer is not necessarily null). Otherwise, the new `shared_ptr` will share ownership with the initial value of `r`, except that it is empty if the `dynamic_cast` performed by `dynamic_pointer_cast` returns a null pointer.

Let `Y` be typename std::shared_ptr <T>::element_type, then the resulting std::shared_ptr's stored pointer will be obtained by evaluating, respectively:

1-2) static_cast<Y*>(r.get()).
3-4) dynamic_cast<Y*>(r.get()) (If the result of the `dynamic_cast` is a null pointer value, the returned `shared_ptr` will be empty.)
5-6) const_cast<Y*>(r.get()).
7-8) reinterpret_cast<Y*>(r.get())

The behavior of these functions is undefined unless the corresponding cast from `U*` to `T*` is well formed:

1-2) The behavior is undefined unless static_cast<T*>((U*)nullptr) is well formed.
3-4) The behavior is undefined unless dynamic_cast<T*>((U*)nullptr) is well formed.
5-6) The behavior is undefined unless const_cast<T*>((U*)nullptr) is well formed.
7-8) The behavior is undefined unless reinterpret_cast<T*>((U*)nullptr) is well formed.

After calling the rvalue overloads (2,4,6,8), `r` is empty and r.get() == nullptr, except that `r` is not modified for `dynamic_pointer_cast` (4) if the dynamic_cast fails. | (since C++20)

### Parameters

r | - | The pointer to convert

### Notes

The expressions std::shared_ptr <T>(static_cast<T*>(r.get())), std::shared_ptr <T>(dynamic_cast<T*>(r.get())) and std::shared_ptr <T>(const_cast<T*>(r.get())) might seem to have the same effect, but they all will likely result in undefined behavior, attempting to delete the same object twice!

### Possible implementation

First version

    template< class T, class U >
    std::shared_ptr<T> static_pointer_cast( const std::shared_ptr<U>& r ) noexcept
    {
        auto p = static_cast<typename std::shared_ptr<T>::element_type*>(r.get());
        return std::shared_ptr<T>(r, p);
    }

Second version

    template< class T, class U >
    std::shared_ptr<T> dynamic_pointer_cast( const std::shared_ptr<U>& r ) noexcept
    {
        if (auto p = dynamic_cast<typename std::shared_ptr<T>::element_type*>(r.get())) {
            return std::shared_ptr<T>(r, p);
        } else {
            return std::shared_ptr<T>();
        }
    }

Third version

    template< class T, class U >
    std::shared_ptr<T> const_pointer_cast( const std::shared_ptr<U>& r ) noexcept
    {
        auto p = const_cast<typename std::shared_ptr<T>::element_type*>(r.get());
        return std::shared_ptr<T>(r, p);
    }

Fourth version

    template< class T, class U >
    std::shared_ptr<T> reinterpret_pointer_cast( const std::shared_ptr<U>& r ) noexcept
    {
        auto p = reinterpret_cast<typename std::shared_ptr<T>::element_type*>(r.get());
        return std::shared_ptr<T>(r, p);
    }

### Example

Run this code

    #include <iostream>
    #include <memory>

    struct Base
    {
        int a;
        virtual void f() const { std::cout << "I am base!\n";}
        virtual ~Base(){}
    };

    struct Derived : Base
    {
        void f() const override
        { std::cout << "I am derived!\n"; }
        ~Derived(){}
    };

    int main(){
        auto basePtr = std::make_shared<Base>();
        std::cout << "Base pointer says: ";
        basePtr->f();

        auto derivedPtr = std::make_shared<Derived>();
        std::cout << "Derived pointer says: ";
        derivedPtr->f();

        // static_pointer_cast to go up class hierarchy
        basePtr = std::static_pointer_cast<Base>(derivedPtr);
        std::cout << "Base pointer to derived says: ";
        basePtr->f();

        // dynamic_pointer_cast to go down/across class hierarchy
        auto downcastedPtr = std::dynamic_pointer_cast<Derived>(basePtr);
        if(downcastedPtr)
        {
            std::cout << "Downcasted pointer says: ";
            downcastedPtr->f();
        }

        // All pointers to derived share ownership
        std::cout << "Pointers to underlying derived: "
                << derivedPtr.use_count()
                << "\n";
    }

Output:

    Base pointer says: I am base!
    Derived pointer says: I am derived!
    Base pointer to derived says: I am derived!
    Downcasted pointer says: I am derived!
    Pointers to underlying derived: 3

### See also

(constructor) | constructs new `shared_ptr` (public member function)

Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/memory/shared_ptr/pointer_cast&oldid=107300"