检查一个类型是否直接派生自"enable if"上下文中的另一个类型(是其子类型)



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如何做,但是在用户代码中摆脱宏定义几乎是不可能的。

最新更新