2

I have a shared pointer storing a base class, like this:

std::shared_ptr<Base> baseClassPointer;

How do I check whether it is currently holding an instance of an SuperClassA? Where:

public class SuperClassA : public Base {} // There can be many other superclasses

I've tried something like below, but obviously did not work:

std::is_same<SuperClassA, decltype(baseClassPointer->get())>::value;
cigien
  • 57,834
  • 11
  • 73
  • 112
Yves Calaci
  • 1,019
  • 1
  • 11
  • 37
  • 1
    Does this answer your question? [dynamic\_cast across a shared\_ptr?](https://stackoverflow.com/questions/23795265/dynamic-cast-across-a-shared-ptr) – kmdreko Jul 13 '20 at 23:55
  • Nope. I have stated nowhere I want to cast the values. Thank you, though. – Yves Calaci Jul 14 '20 at 00:05
  • 1
    The linked Q&A doesn't *directly* address your question, but `dynamic_cast` will return null if the pointer's dynamic type is not the type you are looking for. The link just shows you how to do that with `shared_ptr`. – kmdreko Jul 14 '20 at 00:23
  • Honestly, I did not think about it. I've got it working before reading your last comment but it looks like I've got a better answer from your comment. Thank you! – Yves Calaci Jul 14 '20 at 00:33

1 Answers1

1

For those interested on knowing how I did this, here goes:

bool same = typeid(SuperClassA) == typeid(*baseClassPointer->get());

Or:

bool same = std::dynamic_pointer_cast<SuperClassA>(baseClassPointer).use_count() > 0;

Or even better (performance-wise):

bool same = dynamic_cast<SuperClassA*>(baseClassPointer->get()) != nullptr;
Yves Calaci
  • 1,019
  • 1
  • 11
  • 37
  • You said in comments that you don't want to cast values, but you consider `dynamic_pointer_cast` is preferable? You do realise you are contradicting yourself? The effect of `dynamic_pointer_cast` is the same as `dynamic_cast`, except that the result is wrapped in a `shared_ptr`. – Peter Jul 14 '20 at 00:45
  • The question was all about checking the underlying type of a `std::shared_ptr<>`. The comment mentioned a `how to cast shared pointers` question, while also marking my question as a duplicate. Later on I figured out that checking the nullability of casted values would also work. The answer also shows how to do this without casting, although I found that the other solution (using casts) had better readability. – Yves Calaci Jul 14 '20 at 01:14
  • 1
    `typeid()` is not the way to handle this. Definitely use `dynamic_cast` or `dynamic_pointer_cast` only. I would go with `dynamic_cast`, eg: `bool same = (dynamic_cast(baseClassPointer.get()) != nullptr);`, as you don't really need the overhead of `std::dynamic_pointer_cast` creating a temporary `shared_ptr` object to increment the refcount just to immediately decrement it. – Remy Lebeau Jul 14 '20 at 01:29
  • @RemyLebeau yea, indeed. I was really thinking about this. I'll update my answer to cover this. By the way, I'm a big fan of yours, seriously, ever since I started developing a bunch of years ago, with Borland C++ Builder. Just thought you'd like to know this :) – Yves Calaci Jul 14 '20 at 02:15
  • Actually, Remy. Aren't there better ways to achieve type checking? Like `std::is_same` or something? Isn't `try-casting` still expensive here? – Yves Calaci Jul 14 '20 at 02:18
  • @Henri `dynamic_pointer_cast` makes more sense only if you are going to actually use the casted pointer to access the object. `dynamic_cast` makes more sense for just a `nullptr` check. `is_same` is a compile-time check, so you can't use it on a pointer to a polymorphic object whose actual type is not known until runtime, hence the need for `dynamic_(pointer_)cast` – Remy Lebeau Jul 14 '20 at 03:26