You can define your own SmartPtrCast template function which does something like:
template <typename DestT, typename SrcT>
inline SmartPtr<DestT> SmartPtrCast(const SmartPtr<SrcT> &src)
{
return SmartPtr<DestT>(static_cast<DestT*>(src.get()));
}
Then, all you have to do cast gracefully from A to B is:
SmartPtr<B> b = SmartPtrCast<B>(doSomething(foo));
Caveat Emptor:
This will only work if the smart pointer returned by doSomething()
is referenced somewhere else, and is not destroyed when it goes out of scope. Judging by your example, this is the case, but it's still not as graceful, and it should be noted that the two pointers won't share their reference counting (so if one of them gets destroyed, the second will lose its data).
A better solution is either to detach one of the pointers (if SmartPtr has a detach method). An even better solution (if you don't have a detach method or if you want to share the reference count) is to use a wrapper class:
template <typename SrcT, typename DestT>
class CastedSmartPtr
{
private:
SmartPtr<SrcT> ptr;
public:
CastedSmartPtr(const SmartPtr<SrcT>& src)
{
ptr = src;
}
DestT& operator* () const
{
return *(static_cast<DestT*> >(ptr.get()));
}
DestT* operator->() const
{
return static_cast<DestT*> >(ptr.get());
}
DestT* get() const
{
return static_cast<DestT*> >(ptr.get());
}
}
template <typename DestT, typename SrcT>
inline SmartPtr<DestT> SmartPtrCast(const SmartPtr<SrcT>& src)
{
return CastedSmartPtr<SrcT, DestT>(src);
}
This will use a SmartPtr
internally (so reference count is properly shared) and static_cast
it to internally to DestT
(with no performance impact). If you want to use dynamic_cast
, you can do it only once, in the constructor, to avoid unnecessary overhead. You may also want to add additional method to the wrapper such as copy constructor, assignment operator, detach method, etc.
boost::shared_ptr<A> b = boost::dynamic_ptr_cast<B>(foo)
Look for something like that. – Overcast