C++: using typeinfo to test class inheritance
Asked Answered
E

3

4

I have a pointer to a polymorphic type, p. I also have a type_info for a class somewhere in the same hierarchy, ti.

If I just compare the typeid(*p) == ti, then I can test at runtime whether the pointer is pointing to a direct instance of that class.

Is there a similar way to use C++'s RTTI to test whether *p inherits from that class?

Earlie answered 15/7, 2012 at 10:9 Comment(0)
B
2

There's no way to do this in standard C++ alone. If you're using an implementation that has the Itanium C++ ABI1 you can do this though, for example:

#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
#include <memory>

class base {
protected:
  base() {
  }
public:
  static bool check(const std::type_info& p) {
    // Find the real type_info for single inheritance non virtual 
    const __cxxabiv1::__si_class_type_info* test = dynamic_cast<const __cxxabiv1::__si_class_type_info*>(&p);
    return test ? typeid(base) == *test->__base_type : false;
  }

  virtual ~base() {}
};

class der : public base {
};

class foo {};

int main() {
  der d;
  foo f;

  std::cout << base::check(typeid(d)) << "\n";
  std::cout << base::check(typeid(f)) << "\n";
}

Here this works because the type has a single, non-virtuallly inherited base. You can support more cases though with care and similar dynamic_casts.

Whilst this is possible under these certain circumstances I think you're solving the wrong problem though - a solution based around a std::map is more portable and avoids relying on implementation details like this.

1 confusingly named, it's a surprisingly large compiler/architecture list, not just Itanium

Boat answered 15/7, 2012 at 11:50 Comment(2)
I don't, alas. (I don't even have STL.) I thought this would be the answer, but couldn't find any definitive statement such. Oh, well, custom RTTI it is, then...Earlie
@DavidGiven - It might be that your implementation has a similar ABI.Boat
G
1

Yes, you can use dynamic_cast<> for that purpose. If you try to cast to Base*, it performs a runtime check to see if your class really is derived from Base (or directly is a Base). In case of failure, dynamic_cast<> returns nullptr. Example :

struct Base {
     virtual ~Base() {}
};

struct AnotherBase {
     virtual ~Base() {}
};

struct Derived : Base {};


Base * basePtr = new Base();
Base * derivedPtr = new Derived();
AnotherBase * anotherBasePtr = new Base();

// is derivedPtr a pointer to a class derived from AnotherBase ?
AnotherBase* test2 = dynamic_cast<AnotherBase*>(derivedPtr);    // test2 == nullptr

// is basePtr a pointer to a class derived from Derived ?
Derived * test3 = dynamic_cast<Derived*>(basePtr);    // test3 == nullptr

Side nodes :

  • if dynamic_cast<> is used to convert pointers, it returns either nullptr or the converted pointer.

  • BUT when dynamic_cast<> is used to convert references it throws an exception in case of failure.

  • The runtime check of dynamic_cast<> is only possible for polymorphic types. If your Base doesn't contain any virtual function (= non polymorphic), it won't be possible to safely convert a Base* to a Derived*.

Gillette answered 15/7, 2012 at 10:51 Comment(5)
Unfortunately dynamic_cast<> only works if I know what the class is at compile time. I don't know that: all I have is a type_info for the class. I don't actually need to cast the pointer, only determine whether the object being pointed at inherits from the class for which I have the type_info.Earlie
@DavidGiven I misunderstood your question. So no, you cannot. But you can create a map<typeinfo*,dynamic_cast_wrapper> allowing you to do what you want. Tell me if you're interested & I'll post a detailed answer.Viridi
That's all right, thanks; I already have a plan for custom RTTI to do this, but wanted to check to see whether I really needed it first.Earlie
I just figured out that my suggestion was partly wrong anyway. It is not easy to properly wrap a dynamic_cast like I suggested !Viridi
Long time ago this was asked .. i am interested if the new C++ standart have some extensions which may cover this question ?Eliga
D
0

Great thanks to Flexo. I have been researching the C++ ABI for a quite while. After a hour of work, I've got this demo: http://pastebin.com/j7DYY5ej. Here is a code to check inheritance in some cases. I've implemented operators ==, !=, <, >, <=, >= for the types. I'm planning to improve this way of type equation and to use it in my project. Note that I used G++ 4.8 under Linux.

Daunt answered 27/7, 2012 at 19:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.