在Boost :: Serialise中序列化类的非侵入式方法是否使类可序列化?

时间:2013-09-18 03:51:52

标签: c++ serialization boost

我正在尝试理解Boost的序列化库(see tutorial),并且非常类似于序列化类的非侵入式方法,因为这意味着我可以将所有序列化代码放在单独的文件中:

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

class gps_position
{
public:
    int degrees;
    int minutes;
    float seconds;
    gps_position(){};
    gps_position(int d, int m, float s) :
        degrees(d), minutes(m), seconds(s)
    {}
};

namespace boost {
namespace serialization {

template<class Archive>
void serialize(Archive & ar, gps_position & g, const unsigned int version)
{
    ar & g.degrees;
    ar & g.minutes;
    ar & g.seconds;
}

} // namespace serialization
} // namespace boost

虽然这个方法提供了一个函数'serialise',它可以用来序列化'gps_position'类,但我不确定这个类本身是否是 serializable (即表现得像一个原语)序列化/反序列化的术语)一旦创建了这个函数,或者我必须使用侵入式方法......

也就是说,如果我有另一个包含'gps_position'实例的向量的类,Boost会知道在Boost :: serialization命名空间中查找重载的'serialize'函数,该函数匹配'gps_position'参数我尝试序列化父类?或者它只是明确地查找类的'serialize'方法(在这个实例中它找不到)?

我在教程中找不到这个问题的答案,并且希望有经验的人可以使用这个库,这可能会有所帮助!

P.S我不愿意“只是尝试一下”,因为我不知道失败应该是什么样的(Boost只会序列化“某些东西”?)......

2 个答案:

答案 0 :(得分:4)

  

虽然此方法提供了可以使用的“序列化”功能   为了序列化'gps_position'类,我不确定该类   它本身是可序列化的(即就行为而言就像一个原始行为   序列化/反序列化)一旦创建了这个函数,或者如果   我必须使用侵入式方法...

是的,该课程将通过使用'&amp;'的常规方法进行序列化。具有boost.serialization存档的运算符,无论您使用哪种方法。

  

也就是说,如果我有另一个类,其中包含一个向量   'gps_position'实例,Boost会知道要查找重载   'serialize'函数在Boost :: serialization命名空间中匹配a   当我尝试序列化父类时,'gps_position'参数?要么   它只会明确地查找类的'serialize'方法   (在这种情况下它不会找到)?

您还需要为父类提供序列化功能。在其中,您将以与完成子类相同的方式序列化类的每个成员。

  P.S我不愿意“试试”,因为我不知道失败了   应该看起来像(Boost只是序列化“某些东西”?)......

尝试一下,是你学到的最好的方法。最有可能的是,在简要查看文档后,其他任何想要回答这个问题的人都会学到这些知识。

以下是侵入式和非侵入式版本的快速模型:

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <boost/serialization/access.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

// child class serialized using intrusive

struct child
{
  std::string name;

  child() = default;

  explicit child(const std::string& name)
    : name(name)
  { }

  template <class Archive>
  void serialize(Archive& ar, const unsigned int /* version */)
  {
    ar & name;
  }
};


struct parent
{
  std::vector<child> children;

  parent() = default;

  explicit parent(const std::vector<child>& children)
    : children(children)
  { }
};

// parent class serialized using non-instrusive

namespace boost {
namespace serialization {

template <class Archive>
void serialize(Archive& ar, parent& p, const unsigned int /* version */)
{
  ar & p.children;
}

}
}

int main()
{
  parent p1 {{child("one"), child("two"), child("three")}};

  std::stringstream ss;
  boost::archive::text_oarchive oa(ss);
  oa << p1;

  parent p2;
  boost::archive::text_iarchive ia(ss);
  ia >> p2;

  for (auto& child : p2.children) {
    std::cout << child.name << "\n";
  }
}

答案 1 :(得分:1)

  

虽然这个方法提供了一个函数'serialise',可用于序列化'gps_position'类,但我不确定该类本身是否可序列化(即,在序列化/反序列化方面就像一个原语)这个函数已经创建,或者如果我必须使用侵入式方法......

documentation说:

  

类型T 可序列化当且仅当下列情况之一为真时:

     
      
  • 它是一种原始类型。 [...]
  •   
  • 这是一个类类型,根据下面详述的原型声明了以下之一:   
        
    • 班级成员函数serialize
    •   
    • 全局函数serialize
    •   
  •   
  • 它是指向可序列化类型的指针。
  •   
  • 它是对可序列化类型的引用。
  •   
  • 它是可序列化类型的本机C ++数组。
  •   

  

也就是说,如果我有另一个包含'gps_position'实例的向量的类,Boost会知道在Boost :: serialization命名空间中查找重载的'serialize'函数,该函数匹配'gps_position'参数我尝试序列化父类?或者它只是明确地查找类的'serialize'方法(在这个实例中它找不到)?

没有定义成员函数serialize且没有定义全局函数serialize的类类型(后者具有类类型的非const ref作为第二个参数)不符合 Serializable 概念。

但是,在文档的同一页面上:

  

上述设施足以实现所有STL容器的序列化。实际上,这已经完成并且已经包含在库中。

也就是说,如果您包含相应的头文件<boost/serialization/vector.hpp>,则矢量模板的特化将变为可序列化,如果其value_type 可序列化

由于您的课程gps_position 可序列化,如果您包含上述标题,则std::vector<gps_position>可序列化。但是,根据规则,包含此类向量的类不会自动可序列化。它需要有成员或非成员函数serialize

#include <boost/serialization/vector.hpp>
struct gps_position { int i; };
struct gps_path { std::vector<gps_position> v; }

template<class Archive>
void serialize(Archive& ar, gps_position& p, const unsigned int)
{  ar & p.i;  }
// by declaring this function, `gps_position` is Serializable

template<class Archive>
void serialize(Archive& ar, gps_path& p, const unsigned int)
{  ar & p.v;  }
// as `v` is Serializable (because `gps_position` is Serializable),
// you can leave it to the boost library to serialize the individual
// elements of the vector

注意:该功能不必是全局的。如文档的链接页面所述,支持非限定查找和ADL:

  

为了获得最大的可移植性,请在命名空间boost::serialization中包含任何自由函数模板和定义。如果可移植性不是问题,并且正在使用的编译器支持ADL(Argument Dependent Lookup),则自由函数和模板可以位于以下任何名称空间中:

     
      
  • boost::serialization
  •   
  • 存档类的命名空间
  •   
  • 要序列化的类型的命名空间
  •