Увеличить сериализацию - включить отслеживание объектов - PullRequest
0 голосов
/ 13 марта 2012

У меня есть класс A, владеющий std :: vector, и набор экземпляров класса B, содержащий указатель на вектор в A.

Теперь я хотел бы использовать boost :: serialization длясериализовать все мои экземпляры A и B, но в сериализованных данных может существовать только один экземпляр вектора данных в A.

Я знаю, что эту проблему можно (и часто следует) решить с помощью shared_ptr, нов моем конкретном случае это не сработает.

Как будут выглядеть методы сериализации для архивации?

Ниже я попробовал.Мне кажется, что отслеживание объектов не выполняется или что reset_object_address не работает так, как я думал.

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

1 Ответ

0 голосов
/ 28 октября 2012

Одним из решений является изменение методов сохранения и загрузки в 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;

}

Т.е. просто сериализуйте ваш vector_wrapper напрямую, а не как указатель.После этого исправления все утверждения пройдены.

...