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 );
}