Sie können Ihre eigene SmartPtrCast-Vorlagefunktion definieren, die etwa so funktioniert:
template <typename DestT, typename SrcT>
inline SmartPtr<DestT> SmartPtrCast(const SmartPtr<SrcT> &src)
{
return SmartPtr<DestT>(static_cast<DestT*>(src.get()));
}
Dann müssen Sie sich nur noch elegant von A nach B werfen:
SmartPtr<B> b = SmartPtrCast<B>(doSomething(foo));
Caveat Emptor: Dies funktioniert nur, wenn der Smart Pointer, der von doSomething()
wird an anderer Stelle referenziert und wird nicht zerstört, wenn sie den Geltungsbereich verlässt. Nach Ihrem Beispiel zu urteilen, ist dies der Fall, aber es ist immer noch nicht so anmutig, und es sollte beachtet werden, dass die beiden Zeiger ihre Referenzzählung nicht teilen (wenn also einer von ihnen zerstört wird, verliert der zweite seine Daten).
Eine bessere Lösung besteht darin, einen der Zeiger zu trennen (wenn SmartPtr eine Trennungsmethode hat). Eine noch bessere Lösung (wenn Sie keine detach-Methode haben oder wenn Sie die Anzahl der Verweise gemeinsam nutzen wollen) ist die Verwendung einer Wrapper-Klasse:
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);
}
Dabei wird ein SmartPtr
intern (damit die Referenzzählung ordnungsgemäß gemeinsam genutzt wird) und static_cast
es intern zu DestT
(ohne Auswirkungen auf die Leistung). Wenn Sie Folgendes verwenden möchten dynamic_cast
können Sie dies nur einmal, im Konstruktor, tun, um unnötigen Overhead zu vermeiden. Möglicherweise möchten Sie dem Wrapper auch zusätzliche Methoden hinzufügen, z. B. einen Kopierkonstruktor, einen Zuweisungsoperator, eine Abtrennmethode usw.