Увеличить сериализацию пустого std::forward_list

Я использую Boost 1.59.0 для сериализации объектов (назовем их Foo) в std::forward_list<Foo>, Тем не менее, я не могу сделать это в тех случаях, когда std::forward_list<Foo> пустой. Чтобы продемонстрировать свою проблему, я расширил " Очень простой случай" из учебника по сериализации в Boost.

#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, однако при его запуске выдается:

прерывание вызывается после создания экземпляра 'boost:: archive:: 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,

Вопрос: Как я могу сериализовать пустой std::forward_list<Foo> без вставки фиктивных объектов Foo?

2 ответа

Попробуйте закрыть ofstream перед чтением из файла. Лучший способ, двигаться ofs внутри "// save dataБлок

{
    // save data
    std::ofstream ofs("filename");
    boost::archive::text_oarchive oa(ofs);
    oa << g;
}

Я предполагаю, что при отсутствии данных запись меньше буфера ofstream, и файл физически пуст / неполен во время чтения.

Это недостаток в примере "очень простой случай", если вы спросите меня.

Это вызвано ошибкой в ​​boost (все еще есть в 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()
Другие вопросы по тегам