我想制作一个“接口” /混合类(模板),并确保没有人认为将成员添加到此类模板是个好主意,我想static_assert
条件。
不幸的是,std::is_empty
不允许使用虚函数(因为多态类需要一些空间来存储其虚函数表指针或等效的实现细节)。
是否有std::is_empty
的变体允许虚拟功能,但不允许数据成员(或者很容易编写)?
我希望此方法可以正常工作(加上我现在无法想到的所有暗角情况):
#include <type_traits>
struct A {};
struct B : A {};
struct AA { virtual ~AA() = default; };
struct BB : AA {};
static_assert(std::is_empty_v<A>);
static_assert(std::is_empty_v<B>);
// These should also work with the replacement for is_empty:
static_assert(std::is_empty_v<AA>);
static_assert(std::is_empty_v<BB>);
int main()
{}
我猜这需要编译器魔术或非常特定于平台的破解/检查,具体取决于虚拟函数的实现方式。
答案 0 :(得分:3)
我会这样做:
struct dummy_polymorphic
{
virtual ~dummy_polymorphic() {}
};
template <typename T>
inline constexpr bool empty_maybe_polymorphic_v = std::is_empty_v<T> ||
(std::is_polymorphic_v<T> && sizeof(T) <= sizeof(dummy_polymorphic));
这是我能想到的最好方法,但它有一些局限性:
我们假设一个多态类的开销总是相同的(通常是一个相当安全的假设,除非您的类由于多重继承而最终带有多个vtable指针)。我看不出有什么办法摆脱 的限制。
如果T
具有重复的空基数,则会中断:
struct A {};
struct B : A{};
struct C : A, B {virtual ~C() {}};
std::cout << sizeof(C) << '\n'; // 16, rather than 8