【问题标题】:Combination of Boost ICL and Boost SerializationBoost ICL和Boost序列化的结合
【发布时间】:2014-06-02 22:23:11
【问题描述】:

我正在尝试使用 Boost 序列化库来归档 Boost ICL 间隔集(因为我找不到任何其他或多或少的标准方法来序列化它们)。我想将serialize 函数拆分为两个函数saveload。很抱歉,我现在被困在load 函数中——我什至无法保存间隔集的大小。 我的测试程序如下。编译器抱怨A << IS.iterative_size() 行,这很奇怪,因为iterative_size() 函数的返回类型是size_t

#include <fstream>
#include <string>

#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/split_free.hpp>

#include <boost/icl/discrete_interval.hpp>
#include <boost/icl/interval_set.hpp>

const std::string Filename = "tmp.archive";

typedef boost::icl::discrete_interval<int> Interval;
typedef boost::icl::interval_set<int> IntervalSet;

namespace boost
{
  namespace serialization
  {

    template<class Archive>
    void save(Archive& A, const IntervalSet& IS, const unsigned int)
    {
      A << IS.iterative_size();
      // ...
    }

    template<class Archive>
    void load(Archive& A, IntervalSet& IS, const unsigned int)
    {
      // ...
    }

    template<class Archive>
    inline void serialize(Archive& A, IntervalSet& IS, const unsigned int V)
    {
      split_free(A, IS, V); 
    }

  }
}

int main()
{
  std::ofstream f(Filename);
  if (f.good())
  {
    boost::archive::binary_oarchive oa(f);
    IntervalSet s;
    s += Interval::closed(100, 200); 
    oa << s;
    f.close();
  }
  else
  {
    std::cout << "Error" << std::endl;
  }
}

有什么想法吗?

(编译器 - GCC 4.8.1,Boost - 1.55.0,操作系统 - Xubuntu 3.11)

【问题讨论】:

    标签: c++ serialization boost


    【解决方案1】:

    iterative_size() 不返回 lvalue,这是必需的。无论如何,您都无法有效地反序列化派生属性(与向量不(反)序列化 size() 成员结果的方式大致相同。相反,它序列化所有数据,而 size() 恰好最终成为最后还是一样。

    也看看

    如果没有这样的默认构造函数,函数模板load_construct_datasave_construct_data 将不得不被覆盖。这是一个简单的例子

    来自docs

    这可能在对象实例仅从(非默认)构造函数参数初始化的情况下有用。

    更新这是一个演示实现:Live On Coliru

    #include <boost/archive/binary_iarchive.hpp>
    #include <boost/archive/binary_oarchive.hpp>
    #include <boost/serialization/split_free.hpp>
    
    #include <boost/icl/discrete_interval.hpp>
    #include <boost/icl/interval_set.hpp>
    
    namespace boost { namespace serialization {
    
        template <typename Archive, typename V>
            void save(Archive& ar, boost::icl::discrete_interval<V> const& di, unsigned) {
                auto const& bb = di.bounds().bits();
                auto const& l  = di.lower();
                auto const& u  = di.upper();
    
                ar << bb << l << u;
            }
    
        template <typename Archive, typename V>
            void load(Archive& ar, boost::icl::discrete_interval<V>& di, unsigned) {
                auto bb = di.bounds().bits();
                V    l, u;
    
                ar >> bb >> l >> u;
    
                di = boost::icl::discrete_interval<V>(l, u, boost::icl::interval_bounds(bb));
            }
    
        template <typename Archive, typename V>
            void serialize(Archive& ar, boost::icl::discrete_interval<V>& di, unsigned v) {
                split_free(ar, di, v);
            }
    
        template <typename Archive, typename V>
            void save(Archive& ar, boost::icl::interval_set<V> const& is, unsigned) {
                auto sz = is.iterative_size();
    
                ar & sz;
                for (auto& di : is) ar & di;
            }
    
        template <typename Archive, typename V>
            void load(Archive& ar, boost::icl::interval_set<V>& is, unsigned) {
                is.clear();
    
                size_t sz;
                ar & sz;
    
                size_t counter = sz;
    
                while (counter--) {
                    typename boost::icl::interval_set<V>::value_type di;
                    ar & di;
                    is.insert(is.end(), di);
                }
    
                assert(is.iterative_size() == sz);
            }
    
        template <typename Archive, typename V>
            void serialize(Archive& ar, boost::icl::interval_set<V>& is, unsigned v)
            {
                split_free(ar, is, v);
            }
    } }
    
    const std::string Filename = "tmp.archive";
    
    typedef boost::icl::discrete_interval<int> Interval;
    typedef boost::icl::interval_set<int> IntervalSet;
    
    #include <fstream>
    #include <string>
    
    int main()
    {
        {
            std::ofstream f(Filename);
            boost::archive::binary_oarchive oa(f);
            IntervalSet s;
            s += Interval::closed(100, 200); 
            s += Interval::left_open(30,45);
            s += Interval::right_open(77, 78);
    
            oa << s;
        }
        {
            std::ifstream f(Filename);
            boost::archive::binary_iarchive ia(f);
    
            IntervalSet s;
            ia >> s;
    
            std::cout << "Deserialized: ";
            std::copy(s.begin(), s.end(), std::ostream_iterator<Interval>(std::cout, " "));
        }
    }
    

    打印:

    Deserialized: (30,45] [77,78) [100,200] 
    

    【讨论】:

    • 为什么&lt;&lt; 运算符需要lvalue?我认为将serialize 拆分为save/load 对就足以摆脱&lt;&lt;&gt;&gt; 自动替换&amp;&gt;&gt;
    • @HEKTO 不要问我。如果你要问我,我猜它与 serialize(Archive&amp;ar, T&amp; v, unsigned) 对称,这是支持加载和保存所必需的。
    • 好吧,我能够使用中间的std::vector 实现save/load 函数——这不是很有趣,但是很有效。无论如何,谢谢你的建议。
    • @HEKTO FWIW 这是我的看法 - 不需要临时向量 Live On Coliru
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-11
    • 2016-02-28
    • 2011-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多