Boost logo

Boost Users :

From: Guy Létourneau (Guy.Letourneau_at_[hidden])
Date: 2006-07-21 13:12:51


Any updates on my problem Robert?

Thanks,

Guy

>
>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]'
>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