C ++ не имеет отражения, дочернее хранилище содержит хранилище родителя, и трудно провести линию между одним подобъектом и другим. Некоторые метапрограммирования должны быть купольными, имитируя библиотеки, подобные Qt или MFC \ WF C
#include <iostream>
#include <type_traits>
#define DECLARE_CLASS(Name, ParentName) using Parent = ParentName;
#define PARENT_CLASS(Name) Name::Parent
class LibBase {
public:
DECLARE_CLASS(LibBase, void)
};
class A : public LibBase {
public:
DECLARE_CLASS(A, LibBase)
};
class B : public A {
public:
DECLARE_CLASS(B, A)
};
int main()
{
std::cout << std::boolalpha;
std::cout << std::is_same<PARENT_CLASS(B), A>::value << std::endl;
std::cout << std::is_same<PARENT_CLASS(B), LibBase>::value << std::endl;
}
Очевидно, что у этого простого подхода есть ловушка, в которой мы не получим ошибку, если класс не определен с помощью нашего макроса. и это только stati c,
Первая проблема может быть решена путем создания вложенного класса «trait» по объявлению, который получил имя на основе имени класса, переданного в DECLARE_OBJECT. Это сделало бы результат PARENT_CLASS (Name) уникальным, например,
#define DECLARE_CLASS(Name, ParentName) struct TraitsOf##Name { \
using Parent = ParentName; \
};
#define PARENT_CLASS(Name) Name::TraitsOf##Name::Parent
Вторая проблема может быть решена путем создания собственной функции RTTI в макроопределении
К сожалению, форма is_child_of<LibBase, A>::value
недостижима при это потому, что замена макроса происходит перед заменой шаблона. Возможно, какой-либо подход регистрации * stati c может быть использован для того, чтобы дать классам уникальные черты в ожидании, как это делает BOOST_TYPEOF, но избавиться от макроопределений в пользовательском коде было бы почти невозможно.