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

Nyu*_*ufu 36 c++ inheritance type-traits c++17

我需要一个类型特征,如果给定的类型派生自任何东西,则为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
}
Run Code Online (Sandbox Code Playgroud)

是否有可能以某种方式实现"is_inherit"特征结构?


为什么?

我正在为Windows x64开发一个手动堆栈框架构建器.根据https://docs.microsoft.com/en-us/cpp/build/return-values-cpp文档,如果是类型:

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

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

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

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

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

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

eca*_*mur 32

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

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

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();
};
Run Code Online (Sandbox Code Playgroud)

然后我们检测模板参数是否可以T从类型的值构造聚合any_base<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 {};
Run Code Online (Sandbox Code Playgroud)

例子.

  • 如果我有一个类'E类{E(B&){}};`我担心has_any_base_v会说真的 (4认同)

Vit*_*meo 9

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