2016-01-20 9 views
5

È possibile serializzare un'istanza boost::ptr_vector utilizzando cereali? Se é cosi, come?Come serializzare un boost :: ptr_vector usando i cereali?

+2

Non ho familiarità con 'ptr_vector', ma sembra che sia essenzialmente un wrapper attorno a' std :: vector '. cereal non supporta i puntatori grezzi, quindi penso che sia improbabile che si possa serializzare un 'ptr_vector' senza modifiche significative ai cereali o una soluzione complicata. – Azoth

risposta

3

È sicuramente possibile. È possibile creare e save()load() funzioni template esterni sul tipo di archivio e il puntatore in questo modo:

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

Questo dovrebbe funzionare con qualsiasi tipo di contenuto che è default-costruibile ed è già singolarmente serializzabile.

+0

.... e per il quale i sovraccarichi per 'save' e' load' possono essere trovati in un namespace _associato_ (vedi ADL). Potrei aggiungere che questa versione ha una semantica della costruzione piuttosto divertente sul carico. È "ok" perché ptr_vectors non può avere elementi di aliasing comunque – sehe

+0

@sehe, con la semantica del carico divertente, vuoi dire che questo può essere fatto in modo più efficiente? –

+0

In realtà no, sembra a posto. – sehe