|
Boost Users : |
From: Guy Létourneau (Guy.Letourneau_at_[hidden])
Date: 2006-07-19 10:32:18
Robert,
I've created a simple test as you suggested. The problem is that the test does not even build (in oserializer.hpp, there are 2 conditions for this to happen but none seems to match my test..). Here's what the compiler gives me:
C:/Boost/include/boost-1_33_1/boost/archive/detail/oserializer.hpp: In function `void boost::archive::save(Archive&, T&) [with Archive = boost::archive::text_oarchive, T = A]':
C:/Boost/include/boost-1_33_1/boost/archive/basic_text_oarchive.hpp:78: instantiated from `void boost::archive::basic_text_oarchive<Archive>::save_override(T&, int) [with T = A, Archive = boost::archive::text_oarchive]'
C:/Boost/include/boost-1_33_1/boost/archive/detail/interface_oarchive.hpp:78: instantiated from `Archive& boost::archive::detail::interface_oarchive<Archive>::operator<<(T&) [with T = A, Archive = boost::archive::text_oarchive]'
../main.cpp:90: instantiated from here
C:/Boost/include/boost-1_33_1/boost/archive/detail/oserializer.hpp:567: error: incomplete type `boost::STATIC_ASSERTION_FAILURE<false>' does not have member `value'
#include <iostream>
#include <fstream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/export.hpp>
class A
{
public:
A()
{
i = 1;
};
virtual ~A()
{
};
virtual void Dummy() = 0;
private:
int i;
};
BOOST_IS_ABSTRACT(A)
class B : public A
{
public:
B()
{
};
virtual ~B()
{
};
void Dummy()
{
};
void SetValue( std::string& value )
{
Data = value;
}
private:
friend
class boost::serialization::access;
template <class Archive>
void serialize( Archive& ar, const unsigned int version )
{
ar & boost::serialization::base_object<A>( *this );
ar& Data;
std::cout << "Serialization of B" << std::endl;
std::cout.flush();
}
std::string Data;
};
BOOST_CLASS_EXPORT(B);
int main()
{
// Create a B object
B* Child = new B;
// Set some data
std::string Data = "test";
Child->SetValue( Data );
// Assign it to a A ptr
A* Parent = Child;
// create and open a character archive for output
std::ofstream ofs( "filename" );
// save data to archive
{
try
{
boost::archive::text_oarchive oa( ofs );
// write class instance to archive
oa << *Parent;
}
catch( boost::archive::archive_exception& e )
{
std::cout << "Save failed! : " << e.what();
std::cout.flush();
return false;
}
catch( ... )
{
std::cerr << "Unknown Exception " << std::endl;
return false;
}
// archive and stream closed when destructors are called
}
delete Child;
}
The example is very simple. Again, I have problems only when serializing via a base class ptr (serializing object "directly" works fine).
Thanks again for your help,
Guy
>Hmm - looks like it should work to me.
>
>I would try the following:
>
>a) make a tiny test - a main which which does nothing but tests the
>serialization.
>This you can ship to us in necessary.
>b) For now - remove all the BOOST_CLASS_TRACKING macros.
>It shouldn't make a difference but let's start simple.
>c) You'll have to add BOOST_CLASS_EXPORT for SomeData
>d) double check that everything is in the same namespace.
>e) try removing the friend class boost::serialization::access; from
>the base class. NonVolatileData::serialize(..) should never be called
>by the serialization library in this case - so if this traps during >compile,
>it will show a chain of "compile time calls". By looking at this chain
>one can see where things went wrong. Unfortunately this requires
>looking at the header source code - oh well.
>f) double check that the test corresponding to your example builds
>and runs in your environment. If that passes, but yours does not, try
>modifying the test bit by bit by commenting out the code that is there
>and replacing it with your own code. If you finish this and the test
>still works - then just remove all the commented code and you'll be
>done.
>
>Robert Ramey
Guy Létourneau wrote:
> Robert,
> I've tried to include your changes but it doesn't solve the problem.
> I had to add the following line: BOOST_IS_ABSTRACT(NonVolatileData)
> for the program to compile. I agree with you, to have an abstract
> class is what is needed in that case as the NonVolatileData class is
> not intended to do something useful except for allowing my data
> storage layer to be generic. However, abstract or not, I still have
> the same problem: when serializing my SomeData object through a
> pointer to the NonVolatileData, only the data of the parent class
> gets serialized. Anything else you want me to try?
>
> Thanks,
> Guy
>
>> Try making the base class polymorphic - that it define at least
>> one abstract function. See my changes below. This will have
>> the beneficial effect of inhibiting anyone from creating an instance
>> of your base class directly.
>> Robert Ramey
>
>> Guy Létourneau wrote:
>>> Hello,
>>>
>>> I need to develop a generic data storage layer. Its job is to handle
>>> the serialization of all objects that need to be persistent in my
>>> system and handle management of archives, backups and restores and
>>> so forth. The most important point is that it must stay generic,
>>> i.e. have no knowledge of the type of objects being passed by other
>>> modules in the system. Because of this, I define a base class
>>> NonVolatileData from which all data classes in the system will
>>> derive:
>>>
>>> ///////////////////////////////////////////////////////////////////////
>>> // Base class
>>> class NonVolatileData
>>> {
>>> friend
>>> class boost::serialization::access;
>>>
>>> public:
>>>
>>> NonVolatileData(){ i = 1; };
>>> virtual ~NonVolatileData() = 0; // Note - pure virtual function
>>> make class abstract-
>>>
>>>
>>> protected:
>>>
>>> virtual void Dummy() =0; // Note - pure virtual function make
>>> class abstract-
>> ;
>>>
>>> int i;
>>> template <class Archive>
>>> void serialize( Archive& ar, const unsigned int version )
>>> {
>>> ar & i;
>>> }
>>> };
>>> BOOST_CLASS_TRACKING(NonVolatileData,
>>> boost::serialization::track_never)
>>>
>>>
>>> class SomeData: public NonVolatileData
>>> {
>>> friend
>>> class boost::serialization::access;
>>>
>>> public:
>>>
>>> SomeData ()
>>> {
>>> };
>>>
>>> ~SomeData ()
>>> {
>>> };
>>>
>>> void SetValue( std::string& Address )
>>> {
>>> this->Address = Address;
>>> }
>>>
>>> void Dummy()
>>> {
>>> }
>>>
>>> private:
>>>
>>> template <class Archive>
>>> void serialize( Archive& ar, const unsigned int version )
>>> {
>>> ar &
>>>
>>> boost::serialization::base_object<NonVolatileData>(*this);
>>> ar& Address; }
>>>
>>> std::string Address;
>>> };
>>> BOOST_CLASS_TRACKING(SomeData, boost::serialization::track_never)
>>> /////////////////////////////////////////////////////////////////
>>>
>>> My data storage interface will take a ptr to the base class i.e.
>>> Save(NonVolatileData* data) so the serialization will be performed
>>> through a ptr to the base class. I've read the documentation
>>> multiple times and I'm still unable to make that work correctly.
>>> When a do a save, only the base class is serialized even though the
>>> base class is polymorphic. I've tried using the
>>> BOOST_CLASS_EXPORT_GUID macro the force a registration of my derived
>>> class without success. I've also checked the example from demo.cpp.
>>> It uses the direct call to register_type() but in my case, I don't
>>> want to change the code everytime a new class is defined in the
>>> system so I went with option 2 (the macro). There's probably a
>>> subtle detail I do not do correctly (polite way of saying I'm
>>> missing something :-)).
>>>
>>> Thanks for your help,
>>>
>>> Guy Letourneau =
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net