2

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

#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”类,但我不确定该类本身是否可序列化(即,在序列化/反序列化方面就像一个原语)一旦这个函数有已创建,或者如果我必须为此使用侵入性方法...

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

我在教程中找不到这个问题的答案,希望有使用这个库的经验的人能解释一下!

PS我不愿意“尝试一下”,因为我不知道失败应该是什么样子(Boost会序列化“某事”吗?)...

4

2 回答 2

4

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

是的,无论您使用哪种方法,该类都可以通过将“&”运算符与 boost.serialization 存档一起使用的常规方法进行序列化。

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

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

PS我不愿意“尝试一下”,因为我不知道失败应该是什么样子(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";
  }
}
于 2013-09-18T04:34:01.083 回答
1

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

文档说:

当且仅当满足以下条件之一时,类型T才是可序列化的:

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

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

没有定义成员函数serialize和全局函数serialize的类类型(后者具有类类型的非常量引用作为第二个参数)不满足可序列化的概念。

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

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

也就是说,如果您包含适当的头文件 ,<boost/serialization/vector.hpp>则向量模板的特化变为Serializable如果它value_typeSerializable

由于您的类gps_positionSerializable ,如果您包含上述标题, astd::vector<gps_position>也是Serializable 。但是,包含此类向量的类本身不会根据规则自动序列化。它需要有一个成员或非成员函数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(参数相关查找),则免费函数和模板可以位于以下任何命名空间中:

  • boost::serialization
  • 归档类的命名空间
  • 被序列化类型的命名空间
于 2013-09-18T04:43:36.493 回答