Question

Consider a class D derived from a class B, and a sb instance of std::shared_ptr<B>. Once I have verified that dynamic_cast<D*>(sb.get()) is possible, I want to create a proper std::shared_ptr<D> from sb. In other words, I'd like to implement a kind of dynami_cast<> between shared_ptr's. How can I do this in a clean way? A possible solution would be to make B derive from std::enable_shared_from_this and to use shared_from_this() from the (casted) pointer to D. But this would require a change in the definition of type B. Are there better ideas? Is there anything in boost?

Was it helpful?

Solution

Are you aware of std::dynamic_pointer_cast?

http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast

OTHER TIPS

As other answers pointed out, the standard library already provides what you want, but for completeness, implementing it is easy:

template<typename To, typename From>
  std::shared_ptr<To>
  dynamic_pointer_cast(const std::shared_ptr<From>& from)
  {
    return std::shared_ptr<To>(from, dynamic_cast<To*>(from.get()));
  }

This uses the aliasing constructor to create a new shared_ptr of a different type that shares ownership with from, so they share the same reference count even though they own different pointers (in this case the pointers they own are different types but point to the same object, but that doesn't have to be true.)

This isn't quite right, because if the cast fails (returning a null pointer) you get a shared_ptr that stores a null pointer, but shares ownership with a non-null pointer. To handle that we need a small tweak:

template<typename To, typename From>
  std::shared_ptr<To>
  dynamic_pointer_cast(const std::shared_ptr<From>& from)
  {
    if (auto p = dynamic_cast<To*>(from.get()))
      return std::shared_ptr<To>(from, p);
    return {};
  }

Now we return an empty shared_ptr<To> if the cast fails, which is a better match to the behaviour of dynamic_cast<To*>.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top