If I got objects a
and b
, how do I determine if the class of a
inherits from the class of b
?
Background: I got a C++ library for which I would like to write a Python bindings generator. That library provides a set of classes derived from a common base class. For the Python bindings, I need a list of functions for all classes. I got a list of methods through nm -D myLibrary.so
, but that is missing methods of classes inherited e.g. in the style of
template<class WrappedClass>
class Wrapper: public WrappedClass {
public:
// ...
};
typedef Wrapper<ClassA> ClassB;
. So I got all functions of classes like ClassA
and would just like to know to which ClassB
they belong.
I can get a list of names of all available classes from the library on runtime, and can get objects with those types via a factory function that accepts class names and gives objects of that type. So the last piece is to dynamically determine which classes like ClassB
belong to which classes like ClassA
. Therefore the question.
PS: I could in principle write a C++ code generator that generates test code that is then compiled against the library to determine which classes inherit from which others. That would come to the high cost of not being able to compile my code along with the library but requiring a second compilation. Since I have nearly everything apart from this problem here to circumvent that, I hope very much that there is a different solution.
PPS: I was told to use decltype
in the comments. That does not work:
#include <iostream>
#include <type_traits>
struct A {};
struct B : A {};
int main() {
A* a = new A();
A* b = new B();
std::cout << std::boolalpha;
std::cout << "A, B: " << std::is_base_of<A,B>::value << std::endl;
std::cout << "a, b: " << std::is_base_of<decltype(a),decltype(b)>::value << std::endl;
std::cout << "*a, *b: " << std::is_base_of<decltype(*a),decltype(*b)>::value << std::endl;
std::cout << "a., B: " << std::is_base_of<decltype(a),B>::value << std::endl;
std::cout << "*a., B: " << std::is_base_of<decltype(*a),B>::value << std::endl;
return 0;
}
}
yields
A, B: true
a, b: false
*a, *b: false
a., B: false
*a., B: false
PPPS: One answer suggested to use
std::is_base_of_v<std::decay_t<decltype(*a)>, std::decay_t<decltype(*b)>>
. I can't get it to work:
#include <iostream>
#include <type_traits>
struct A {};
struct B : A {};
int main() {
A* a = new A();
A* b = new B();
std::cout << std::boolalpha;
std::cout << "A, B: " << std::is_base_of<A,B>::value << std::endl;
std::cout << "B, A: " << std::is_base_of<B,A>::value << std::endl;
std::cout << "*a, *b: " << std::is_base_of<std::decay_t<decltype(*a)>, std::decay_t<decltype(*b)>>::value << std::endl;
std::cout << "*b, *a: " << std::is_base_of<std::decay_t<decltype(*b)>, std::decay_t<decltype(*a)>>::value << std::endl;
return 0;
}
yields:
A, B: true
B, A: false
*a, *b: true
*b, *a: true