如何在编译时检测 class 在 C++17 中是否没有虚基?
How to detect whether a class has no virtual base in C++17 at compile time?
鉴于:
- 定义的类型T;
- 任何你想要的工具。
如何在编译时检测C++17中T是否没有虚基?
编辑:
其实我是在写一个type-erased container,在写获取copy ctor的代码的时候,发现只要一个class没有
virtual base 并且没有用户提供的复制构造函数,复制构造函数可以是指向诸如 std::memcpy.
之类的东西的指针
如果您使用 ,您 可能 能够根据指向 class 的成员函数的指针的大小来确定这一点微软 Visual C++。它不适用于其他编译器,尤其是那些实现了 Itanium C++ ABI.
的编译器
在 Microsoft 实施中,class 的布局可能会因虚拟基地 class 的位置而异,而 pointer-to-member-function 将需要应用偏移量才能获得调用的正确 this
指针。当存在虚拟基 class 时,这会导致 pointer-to-member-function 比没有虚拟基时更大。由于 sizeof
运算符是一个编译时常量,因此可以在不同的地方(包括模板参数)使用它来根据是否存在虚拟基来区分代码。
这是一个简单的测试程序(在 Godbolt 上)。如果编译成功,您可以使用成员函数指针的大小来确定是否为 class.
指定了虚拟基 class
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;
}
要确定是否可以使用 std::memcpy
,您实际上需要 std::is_trivially_meowable
。
例如,如果您想使用std::memcpy
进行复制,您可以使用std::is_trivially_copyable
进行检查。
您还可以检查平凡可构造和平凡可破坏。
正如您在评论中所说,您还想用非平凡的 classes 来做到这一点。这不可避免地会导致未定义的行为,所以我不会尝试。我建议删除那些 classes 中的 vtable 并在依赖未定义行为之前使它们变得微不足道。
此外,如果您使用指向那些 class 的指针,则指针本身是微不足道的。所以你可以用这种方式简单地复制你的class。
鉴于:
- 定义的类型T;
- 任何你想要的工具。
如何在编译时检测C++17中T是否没有虚基?
编辑:
其实我是在写一个type-erased container,在写获取copy ctor的代码的时候,发现只要一个class没有 virtual base 并且没有用户提供的复制构造函数,复制构造函数可以是指向诸如 std::memcpy.
之类的东西的指针如果您使用 ,您 可能 能够根据指向 class 的成员函数的指针的大小来确定这一点微软 Visual C++。它不适用于其他编译器,尤其是那些实现了 Itanium C++ ABI.
的编译器在 Microsoft 实施中,class 的布局可能会因虚拟基地 class 的位置而异,而 pointer-to-member-function 将需要应用偏移量才能获得调用的正确 this
指针。当存在虚拟基 class 时,这会导致 pointer-to-member-function 比没有虚拟基时更大。由于 sizeof
运算符是一个编译时常量,因此可以在不同的地方(包括模板参数)使用它来根据是否存在虚拟基来区分代码。
这是一个简单的测试程序(在 Godbolt 上)。如果编译成功,您可以使用成员函数指针的大小来确定是否为 class.
指定了虚拟基 classstruct 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;
}
要确定是否可以使用 std::memcpy
,您实际上需要 std::is_trivially_meowable
。
例如,如果您想使用std::memcpy
进行复制,您可以使用std::is_trivially_copyable
进行检查。
您还可以检查平凡可构造和平凡可破坏。
正如您在评论中所说,您还想用非平凡的 classes 来做到这一点。这不可避免地会导致未定义的行为,所以我不会尝试。我建议删除那些 classes 中的 vtable 并在依赖未定义行为之前使它们变得微不足道。
此外,如果您使用指向那些 class 的指针,则指针本身是微不足道的。所以你可以用这种方式简单地复制你的class。