dynamic_pointer_cast
is only implemented for std::shared_ptr
. I need the same functionality for unique pointers.
The wrinkle is that dynamic_casting a pointer could fail (yield nullptr
), so what do we want to happen then? I decided that in that case I would like the original pointer to remain unchanged.
I have implemented the following:
template< typename T, typename S >
inline std::unique_ptr<T> dynamic_pointer_cast(std::unique_ptr<S>&& ptr_)
{
T* const converted_ptr = dynamic_cast<T*>(ptr_.get());
if (!converted_ptr)
// cast failed, leave input untouched, return nullptr
return nullptr;
// cast succeeded, clear input, return casted ptr
ptr_.release();
return std::unique_ptr<T>(converted_ptr);
}
Testing code:
#include <memory>
int main(int argc, char **argv)
{
std::unique_ptr<Base> basePtr = std::make_unique<Derived1>();
// this should fail, basePtr should remain non-empty, return should be empty
auto deriv2Ptr = dynamic_pointer_cast<Derived2>(std::move(basePtr));
// this should succeed, basePtr should become empty, return should be non-empty
auto deriv1Ptr = dynamic_pointer_cast<Derived1>(std::move(basePtr));
return 0;
}
Is this safe? Does the interface make sense? For the latter question: I decided to take an R-value ref so users have to write std::move
, denoting pointer will be emptied. But then it may not if the cast fails... Normal ref is the other option, but then it's less clear at the call site that the unique_ptr
will likely be cleared.