我正在尝试使用boost序列化以下字符串类型:
using CustomString = std::basic_string<char, std::char_traits<char>, CustomAllocator<char>>;
字符串
**1.**由于此类型与std::string的定义相同,除了分配器之外,我的第一种方法是像boost对std::string所做的那样。
我在using语句后添加了BOOST_CLASS_IMPLEMENTATION(CustomString, boost::serialization::primitive_type)
。
这看起来工作得很好,直到我试图序列化一个有空格的字符串。
序列化是在boost::archive::text_oarchive中完成的,并且分隔符被设置为空格。因此,在序列化之后,只有字符串的第一部分从存档中读取,例如,我将“Hello World”写入存档,但在序列化之后只得到“Hello”。对于std::string,boost在文本之前添加了一个长度字段。这不是自定义字符串的情况。
长度条目的源是boost\archive\impl\text_oarchive_impl.ipp
text_oarchive_impl<Archive>::save(const std::string &s)
{
const std::size_t size = s.size();
*this->This() << size;
this->This()->newtoken();
os << s;
}
型
我在以下问题的答案中发现了同样的问题:Can boost::container::strings be serialized using boost serialization?
我扩展了这个例子,以使问题可见:https://coliru.stacked-crooked.com/a/84b2cb162d58534a
**2.**现在我编写了自己的序列化函数
namespace boost
{
namespace serialization
{
template<class Archive>
inline void serialize(Archive& ar, CustomString & s, const unsigned int file_version)
{
boost::serialization::split_free(ar, s, file_version);
}
template<typename Archive>
inline void save(
Archive& ar, const CustomString & s, const unsigned int /* file_version */
)
{
ar << s.size();
for (size_t i = 0; i < s.size(); i++)
{
ar << s.c_str()[i];
}
}
template<typename Archive>
inline void load(
Archive& ar, CustomString & s, const unsigned int /* file_version */
)
{
size_t size;
ar >> size;
char c;
for (size_t i=0; i < size;i++)
{
ar >> c;
s.push_back(c);
}
}
} // namespace serialization
} // namespace boost
型
这段代码确实可以工作,但会产生一个相当长的归档文件,因为字符被编码为十进制值:
std::initializer_list
自定义字符串存档:22 serialization::archive 19 0 0 11 72 101 108 108 111 32 87 111 114 108 100
如果您能给我一些提示,告诉我如何改进这两种方法中的一种,我将不胜感激。谢谢!
1条答案
按热度按时间fivyi3re1#
是的,我仍然很惊讶对
{std,boost::container}::basic_string
的支持不是开箱即用的。而且,很惊讶没有人注意到旧的答案被打破了。我同意自定义序列化是更安全的选择。它可以更简单和轻量级:
Live On Coliru
字符串
传递Assert并打印预期的:
型
如果注解掉
make_array
行,则会接近于手动编码的内容:(Live)型