是否有一种(可移植的)方法来检测c++类中的布局变化?



例如,我有一个具有典型序列化模式的类Foo。

struct Foo {
int a;
bool b;
template <typename Archive>
void serialize(Archive & ar) {
ar & a;
ar & b;
}
};

现在假设有人出现并添加了一个字段。

struct Foo {
int a;
bool b;
std::string c;
template <typename Archive>
void serialize(Archive & ar) {
ar & a;
ar & b;
}
};

这个编译正常,但是Archive方法是错误的。我可以加上


namespace detail {
template <int a, int b>
void AssertSizeOfImplementation() {
static_assert(a == b, "Size does not match (check stack trace)");
}
}  
template <typename T, int size>
void AssertSizeOf() {
detail::AssertSizeOfImplementation<sizeof(T), size>();
}

struct Foo {
int a;
bool b;
template <typename Archive>
void serialize(Archive& ar) {
ar& a;
ar& b;
AssertSizeOf<Foo,8>();
}
};

现在如果我添加额外的字段,我将看到一个编译错误

:在实例化'void detail::AssertSizeOfImplementation() [with int a = 40;int b = 8]':

然后我可以修复我的序列化代码并更新断言。

然而,这不是很便携。sizeof将根据包装和架构返回不同的结果。

使用sizeof还有其他选择吗?

(在godbolt上玩这个https://godbolt.org/z/fMo8ETjnr)

boost中有一个很酷的库:boost pfr。我从未在实际项目中使用过它(只是一些玩具),但似乎工作得很好:

struct Foo {
int a;
bool b;
template <typename Archive>
void serialize(Archive& ar, const unsigned int)
{
boost::pfr::for_each_field(*this, [&ar](const auto& field) { ar& field; });
}
};

现场演示。

现在,任何字段列表的更改都将被考虑在内,而无需更改序列化代码。

我试过godbolt,但我没能解决链接问题(找不到boost库),所以它实际上可以运行。

最新更新