On Tue, Oct 6, 2015 at 6:19 AM, Karolin Varner
Hi all!
There is the family of boost pointer cast (boost::static_pointer_cast, boost::dynamic_pointer_cast, ...) that allow a developer to write generic code by casting pointers regardless of whether they are some smart pointer (e.g. shared_ptr) or plain pointers.
However, those functions have not been implemented for unique_ptr, because they create a copy of their pointer and unique_pointers can not be copied.
In my case I still needed to cast some unique_ptr and since it's ok to move unique_ptrs I wrote a function that does exactly that. The code is below – Comments are very, very welcome. It works for my case, but I am sure it is not as generic and safe as it should be ;) . Specifically, for a library, it should be made to work on any kind of smart/plain pointer. Not just unique_ptr.
Is there any interest to include a boost::static_moving_pointer_cast and the other types of casts in boost?
Best, Karolin
/// Dynamic cast a unique_ptr. /// /// This function shall move the pointer in in_ptr, into /// a new unique_pointer of the desire type, dynamic_casting /// it in the process. /// In given pointer shall contain a NULL pointer afterwards. /// /// If unsuccessful, function shall throw an error and leave /// in_ptr unmodified. /// /// This behaviour contrasts a bit with the behaviour of the /// normal dynamic_cast: /// 1. dynamic_cast copies objects, this moves them since /// unique_pointers can not be copied. /// 2. dynamic_cast returns a NULL pointer if the pointer to /// cast is of an incomplete type, this throws /// incomplete_cast instead, to ease error handling. /// /// @tparam T The type to convert to (as non-pointer) /// @tparam F The type to convert from (as non-pointer) /// @param in_ptr The unique_ptr to cast /// @return in_ptr, cast to the desired type template
std::unique_ptr<T> dynamic_moving_pointer_cast(std::unique_ptr<F> &in_ptr) {
The argument should be &&, not &, or else you won't be able to bind to r-values.
// Exception safety: If The dynamic cast throws an error, // or of we throw incomplete_cast, in_ptr will still be // unmodified T *plain_out_ptr = dynamic_cast
(in_ptr.get()); if (plain_out_ptr == NULL && in_ptr.get() != NULL) throw incomplete_cast(); // Exception safety: Both operations are noexcept in_ptr.release(); return std::unique_ptr<T>(plain_out_ptr); }
It would nice to generalize this to arbitrary smart pointers, because even for copyable smart pointers (e.g. shared_ptr, intrusive_ptr), there is interest in "cast moving" to avoid needlessly touching the reference count in such case (better performance). However, I am not sure we can implement this non-intrusively. -- François