2012-03-13 3 views
0

J'ai une classe A posséder un std :: vecteur, et un ensemble d'instances de la classe B, contenant un pointeur sur le vecteur A.sérialisation Boost - activer le suivi des objets

Maintenant, je voudrais utiliser boost :: sérialisation pour sérialiser toutes mes instances de A et B, mais une seule instance du vecteur de données dans A peut exister dans les données sérialisées.

Je sais que ce problème peut (et devrait souvent) être résolu en utilisant shared_ptr, mais cela ne fonctionnera pas dans mon cas particulier. A quoi ressembleraient les méthodes de sérialisation pour archiver cela?

Voici ce que j'ai essayé. Pour moi, il semble qu'aucun suivi d'objet n'est fait, ou que reset_object_address ne fonctionne pas comme je le pensais.

#include <assert.h> 
#include <vector> 
#include <sstream> 
#include <boost/archive/binary_oarchive.hpp> 
#include <boost/archive/binary_iarchive.hpp> 
#include <boost/serialization/vector.hpp> 

std::stringstream ss; 

// A wrapper class created to controle the serialization traits 
template< typename T > 
struct vector_wrapper { 
    std::vector<T> v; 
    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) { 
     ar & v; 
    } 
}; 

namespace boost { 
namespace serialization { 
template<class T> 
struct tracking_level<const vector_wrapper<T> * > 
{ 
    typedef mpl::integral_c_tag tag; 
    typedef mpl::int_<track_always> type; 
    BOOST_STATIC_CONSTANT(
     int, 
     value = tracking_level::type::value 
    ); 
}; 
} // namespace serialization 
} // namespace boost 

struct A { 
    vector_wrapper<unsigned> data; 

    BOOST_SERIALIZATION_SPLIT_MEMBER(); 

    A() {}; 
    A(unsigned i) { data.v.push_back(i); } 

    template<class Archive> 
    void save(Archive & ar, const unsigned int version) const { 
     const vector_wrapper<unsigned> * ptr = &data; 
     ar & ptr; 
     std::cout << "SAVE> data size: " << data.v.size() << " ptr: " << &data << std::endl; 
    } 

    template<class Archive> 
    void load(Archive & ar, const unsigned int version) { 
     const vector_wrapper<unsigned> * ptr = 0; 
     ar & ptr; 

     data = *ptr; 
     ar.reset_object_address(&data, ptr); // does not seem to have any effect 
     std::cout << "LOAD> data size: " << data.v.size() << " ptr: " << &data << std::endl; 

     delete ptr; 
    } 
}; 

struct B { 
    const vector_wrapper<unsigned> * ptr_data; 

    B() : ptr_data(0) { } 
    B(const vector_wrapper<unsigned> * p) : ptr_data(p) { } 

    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) { 
     ar & ptr_data; 
     std::cout << "SERILIAZE> ptr: " << ptr_data << std::endl; 
    } 
}; 

struct C { 
    A a; 
    B b1; 
    B b2; 
    B b3; 

    C() { } // default constructor 
    C (unsigned i) : // bootstrap constructor 
     a(i), 
     b1(&a.data), 
     b2(&a.data), 
     b3(&a.data) { } 

    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) { 
     ar & a; 
     ar & b1; 
     ar & b2; 
     ar & b3; 
    } 
}; 

int main(int argc, const char *argv[]) { 
    C c1(7); 
    boost::archive::binary_oarchive o(ss); 
    o << c1; 

    C c2; 
    boost::archive::binary_iarchive i(ss); 
    i >> c2; 

    assert(&c1.a.data == c1.b1.ptr_data); 
    assert(&c1.a.data == c1.b2.ptr_data); 
    assert(&c1.a.data == c1.b3.ptr_data); 

    assert(&c2.a.data == c2.b1.ptr_data); // fails 
    assert(&c2.a.data == c2.b2.ptr_data); // fails 
    assert(&c2.a.data == c2.b3.ptr_data); // fails 

    return 0; 
} 

Répondre

0

L'une des solutions est de changer vos méthodes de sauvegarde et de charge en A, à:

template<class Archive> 
void save(Archive & ar, const unsigned int version) const { 
    ar & data; 
    std::cout << "SAVE> data size: " << data.v.size() << " ptr: " << &data << std::endl; 
} 

template<class Archive> 
void load(Archive & ar, const unsigned int version) { 
    ar & data; 
    std::cout << "LOAD> data size: " << data.v.size() << " ptr: " << &data << std::endl; 

} 

à savoir, juste sérialiser votre vector_wrapper directement, non pas comme pointeur. Après cette correction toutes les assertions sont passées.