使用C ++ 17可以检测结构/类是否有任何基础?

时间:2017-09-13 10:45:52

标签: c++ inheritance c++17 typetraits

我需要一个类型特征,如果给定的类型派生自任何东西,则为true,否则为false。

例如:

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
}

是否有可能以某种方式实现&#34; is_inherit&#34;特质结构?

为什么?

我正在为Windows x64开发手动堆栈框架构建器。根据{{​​3}}文档,如果是类型:

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

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

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

  

由于C ++ 11标准中的定义已更改,因此我们不建议使用std::is_pod进行此测试。

到目前为止,有了一些共轭特征,我可以检测出类型是否符合C ++ 03 POD的定义。然而,对于C ++ 17,聚合规则已经改变,这破坏了我的解决方案。

如果我能以某种方式检测类型T是否有任何基类,我的解决方案将再次起作用。

2 个答案:

答案 0 :(得分:32)

是的,这是可能的,至少对于聚合来说。

首先,我们构建一个可转换为其模板参数的任何正确基础的类模板:

import re
rx = r"(a.*?c)?.*g"
s = "abcdefg"
m = re.search(rx, s)
if m:
    print(m.group(0)) # => abcdefg
    print(m.group(1)) # => abc

然后我们检测模板参数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(); }; 是否可以从T类型的值构建聚合:

any_base<T>

Example

答案 1 :(得分:9)

我认为检查“T是否来自任何东西”是不可能的,至少不是以符合标准的方式。如果您使用此技术检查类型是否为POD /普通/聚合,则有一些类型特征可能对您有所帮助: