使用可变成员的boost :: serialization

时间:2010-05-18 00:29:11

标签: c++ serialization boost mutable boost-serialization

使用boost :: serialization,在可变成员中序列化包含缓存的派生值的对象的“最佳”方法是什么?

class Example
{
public:
    Example(float n) : 
        num(n),
        sqrt_num(-1.0)
    {}

    // compute and cache sqrt on first read
    float get_sqrt() const
    { 
        if(sqrt_num < 0) 
            sqrt_num = sqrt(num);
        return sqrt_num;
    }

    template <class Archive> 
    void serialize(Archive& ar, unsigned int version)
    { ... }
private:
    float num;
    mutable float sqrt_num;
};

出于维护原因,我想避免将serialize()拆分为单独的save()和load()方法。

序列化的一个次优实现:

    template <class Archive> 
    void serialize(Archive& ar, unsigned int version)
    {
        ar & num;
        sqrt_num = -1.0;
    }

它处理反序列化的情况,但在序列化的情况下,缓存的值被终止,必须重新计算。

在这种情况下,最佳做法是什么?

2 个答案:

答案 0 :(得分:3)

拆分保存和加载方法并不意味着您必须维护两个序列化代码副本。您可以拆分它们,然后使用通用功能再次将它们连接起来。

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

  BOOST_SERIALIZATION_SPLIT_MEMBER()

  template <class Archive>
  void save(Archive& ar, const unsigned int version) const {
      const_cast<Example*>(this)->common_serialize(ar, version);
  }

  template <class Archive>
  void load(Archive& ar, const unsigned int version) {
      common_serialize(ar, version);
      sqrt_num = -1;
  }

  template <class Archive>
  void common_serialize(Archive& ar, const unsigned int version) {
      ar & num;
  }

你可能已经注意到了const_cast。对于这个想法,这是一个不幸的警告。虽然serialize成员函数对于保存操作是非const的,但save成员函数需要是const。但是,只要你序列化的对象最初没有被声明为const,就可以安全地将其丢弃,如上所示。文件briefly mentions the need to cast for const members;这是类似的。

通过上述更改,您的代码将为ex1ex2正确打印“2”,您只需维护序列化代码的一个副本。 load代码仅包含特定于重新初始化对象内部缓存的代码; save函数不会触及缓存。

答案 1 :(得分:2)

您可以检查Archive::is_loading字段,并加载缓存的值(如果是的话)。

template <class Archive> 
void serialize(Archive& ar, unsigned int version)
{
    ar & num;
    if(Archive::is_loading::value == true)
        sqrt_num = -1.0;
}