将升压串行化集成到现有代码中
Integrating boost serialising into existing code
我有以下形式的代码:
ODIstream &operator<<(ODIstream& vis, const Song &lyrics)
{
vis >> doh;
vis >> a;
vis >> deer;
vis >> a;
vis >> female;
vis >> deer;
}
其中ODIStream是一个旧的不推荐使用的类库的序列化函数,female是来自不推荐使用类库的容器。它们在为彼此构建的过程中协同工作。我的任务是更新这个代码并删除这个库,因此我们开始:
istream &operator<<(istream& vis, const Song &lyrics)
{
vis >> doh;
vis >> a;
vis >> deer;
vis >> a;
vis >> female;
vis >> deer;
}
但雌性不与鸵鸟一起工作。当我将female更改为stl::list时,它没有内置的序列化运算符(单个类元素有)。
我本来打算使用boost:串行化代码,但我不确定如何将存档与当前的代码模型集成。
有人这样做过吗?
请注意,序列化有一个不同于流的目标。
序列化会导致存档。因此,您不会向ostream
写入,也不会从istream
读取。相反,您将写入oarchive
(文本、二进制、xml)或从相应的iarchive
读取。
每个归档文件都将携带(相当多的)归档文件头。因此,将存档视为流媒体运营商内部的一个细节似乎是个坏主意,快速演示:
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/serialization.hpp>
struct Simplest {
int i;
template <typename Archive> void serialize(Archive& ar, unsigned /*version*/) {
ar & i;
}
friend std::ostream& operator<<(std::ostream& os, Simplest const& data) {
boost::archive::text_oarchive oa(os);
oa << data;
return os;
}
};
int main() {
Simplest a { 4215680 }, b { -42 };
std::cout << a << b;
}
这将导致
22 serialization::archive 10 0 0 4215680
22 serialization::archive 10 0 0 -42
只是为了序列化。。。2个整数。
此外,Boost Serialization是为处理归档错误而设计的。然而,如果读取("解析")失败,输入流操作员通常会离开输入位置,并且必须小心将流状态保持在适当的状态,以便流仍然可以使用。
我建议两种方法之一:
1.始终使用Boost序列化
想象一个演示struct
struct Demo
{
int i;
std::string truth;
using Vars = std::map<std::string, double>;
Vars vars;
};
使用简单的序列化实现和(以及一个只用于进行调试打印的助手):
int main()
{
Demo a { 42, "LtUaE", { { "PI", 3.1415926 }, { "e", std::exp(1.0) } } };
std::cout << "Debug : " << a << "n";
std::string const serialized = serialize(a);
std::cout << "Serious serialization: " << serialized << "n";
// to parse back:
Demo roundtrip = deserialize(serialized);
std::cout << "Parsed back: " << roundtrip << "n";
}
我们得到
Debug : 42;LtUaE;PI;3.14159;e;2.71828;
Serious serialization: 22 serialization::archive 10 0 0 42 5 LtUaE 0 0 2 0 0 0 2 PI 3.1415926000000001 1 e 2.7182818284590451
Parsed back: 42;LtUaE;PI;3.14159;e;2.71828;
查看Coliru直播
这里的一大优势是很容易获得二进制流:也可以在Coliru上直播:
#include <map>
#include <sstream>
#include <iomanip>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/map.hpp>
struct Demo
{
int i;
std::string truth;
using Vars = std::map<std::string, double>;
Vars vars;
template <typename Archive> void serialize(Archive& ar, unsigned /*version*/)
{
ar & i;
ar & truth;
ar & vars;
}
friend std::ostream& operator<<(std::ostream& os, Demo const& demo)
{
os << demo.i << ';' << demo.truth << ";";
for (auto& e : demo.vars)
os << e.first << ";" << e.second << ";";
return os;
}
};
static std::string as_hex(std::string const& binary)
{
std::ostringstream oss;
for (unsigned ch: binary)
oss << std::setw(2) << std::setfill('0') << std::hex << ch;
return oss.str();
}
static std::string serialize(Demo const& data)
{
std::ostringstream oss;
boost::archive::binary_oarchive oa(oss);
oa << data;
return oss.str();
}
static Demo deserialize(std::string const& text)
{
std::istringstream iss(text);
boost::archive::binary_iarchive ia(iss);
Demo data;
ia >> data;
return data;
}
int main()
{
Demo a { 42, "LtUaE", { { "PI", 3.1415926 }, { "e", std::exp(1.0) } } };
std::cout << "Debug : " << a << "n";
std::string const serialized = serialize(a);
std::cout << "Serious serialization: " << as_hex(serialized) << "n";
// to parse back:
Demo roundtrip = deserialize(serialized);
std::cout << "Parsed back: " << roundtrip << "n";
}
2.使用Boost Spirit
使用相同的Demo结构和
int main()
{
Demo a { 42, "LtUaE", { { "PI", 3.1415926 }, { "e", std::exp(1.0) } } };
std::cout << "Quick serialization: " << karma::format_delimited(karma::auto_, ';', a) << "n";
std::string const serialized = serialize(a);
std::cout << "Serious serialization: " << serialized << "n";
// to parse back:
Demo roundtrip = deserialize(serialized);
std::cout << "Parsed back: " << karma::format_delimited(karma::auto_, ';', roundtrip) << "n";
}
打印:
Quick serialization: 42;LtUaE;PI;3.142;e;2.718;
Serious serialization: Demo{42;LtUaE;{{PI: 3.142}, {e: 2.718}}}
Parsed back: 42;LtUaE;PI;3.142;e;2.718;
查看Coliru直播
#include <map>
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
namespace qi = boost::spirit::qi;
namespace karma = boost::spirit::karma;
struct Demo
{
int i;
std::string truth;
using Vars = std::map<std::string, double>;
Vars vars;
};
BOOST_FUSION_ADAPT_STRUCT(Demo, (int,i)(std::string,truth)(Demo::Vars, vars))
static std::string serialize(Demo const& data)
{
std::ostringstream oss;
oss << karma::format(
"Demo{" << karma::int_ << ';' << karma::string << ';'
<< '{'
<< ('{' << karma::string << ": " << karma::double_ << '}') % ", "
<< '}'
<< '}', data);
return oss.str();
}
static Demo deserialize(std::string const& text)
{
auto f(text.begin()), l(text.end());
Demo parsed;
if (qi::parse(f, l,
"Demo{" >> qi::int_ >> ';' >> +~qi::char_(';') >> ';'
>> '{'
>> ('{' >> +~qi::char_(':') >> ": " >> qi::double_ >> '}') % ", " >> '}'
>> '}', parsed))
{
return parsed;
}
throw std::runtime_error("Parse failed at '" + std::string(f,l) + "'");
}
int main()
{
Demo a { 42, "LtUaE", { { "PI", 3.1415926 }, { "e", std::exp(1.0) } } };
std::cout << "Quick serialization: " << karma::format_delimited(karma::auto_, ';', a) << "n";
std::string const serialized = serialize(a);
std::cout << "Serious serialization: " << serialized << "n";
// to parse back:
Demo roundtrip = deserialize(serialized);
std::cout << "Parsed back: " << karma::format_delimited(karma::auto_, ';', roundtrip) << "n";
}
TL;DR
使用Boost序列化的方式,它是为了快速获胜;你会得到
- 工作量越小,鲁棒性越强
- 更灵活,工作量更小
- 较低编译时间
Spirit的好处是:
- 对序列化格式的绝对控制
- 易于解析的可读写格式
- 仅标头库
相关文章:
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 代码在main()中运行,但在函数中出现错误
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- 将节点 js 代码集成到 cpp 库时出错
- 集成来自C++的 R 代码
- 我想使用 CMakeList 将 ODBC 集成到我的 Linux 和 Windows 代码中.txt但它只能在 Win
- 如何在Ubuntu 16.04上的Anaconda环境中将OpenCV C 代码与Python代码集成在一起
- Visual Studio代码集成的终端未显示文本
- 将升压串行化集成到现有代码中
- 集成 Fortran 和 C++ 代码的查询
- 如何将代码与virtualbox集成
- 在Visual Studio 2010(C++)中集成MATLAB代码
- 用僵硬的代码停止odeint中的集成
- MATLAB代码与C/ c++集成时的致命错误
- 需要方向集成已经存在的c++代码到Android NDK
- 在Linux中集成Crypto++代码到Qt应用程序
- 当将卡萨布兰卡代码集成到现有的c++解决方案中时,Memcpy异常
- 有可能在php中集成c++代码吗?
- 如何将异常更正确地集成到我的代码和未来的代码中?(C++)
- 查找集成 Qt4 和 v4l2 库的示例代码