Problem with serialization

O

okinrus

Can someone take a look at this code and figure out why
Serializable_base::add_serializer throws std::bad_alloc. The problem
seems to be the compiler because msvc++ 7.1 says
c:\LibSerial\LibSerial.cpp(83) : warning C4584: 'serial::E' :
base-class 'serial::A' is already a base-class of 'serial::C'
c:\LibSerial\LibSerial.cpp(10) : see declaration of
'serial::A'
c:\LibSerial\LibSerial.cpp(48) : see declaration of
'serial::C'


#include <vector>
#include <iostream>

//#include "Archive.h"
//
// Archive is an abstract class that defines write(int), write(float)
etc.
// But for our purposes it can be just defined to be
//
namespace serial {

class Archive { };

template<class T>
inline Archive& operator&=(Archive& ar, T& x)
{
return ar;
}

}

namespace serial {

class Serializable_base;
class Serial_holder;

// Serialize_base will store a vector of
// Serialize_action_base objects which
// will then be called back in predefined order
// at serialization
class Serialize_action_base
{
public:
virtual void serialize(Archive& ar) = 0;
};

// This should call the serialize method of a class T
template<typename T>
class Serialize_action : public Serialize_action_base
{
T* sc;
public:
Serialize_action() : sc(0)
{ }

void set_obj(T* serial)
{
sc = serial;
}

void serialize(Archive& ar)
{
if (sc != 0)
{
sc->T::serialize(ar);
}
}
};



// Serializable virtually inherits from this class to retrieve
// a unique id
class Serializable_base
{
friend class Serial_holder;
public:
Serializable_base()
{
std::cout << "Serializable_base()" << std::endl;
}

virtual ~Serializable_base()
{
std::cout << "Serializable_base destroyed" << std::endl;
}
protected:
// this is where std::bad_alloc is thrown
void add_serializer(Serialize_action_base* serializer)
{
serializers.push_back(serializer);
}
private:
typedef std::vector<Serialize_action_base*> serializer_actions;
serializer_actions serializers;


void serialize_all(Archive& ar)
{
std::cout << "num serializers = " << serializers.size() <<
std::endl;
for (size_t i = 0; i < serializers.size(); ++i)
serializers->serialize(ar);
}
};


// T is the class that inherits from this class
template<typename T>
class Serializable : public virtual Serializable_base
{
typedef T Base;

friend class Serialize_action;

// This serialize method function should be invoked within the
// Serialize_action object. It should just call the class
// who derives from this class serialize method, which
// means that any class that we should be able to make a
// given class Serializable by writing
//
// class C : public Serializable<C>
// {
// void serialize(Archive& ar) { }
// };
void serialize(Archive& ar)
{
Base* base = dynamic_cast<Base*>(this);
if (base)
base->serialize(ar);
}
public:
Serializable()
: Serializable_base()
{
std::cout << "Serializable()" << std::endl;
sa.set_obj(this);
add_serializer(&sa);
}
private:
Serialize_action<Serializable<T> > sa;
};

class Serial_holder
{
public:
Serial_holder(Serializable_base* r)
: root(r)
{ }


void serialize(Archive& ar)
{
root->serialize_all(ar);
}
private:
Serializable_base* root;
};

}

#endif

//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////

// Do some tests of the serialize classes
#include "LibSerial.h"
#include <iostream>
using namespace serial;


class A : public Serializable<A>
{
int a;
int b;
int c;
public:
A() : a(1), b(2), c(3) { }

~A()
{
std::cout << "A destroyed" << std::endl;
}

void serialize(Archive& ar)
{
std::cout << "Serializing A" << std::endl;
ar &= a;
ar &= b;
ar &= c;
}
};

class B : public Serializable<B>
{
int a;
int b;
public:
B() : a(4), b(5) { }

void serialize(Archive& ar)
{
std::cout << "Serializing B" << std::endl;
ar &= a;
ar &= b;
}

};

class C : public A, public B, public Serializable<C>
{
int c;
int d;
public:
C() : c(6), d(7) { }

void serialize(Archive& ar)
{
std::cout << "Serializing C" << std::endl;
ar &= c;
ar &= d;
}
};

class D : public B, public A, public Serializable<D>
{
int e;
int f;
int g;
public:
D() : e(4), f(5), g(6)
{

}

void serialize(Archive& ar)
{
std::cout << "Serializing D" << std::endl;
ar &= e;
ar &= f;
ar &= g;
}
};

class E : public A, public C, public Serializable<E>
{
int e;
public:
E() : e(5) { }

void serialize(Archive& ar)
{
std::cout << "Serializing E" << std::endl;
ar &= e;
}
};

/// T is the class that were're testing
template<class T>
void do_test(serial::Archive& ar)
{
T c;

std::cout << "testing " << typeid(c).name() << std::endl;

Serial_holder sh(&c);
sh.serialize(ar);
}

int main()
{
serial::Archive ar;
do_test<E>(ar);

return 0;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,981
Messages
2,570,188
Members
46,733
Latest member
LonaMonzon

Latest Threads

Top