Как сериализовать boost::ptr_vector с помощью хлопьев?

Можно ли сериализовать экземпляр boost::ptr_vector с помощью хлопьев? Если да, то как?


person Ton van den Heuvel    schedule 20.01.2016    source источник
comment
Я не очень хорошо знаком с ptr_vector, но похоже, что это оболочка вокруг std::vector<void*>. хлопья не поддерживают необработанные указатели, поэтому я думаю, что маловероятно, что вы сможете сериализовать ptr_vector без существенных изменений в хлопьях или сложного обходного пути.   -  person Azoth    schedule 30.01.2016


Ответы (1)


Это определенно возможно. Вы можете создать внешние шаблонные функции save() и load() для типа архива и указателя следующим образом:

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

Это должно работать с любым содержащимся типом, который конструируется по умолчанию и уже индивидуально сериализуем.

person rhashimoto    schedule 01.02.2016
comment
.... и для которых перегрузки для save и load можно найти в связанном пространстве имен (см. ADL). Я мог бы добавить, что эта версия имеет довольно забавную семантику построения под нагрузкой. Это нормально, потому что ptr_vectors в любом случае не может иметь элементы псевдонимов - person sehe; 02.02.2016
comment
@sehe, ты имеешь в виду, что с забавной семантикой нагрузки это можно сделать более эффективно? - person Ton van den Heuvel; 05.02.2016
comment
На самом деле нет, выглядит нормально. - person sehe; 05.02.2016