[英]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,這使得讀取/寫入文件更加復雜。
這怎么可能讀/寫NewA
和NewB
使用到文件boost::serialization
用最少的代碼改變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)。
主程序也反序列化。
#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
也可以看看:
¹(但請記住可移植性,因為您可能已經知道 POD 方法,請參閱C++ Boost::serialization : How do I archive a object in a program and restore it in another? )
² 不是 POD,與 NSMI 一樣,您的類型不是 POD
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.