std::is_layout_compatible 用于判断两个类型内存布局是否完全一致以确保跨语言/库二进制兼容;要求二者均为 standard-layout、非 union、成员数量及顺序相同、对应成员 layout-compatible、访问控制一致、基类 layout-compatible、且均不含位域。
它用来判断两个类型在内存布局上是否完全一致,从而保证跨编译单元、跨库甚至跨语言(比如 C 和 C++)传递对象时不会因 ABI 差异出错。这不是类型等价检查,而是“它们的二进制排布能不能互换”——比如 struct A 和 struct B 成员顺序、类型、对齐都一样,std::is_layout_compatible_v 才为 true。
标准要求所有这些条件同时成立,缺一不可:
std::is_standard_layout_v)false
很多人以为加了 [[no_unique_address]] 或调整 static_assert 就能绕过 ABI 问题,其实不行。这个元函数不关心语义,只看实际生成的二进制结构。
[[no_unique_address]],布局可能不同 → std::is_layout_compatible_v 仍为 false
true,也不能保证跨工具链安全enum class 和底层整型(如 int)永远不 layout-compatible,哪怕大小和对齐一样std::is_layout_compatible_v 必为 false
struct A {
int x;
char y;
};
struct B {
int x;
char y;
};
static_assert(std::is_layout_compatible_v); // ✅ 通过
struct C {
int x;
char y;
short z; // 多一个字段
};
static_assert(!std::is_layout_compatible_v); // ✅ 失败
struct D {
int x;
char y;
int padding; // 显式填充 ≠ 隐式填充规则
};
// 不保证与 A layo
ut-compatible —— 因为 A 的隐式填充位置/大小由 ABI 决定,D 的 padding 是显式成员
真正难的是确保两端(比如 Rust FFI 和 C++ 导出结构)使用完全相同的 ABI 约束:不仅要 layout-compatible,还要确认对齐、调用约定、名字修饰方式全部一致。这个元函数只是第一道防线,不是银弹。