C++ 有is_base_of<Base,Derived>
。但是,这也包括"祖父母"类型。
有没有办法获得is_child_of<Parent,Child>
功能?目的是在 SFINAE 上下文中使用类型作为哨兵"接口"标记,而不受可能会或可能不会添加到父类型的哨兵的影响。
也就是说,以下输出应为"真、假"。(带有is_base_of
的输出是"true,true"。
#include <iostream>
#include <type_traits>
class A {};
class B : A {};
class C : B {};
int main()
{
std::cout << std::boolalpha;
std::cout << "a2b: " << std::is_child_of<A, B>::value << 'n';
std::cout << "a2c: " << std::is_child_of<A, C>::value << 'n';
}
C++没有反射,子对象的存储包含父对象的存储,并且很难在一个子对象和另一个子对象之间画一条线。一些元编程必须是圆顶的,模仿类似于Qt或MFC\WFC的库
。#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;
}
显然,这种简单的方法存在陷阱,即如果不使用我们的宏定义类,我们就不会出错,并且它只是静态的,
第一个问题可以通过声明创建一个"trait"嵌套类来解决,该类根据传递给DECLARE_OBJECT的类名获取名称。 这将使PARENT_CLASS(名称(的结果唯一,例如
#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
是无法实现的,因为宏替换发生在模板替换之前。也许可以使用一些静态注册方法来为类提供独特的特征,等待BOOST_TYPEOF如何做,但是在用户代码中摆脱宏定义几乎是不可能的。