如何使用boost::具有嵌套结构和最小代码更改的序列化
How to use boost::serialization with nested structs and minimal code changes?
目前我们使用存储在嵌套结构中的POD。示例:
#define MaxNum1 100;
#define MaxNum2 50;
struct A
{
int Value[MaxNum1];
char SomeChar = 'a';
};
struct B
{
A data[MaxNum2];
float SomeFloat = 0.1f;
};
int main()
{
B StructBObject = {};
}
我们希望使用std::vector来增强我们的数据结构,就像这样:
struct NewA
{
std::vector<int> Value;
char SomeChar = 'a';
};
struct NewB
{
std::vector<NewA> data;
float SomeFloat = 0.1f;
};
int main()
{
NewB StructNewBObject = {};
}
反对这种修改的唯一论点是NewA
和NewB
不再是POD,这使得读取/写入文件变得更加复杂。
如何使用boost::serialization
以最小值将NewA
和NewB
读取/写入文件代码更改为NewA
和NewB
?最小的代码更改是很重要的,因为我们使用例如具有多达7个嵌套级别的大型结构。
您可以使用boost序列化进行序列化
template <typename Ar> void serialize(Ar& ar, A& a, unsigned) {
ar & a.Value & a.SomeChar;
}
template <typename Ar> void serialize(Ar& ar, B& b, unsigned) {
ar & b.data & b.SomeFloat;
}
使用这些方法,您将已经使用C数组和std::vector方法获得了开箱即用的正确行为。
如果你想继续使用固定大小的可复制类型²,你可以使用类似Boost Container的static_vector
:它会跟踪当前大小,但数据是在结构内部静态分配的。
三重演示
这里有一个三重演示程序,根据IMPL
变量有三个实现。
正如您所看到的,大部分代码保持不变。然而,为了"最佳比较",我已经确保在序列化之前所有容器的容量都是一半(50/25(。
主程序也进行反序列化。
在Coliru上直播
#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/is_bitwise_serializable.hpp>
#include <boost/serialization/binary_object.hpp>
#include <iostream>
#if (IMPL==0) // C arrays
struct A {
int Value[100];
char SomeChar = 'a';
};
struct B {
A data[50];
float SomeFloat = 0.1f;
};
template <typename Ar> void serialize(Ar& ar, A& a, unsigned) {
ar & a.Value & a.SomeChar;
}
template <typename Ar> void serialize(Ar& ar, B& b, unsigned) {
ar & b.data & b.SomeFloat;
}
#elif (IMPL==1) // std::vector
#include <boost/serialization/vector.hpp>
struct A {
std::vector<int> Value;
char SomeChar = 'a';
};
struct B {
std::vector<A> data;
float SomeFloat = 0.1f;
};
template <typename Ar> void serialize(Ar& ar, A& a, unsigned) {
ar & a.Value & a.SomeChar;
}
template <typename Ar> void serialize(Ar& ar, B& b, unsigned) {
ar & b.data & b.SomeFloat;
}
#elif (IMPL==2) // static_vector
#include <boost/serialization/vector.hpp>
#include <boost/container/static_vector.hpp>
struct A {
boost::container::static_vector<int, 100> Value;
char SomeChar = 'a';
};
struct B {
boost::container::static_vector<A, 50> data;
float SomeFloat = 0.1f;
};
template <typename Ar> void serialize(Ar& ar, A& a, unsigned) {
ar & boost::serialization::make_array(a.Value.data(), a.Value.size()) & a.SomeChar;
}
template <typename Ar> void serialize(Ar& ar, B& b, unsigned) {
ar & boost::serialization::make_array(b.data.data(), b.data.size()) & b.SomeFloat;
}
#endif
namespace bio = boost::iostreams;
static constexpr auto flags = boost::archive::archive_flags::no_header;
using BinaryData = std::vector</*unsigned*/ char>;
int main() {
char const* impls[] = {"C style arrays", "std::vector", "static_vector"};
std::cout << "Using " << impls[IMPL] << " implementation: ";
BinaryData serialized_data;
{
B object = {};
#if IMPL>0
{
// makes sure all containers half-full
A element;
element.Value.resize(50);
object.data.assign(25, element);
}
#endif
bio::stream<bio::back_insert_device<BinaryData>> os { serialized_data };
boost::archive::binary_oarchive oa(os, flags);
oa << object;
}
std::cout << "Size: " << serialized_data.size() << "n";
{
bio::array_source as { serialized_data.data(), serialized_data.size() };
bio::stream<bio::array_source> os { as };
boost::archive::binary_iarchive ia(os, flags);
B object;
ia >> object;
}
}
打印
Using C style arrays implementation: Size: 20472
Using std::vector implementation: Size: 5256
Using static_vector implementation: Size: 5039
最后的想法
另请参阅:
- 提升序列化的逐位可序列化性
- https://www.boost.org/doc/libs/1_72_0/libs/serialization/doc/wrappers.html#binaryobjects
²不是POD,就像NSMI一样,你的类型不是POD
相关文章:
- 如何在C++中序列化结构数据
- 序列化,没有库的整数,得到奇怪的结果
- 如何知道QDataStream不能反序列化某些内容
- 如何使用Python从C++中读取谷物序列化数据
- 如何使用boost::具有嵌套结构和最小代码更改的序列化
- 带有Protobuf序列化的C++Hazelcast:字符串不是UTF-8格式的
- 自定义对象的dlib序列化在gcc中失败
- C++boost序列化多态性问题
- 增强基于 XML class_id的反序列化
- 提升反序列化对象具有 nan 或 -nan 值
- 在 cpp 中的平面缓冲区中序列化对象
- 如何在 c++ 非托管代码中反序列化 byte[] 的 json 字符串?
- 使用 boost::序列化代码将 *this 传递给模板函数会产生错误
- 用于序列化/反序列化目的的标准C++代码
- 代码合成 XSD 树动态序列化
- 序列化来自同一代码库的std::函数
- 没有托管代码的xml序列化
- 如何在使用Boost序列化时删除此重复代码
- 提升 MPL 以生成用于对象序列化的代码
- 代码综合- c++ /树子节点序列化