2

There is is_base_of to check if a class A is a base class of B. But what if I don't have the type of a variable?

Let's say I have five classes A, B, C, D and E, and D and E are derived from both A and B respectively. C is only derived from A. Now I have a pointer to A and I want to know if I can cast the pointer to B. In this case I want to know if my A pointer points to a D or E object, so that I can cast the pointer to a B object.

I tried the following which did not work.

void foo(const std::shared_ptr<A> & ptr) {
    if (std::is_base_of<B, decltype(*ptr)>::value) {
        doSomething(std::static_pointer_cast<B>(ptr));
    }
}

Edit: foo is not a template function, A and B are just placeholders for my existing classes.

gartenriese
  • 4,131
  • 6
  • 36
  • 60
  • 4
    to narrow, use `dynamic_cast`. It checks for you (will throw `std::bad_cast `) – Red Alert Mar 26 '15 at 19:53
  • @RedAlert Exactly ! Provided there's at least one virtual function. – Christophe Mar 26 '15 at 19:54
  • 3
    Well, `std::dynamic_pointer_cast`, and it'll be a null pointer returned, not `std::bad_cast` thrown in case it doesn't work. But yes, this requires a runtime check. – Wintermute Mar 26 '15 at 19:56
  • 2
    `dynamic_cast` also works with pointers, and returns null on failure. It is only when casting references that `std::bad_cast` is thrown, since a reference cannot be null. – Remy Lebeau Mar 26 '15 at 19:57
  • @Wintermute: Thanks, std::dynamic_pointer_cast works! – gartenriese Mar 26 '15 at 20:01
  • possible duplicate of [Check if class is derived from a specific class (compile, runtime both answers available)](http://stackoverflow.com/questions/18099241/check-if-class-is-derived-from-a-specific-class-compile-runtime-both-answers-a) – Julian Mar 26 '15 at 20:07

1 Answers1

-1

If foo is a template function, you must define B before A in the template parameter list. You will also have to specifically type B when calling foo.

If your code is provided as is, then you must make foo a template with A being an argument for the template.

Example:

#include <memory>

template <typename B>
void doSomething(std::shared_ptr<B> &ptr)
{

}

template <typename B, typename A>
void foo(const std::shared_ptr<A> & ptr) {
    if (std::is_base_of<B, decltype(*ptr)>::value) {
        doSomething(std::static_pointer_cast<B>(ptr));
    }
}

class A { };

class B : public A { };

int _tmain(int argc, _TCHAR* argv[])
{
    std::shared_ptr<A> a(new B);

    foo<B>(a);

    return 0;
}
Matthew
  • 771
  • 6
  • 15