我正在使用Boost 1.59.0在std::forward_list<Foo>
中序列化对象(让我们称之为Foo)。但是,在std::forward_list<Foo>
为空的情况下,我无法执行此操作。为了演示我的问题,我从Boost的序列化教程中扩展了“Very simple case”。
#include <fstream>
#include <unordered_map>
#include <forward_list>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/unordered_map.hpp>
#include <boost/serialization/forward_list.hpp>
class Foo
{
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int)
{
ar & a;
ar & b;
}
int a;
int b;
public:
Foo()
: a(-1), b(-1) {}
Foo(int new_a, int new_b)
: a(new_a), b(new_b) {}
};
typedef std::forward_list<Foo> TListType;
class gps_position
{
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int)
{
ar & degrees;
ar & minutes;
ar & seconds;
ar & my_list;
}
int degrees;
int minutes;
float seconds;
TListType my_list;
public:
gps_position(){};
gps_position(int d, int m, float s, TListType new_list) :
degrees(d), minutes(m), seconds(s), my_list(new_list)
{}
};
int main()
{
std::ofstream ofs("filename");
TListType my_list(0);
// my_list.push_front(Foo(-1,-1));
const gps_position g(35, 59, 24.567f, my_list);
{
// save data
boost::archive::text_oarchive oa(ofs);
oa << g;
}
gps_position newg;
{
std::ifstream ifs("filename");
boost::archive::text_iarchive ia(ifs);
ia >> newg;
}
return 0;
}
此代码使用g ++ 4.8.3编译,但运行它会抛出:
在抛出一个实例后终止调用 '升压::归档:: archive_exception'
what():输入流错误
中止(核心倾销)
如果我们通过取消注释此行
将一个元素添加到列表中// my_list.push_front(Foo(-1,-1));
没有抛出任何异常,一切似乎都有效。如果我在上面的代码中将std::forward_list<Foo>
替换为std::forward_list<int>
,那么代码也可以使用。此外,使用std::list<Foo>
或std::vector<Foo>
也有效,因此问题似乎仅限于std::forward_list
。
问题:如何在不插入虚拟Foo对象的情况下序列化空std::forward_list<Foo>
?
答案 0 :(得分:1)
尝试在从文件中读取之前关闭ofstream
。最好的办法是,在“ofs
”块中移动// save data
:
{
// save data
std::ofstream ofs("filename");
boost::archive::text_oarchive oa(ofs);
oa << g;
}
我的猜测是,如果没有数据,则写入小于ofstream缓冲区,并且在读取时文件是空的/不完整的。
如果你问我,这是“非常简单的案例”中的一个缺陷。
答案 1 :(得分:1)
这是由boost中的错误引起的(仍然存在增强1.67,解释和补丁:https://svn.boost.org/trac10/ticket/13563)。它由列表元素中的编译器和默认构造函数的某些组合触发。
作为一种解决方法,您可以序列化一个标志,指示列表是否为空。您需要将序列化功能拆分为“保存”和“加载”,例如:
template<typename Archive>
void save(Archive& ar, const unsigned int version) const
{
ar << degrees;
ar << minutes;
ar << seconds;
bool empty = nodes_.empty(); // workaround
ar << empty;
if (!empty)
ar << nodes_;
}
template<typename Archive>
void load(Archive& ar, const unsigned int version)
{
ar >> degrees;
ar >> minutes;
ar >> seconds;
bool empty; // workaround
ar >> empty;
if (!empty)
ar >> my_list;
}
BOOST_SERIALIZATION_SPLIT_MEMBER()