Увеличить сериализацию пустого 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()