如何在编译时检测一个类在C ++ 17中是否没有虚拟基础?

时间:2018-04-02 04:48:58

标签: c++ c++17 compile-time

假设:

  1. 已定义的类型T;
  2. 您想要的任何工具。
  3. 如何在编译时检测T在C ++ 17中是否没有虚拟基础?

    编辑:

    我实际上是在编写一个类型擦除的容器,当我编写获取复制文件的代码时,我发现只要一个类没有  虚拟基础并没有用户提供的拷贝ctor,copy ctor可以是指向std :: memcpy之类的东西的指针。

2 个答案:

答案 0 :(得分:3)

要了解您是否可以使用std::memcpy,实际上需要std::is_trivially_meowable

例如,如果您要使用std::memcpy进行复制,可以使用std::is_trivially_copyable进行复制。

您还可以检查是否具有可构造性和平凡可破坏性。

正如你在评论中所说,你也想用非平凡的课程来做这件事。这不可避免地导致不确定的行为,所以我不会尝试它。我建议在依赖于不明确的行为之前删除这些类中的vtable并使它们变得微不足道。

此外,如果您使用指向这些类的指针,指针本身也是微不足道的。因此,您可以通过这种方式轻松复制您的课程。

答案 1 :(得分:1)

如果您使用 Microsoft Visual C ++ 可能能够根据指向该类成员函数的指针的大小来确定这一点。它不适用于其他编译器,特别是那些实现Itanium C++ ABI的编译器。

使用Microsoft实现,类的布局可以根据虚拟基类的位置而变化,并且指向成员函数的指针需要应用偏移量来获取正确的this指针电话。这可能导致指向成员函数的指针在存在虚拟基类时比在没有虚拟基础时更大。由于sizeof运算符是编译时常量,因此可以在各种位置(包括模板参数)使用它来根据虚拟基础的存在来区分代码。

这是一个简单的测试程序(和Godbolt)。如果它编译,您可以使用成员函数指针的大小来确定是否为类指定了虚拟基类。

struct B {
    void f();
};

struct C: virtual public B {
    void g();
};

int test(int s) {
    switch (s) {
        case sizeof(&C::g):
            return 1;
        case sizeof(&B::f):
            return 2;
    }
    return 0;
}