提升空std :: forward_list的序列化

时间:2015-12-01 19:11:17

标签: c++ serialization boost boost-serialization forward-list

我正在使用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>

2 个答案:

答案 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()