用C ++ 17可以检测一个结构体/类是否有任何基数?

我需要一个types特征,如果给定的types是从任何东西派生的,那么这个特征将是真的,否则就是假的。

例如:

template<class T> struct is_inherit //... logic of inheritance detection ; template<class T> void AppLogic(){ if constexpr(is_inherit<T>::value) { puts("T has base"); //... } else { puts("T doesn't have base"); //... } } struct A {}; struct C {}; struct B: C {}; int main() { AppLogic<A>(); // print: T doesn't have base AppLogic<B>(); // print: T has base } 

是否有可能以某种方式实现“is_inherit”特质结构?


为什么?

我正在开发Windows x64的手动堆栈框架生成器。 根据https://docs.microsoft.com/en-us/cpp/build/return-values-cpp文档,如果input:

  • 长度为1,2,4,8,16,32或64位;
  • 没有用户定义的构造函数,析构函数或复制赋值运算符;
  • 没有私人或受保护的非静态数据成员;
  • 没有引用types的非静态数据成员;
  • 没有基类;
  • 没有虚拟function;
  • 没有数据成员也不符合这些要求;

那么它的返回值是在RAX寄存器中,否则函数有一个隐藏的参数,我必须检测和处理。

这曾经是C ++ 03 POD的定义,但是在C ++ 11中这个变化了:

由于C ++ 11标准中的定义已经发生变化,因此我们不build议使用std::is_pod来进行此testing。

到目前为止,我可以用一些共轭性状来检测types是否符合C ++ 03 POD的定义。 然而,在C ++ 17中,聚合规则已经发生了变化,这打破了我的解决scheme。

如果我可以以某种方式检测typesT是否有任何基类,我的解决scheme将再次工作。

是的,这是可能的,至less对于聚合。

首先,我们构build一个可转换为模板参数的任何适当基类的类模板:

 template<class T> struct any_base { operator T() = delete; template<class U, class = std::enable_if_t<std::is_base_of_v<U, T>>> operator U(); }; 

然后,我们通过types为any_base<T>的值来检测模板参数T是否是可构造的集合:

 template<class, class = void> struct has_any_base : std::false_type {}; template<class T> struct has_any_base<T, std::void_t<decltype(T{any_base<T>{}})>> : std::true_type {}; 

例子 。

我相信检查“ T是否从任何东西”是不可能的,至less不符合标准的方式。 如果你正在使用这种技术来检查一个types是否是一个POD /平凡/聚合,有一些types特征可以帮助你:

  • std::is_pod

  • std::is_trivial

  • std::is_aggregate