【问题标题】:Is there a way to serialize iterators using boost serialization?有没有办法使用 boost 序列化来序列化迭代器?
【发布时间】:2018-02-22 15:53:17
【问题描述】:

在我的项目中,我有一个包含 std::list 的类,在另一个类中,我维护一个迭代器,指向该列表中间的一个位置。

我可以成功序列化列表,但迭代器成员变量导致问题。这是一个重现的程序:

#include <boost/serialization/list.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <iostream>
#include <fstream>

class A
{
public:
  A(){}
  A(const std::list<int> & _i) : i(_i) {}
  virtual ~A(){}

  std::list<int> i;

  void display() {
    std::cout << "i:";
    for (const int j : i)
      std::cout << " " << j;
    std::cout << std::endl;
  }

private:
  friend class boost::serialization::access;
  //friend std::ostream & operator<<(std::ostream &os, const A &a);
  template<class Archive>
  void serialize(Archive &ar, const unsigned int version)
  {
    ar & i;
  }
};

class Stepper
{
public:
  Stepper() {}
  Stepper(const A& a)
    : p(a.i.size()>0 ? a.i.begin() : a.i.end()) {}

  std::list<int>::const_iterator p;

  void display() {
    std::cout << "p: " << *p << std::endl;
  }

  void step() { p++; }

private:
  friend class boost::serialization::access;
  //friend std::ostream & operator<<(std::ostream &os, const A &a);
  template<class Archive>
  void serialize(Archive &ar, const unsigned int version)
  {
    ar & p;
  }
};

int main()
{
  {
    A a({5,6,7});
    Stepper sa(a);
    a.display();
    sa.display();
    sa.step();
    sa.display();

    std::ofstream ofs( "a.txt" );
    boost::archive::text_oarchive ar(ofs);
    ar & a;
    ar & sa;
  }

  A b;
  Stepper sb;
  {
    std::ifstream ifs( "a.txt" );
    boost::archive::text_iarchive ar(ifs);
    ar & b;
    ar & sb;
  }

  b.display();
  sb.display();

  return 0;
}

在这个程序中,类 A 可以毫无问题地被序列化。 (删除ar&amp;sa 的东西..)但不幸的是,当尝试序列化包含迭代器的类时(上面的确切代码),我得到以下编译错误:

[..snip..]

testser.cpp:72:10:   required from here /usr/include/boost/serialization/access.hpp:116:11:
error: ‘struct std::_List_const_iterator<int>’ has no member named ‘serialize’
         t.serialize(ar, file_version);
         ~~^~~~~~~~~


[..snip..]

testser.cpp:81:10:   required from here /usr/include/boost/serialization/access.hpp:116:11:
error: ‘struct std::_List_const_iterator<int>’ has no member named ‘serialize’

所以,boost/serialization/list.hpp 似乎不支持迭代器。然而,据我所知,将迭代器保留到某处的列表项是totally legitimate,因为除非被删除,否则它们不会失效。有没有办法使用 boost 序列化这个迭代器?我需要编写自定义函数吗?我是否必须从我的 std::list 返回自定义迭代器? (这听起来特别难看..)

感谢您的任何见解。

【问题讨论】:

  • 问题是迭代器将引用曾经存在的列表。不是从可能位于不同位置的文件中读取的新内容。您可以存储该节点在列表中的“偏移量”,然后获取新列表的新迭代器并增加该偏移量的次数。
  • 以此类推,您希望指针如何序列化?
  • 序列化通常用于在程序关闭和重新启动之间保存数据。这意味着你所有的对象都应该死掉。
  • 是的,我同意,但我想在列表恢复后将指针/迭代器恢复到列表中的同一位置。
  • "以此类推,您希望指针如何序列化?"我们的代码已经充满了相互指向的对象,它们可以很好地序列化

标签: c++ boost-serialization


【解决方案1】:

好吧,似乎唯一的方法是将序列化拆分为保存和加载,并计算迭代器在列表中的位置。只要迭代器有效,它就可以工作。不幸的是,这意味着需要添加一个指向结构列表的指针,这是我不想要的,但实际上在我的应用程序中我可以访问它,所以这对我来说不是问题。

class Stepper                                                                            
{                                                                                        
public:                                                                                  
  Stepper() {}                                                                           
  Stepper(const A& _a)                                                                   
    : a(&_a), p(a->i.size()>0 ? a->i.begin() : a->i.end()) {}                            

  const A* a;                                                                            
  std::list<int>::const_iterator p;                                                      

  void display() {                                                                       
    std::cout << "p: " << *p << std::endl;                                               
  }                                                                                      

  void step() { p++; }                                                                   

private:                                                                                 
  friend class boost::serialization::access;                                             

  template<class Archive>                                                                
  void save(Archive &ar, const unsigned int version) const                               
  {                                                                                      
    int d = std::distance(a->i.begin(), p);                                              
    ar & a;                                                                              
    ar & d;                                                                              
  }                                                                                      

  template<class Archive>                                                                
  void load(Archive &ar, const unsigned int version)                                     
  {                                                                                      
    int d;                                                                               
    ar & a;                                                                              
    ar & d;                                                                              
    p = a->i.begin();                                                                    
    for (; d>0; --d)                                                                     
      p++;                                                                               
  }                                                                                      

  BOOST_SERIALIZATION_SPLIT_MEMBER()                                                     
};

【讨论】:

    猜你喜欢
    • 2012-08-12
    • 2014-12-30
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    • 2011-10-21
    • 2018-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多