Search code examples
c++boostcereal

How to serialize a boost::ptr_vector using cereal?


Is it possible to serialize a boost::ptr_vector instance using cereal? If so, how?


Solution

  • It is definitely possible. You can create external save() and load() template functions on the archive and pointer type like this:

    #include <iostream>
    #include <sstream>
    #include <boost/ptr_container/ptr_vector.hpp>
    #include <cereal/archives/binary.hpp>
    #include <cereal/types/string.hpp>
    
    // Sample serializable object.
    struct MyRecord {
       std::string s_;
    
       MyRecord(const std::string s = std::string())
          : s_(s) {
       }
    
       template <class Archive>
       void serialize(Archive& ar ) {
          ar(s_);
       }
    };
    
    // External save function for boost::ptr_vector<T>.
    template<class Archive, class T>
    void save(Archive& ar, const boost::ptr_vector<T>& pv) {
       ar(pv.size());
       for (const auto& element : pv)
          ar(element);
    }
    
    // External load function for boost::ptr_vector<T>.
    template<class Archive, class T>
    void load(Archive& ar, boost::ptr_vector<T>& pv) {
       size_t n;
       ar(n);
    
       pv.reserve(n);
       for (size_t i = 0; i < n; ++i) {
          pv.push_back(new T);
          ar(pv.back());
       }
    }
    
    int main() {
       // Serialize a boost::ptr_vector to a buffer.
       std::ostringstream os;
       {
          boost::ptr_vector<MyRecord> saved;
          saved.push_back(new MyRecord("how"));
          saved.push_back(new MyRecord("now"));
          saved.push_back(new MyRecord("brown"));
          saved.push_back(new MyRecord("cow"));
    
          cereal::BinaryOutputArchive oa(os);
          oa(saved);
       }
    
       // Serialize from the buffer.
       boost::ptr_vector<MyRecord> loaded;
       {
          std::istringstream is(os.str());
          cereal::BinaryInputArchive ia(is);
          ia(loaded);
       }
    
       for (const auto& element : loaded)
          std::cout << element.s_ << '\n';
    
       return 0;
    }
    

    This should work with any contained type that is default-constructible and is already individually serializable.