是否有一种(可移植的)方法来检测 C++ 类 中的布局变化?
Is there a (portable) way to detect layout change in C++ classes?
例如,假设我有一个具有典型序列化模式的 class 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;
}
};
这编译得很好,但存档方法是错误的。我可以添加类似
的内容
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>();
}
};
现在,如果我添加额外的字段,我将看到一个编译错误
: In instantiation of 'void detail::AssertSizeOfImplementation() [with int a = 40; int b = 8]':
然后我可以修复我的序列化代码并更新断言。
然而这不是很便携。 sizeof 将 return 不同的结果,具体取决于包装和体系结构。
除了使用 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 库),所以它实际上 运行。
例如,假设我有一个具有典型序列化模式的 class 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;
}
};
这编译得很好,但存档方法是错误的。我可以添加类似
的内容
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>();
}
};
现在,如果我添加额外的字段,我将看到一个编译错误
: In instantiation of 'void detail::AssertSizeOfImplementation() [with int a = 40; int b = 8]':
然后我可以修复我的序列化代码并更新断言。
然而这不是很便携。 sizeof 将 return 不同的结果,具体取决于包装和体系结构。
除了使用 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 库),所以它实际上 运行。