boost::使用可变成员进行序列化

发布于 2024-09-02 02:29:56 字数 847 浏览 8 评论 0原文

使用 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;
    }

这可以处理反序列化情况,但在序列化情况下,缓存的值将被终止并且必须重新计算。

在这种情况下,最佳实践是什么?

Using boost::serialization, what's the "best" way to serialize an object that contains cached, derived values in mutable members?

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;
};

I'd like to avoid splitting serialize() into separate save() and load() methods, for maintenance reasons.

One suboptimal implementation of serialize:

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

This handles the deserialization case, but in the serialization case, the cached value is killed and must be recomputed.

What is the best practice in this case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清风夜微凉 2024-09-09 02:29:56

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

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 成员函数对于保存操作来说是非常量的,但 save 成员函数需要是 const。不过,只要您要序列化的对象最初没有声明为 const,就可以安全地将其丢弃,如上所示。文档 简要提到需要强制转换 const成员;这很相似。

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

Splitting your saving and loading methods doesn't mean you have to maintain two copies of your serialization code. You can split them and then join them back again with a common function.

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;
  }

You probably noticed the const_cast. That's an unfortunate caveat to this idea. Although the serialize member function is non-const for saving operations, the save member function needs to be const. As long as the object you're serializing wasn't originally declared const, though, it's safe to cast it away as shown above. The documentation briefly mentions the need to cast for const members; this is similar.

With the changes above, your code will correctly print "2" for both ex1 and ex2, and you only have to maintain one copy of the serialization code. The load code only contains code specific to re-initializing the object's internal cache; the save function doesn't touch the cache.

人间不值得 2024-09-09 02:29:56

您可以检查 Archive::is_loading 字段,如果为 true,则加载缓存的值。

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

You can check the Archive::is_loading field, and load cached values if it's true.

template <class Archive> 
void serialize(Archive& ar, unsigned int version)
{
    ar & num;
    if(Archive::is_loading::value == true)
        sqrt_num = -1.0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文