Boost logo

Boost :

Subject: [boost] [smart_ptr] Moving cast for unique_ptr
From: Karolin Varner (karo_at_[hidden])
Date: 2015-10-06 06:19:55


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<typename T, typename F>
std::unique_ptr<T> dynamic_moving_pointer_cast(std::unique_ptr<F> &in_ptr) {
  // 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<F*>(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);
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk