Saltar al contenido

¿Cómo realizar un dynamic_cast con un unique_ptr?

Solución:

Actualizar

Se ha aclarado la pregunta:

lo siento, no estaba claro. Quiero que la propiedad permanezca con el propietario original, la función llamada solo debe obtener una referencia a ella, no la propiedad. No busco dos punteros inteligentes para el mismo objeto.

En ese caso, la solución es simplemente:

dynamic_cast<B&>(*my_unique_ptr)

Hecho. Lanza si el yeso no tiene éxito.


Fundición shared_ptr

Para shared_ptr hay std::dynamic_pointer_cast<> (http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast)

Fundición unique_ptr

La forma más sencilla parecería:

#include <memory>

struct A { virtual ~A() = default; };
struct B : A { };

int main()
{
    std::unique_ptr<A> pa(new B);

    std::unique_ptr<B> pb(dynamic_cast<B*>(pa.release())); // DO NOT DO THIS
}

Como el comentarista señala con razón, esto puede filtrar el objeto si la conversión falla. Esa es no muy útil.

Una razón por la que el dynamic_unique_ptr_cast<> no existe podría ser que el unique_ptr type no borra el borrador. Podría ser difícil / imposible elegir una eliminación adecuada para el tipo de puntero de destino.

Sin embargo, para casos simples, puede usar algo como esto:

template <typename To, typename From, typename Deleter> 
    std::unique_ptr<To, Deleter> dynamic_unique_cast(std::unique_ptr<From, Deleter>&& p) {
        if (To* cast = dynamic_cast<To*>(p.get()))
        {
            std::unique_ptr<To, Deleter> result(cast, std::move(p.get_deleter()));
            p.release();
            return result;
        }
        return std::unique_ptr<To, Deleter>(nullptr); // or throw std::bad_cast() if you prefer
    }


auto pb = dynamic_unique_cast<B>(std::move(pa));

A menos que desee transferir la propiedad de su std::unique_ptr<T>, su función debe tomar puntero o referencia a T.

Entonces firma de Func debería ser algo como Func(DerivedSessionA*)

y luego su llamada puede verse así:

std::unique_ptr<BaseSession> ptr; // Initialize it with correct value

Func(dynamic_cast<DerivedSessionA*>(ptr.get()));

O como parece llamarlo directamente desde un método en BaseSession:

Func(dynamic_cast<DerivedSessionA*>(this));

Este es dynamic_pointer_cast de boost. La idea es bastante simple (pero ignore el borrador).

//dynamic_pointer_cast overload for std::unique_ptr
template<class T, class U> std::unique_ptr<T> dynamic_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
{
    (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );

    BOOST_STATIC_ASSERT_MSG( boost::has_virtual_destructor<T>::value, "The target of dynamic_pointer_cast must have a virtual destructor." );

    T * p = dynamic_cast<T*>( r.get() );
    if( p ) r.release();
    return std::unique_ptr<T>( p );
}
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *