[serialization] Visual Studio 2008 + Boost 1.35 : runtime casting not working
Hi,
Below is a basic sample adapted from the documentation at:
http://tinyurl.com/55fr4q
For me, with Visual Studio 2008, the deserialization of the base pointer
results in an instance of the base class, not the serialized derived
class. Also, if I add a virtual function to the base class,
deserialization results in an exception (it attempts to instantiate the
base class anyway).
I added the change cited here and rebuilt the serialization library,
which did not help:
http://tinyurl.com/5j4e8x
Any suggestions would be appreciated.
Thanks,
Steve Sanders
#include "stdafx.h"
#include "stdafx.h"
#include <sstream>
// include headers that implement a archive in simple text format
#include
The base class MUST be polymorphic - that is have at least one virtual function.
AND the the pointer to the base class - not the derived class should be serialized.
Robert Ramey
#include "stdafx.h"
#include "stdafx.h"
#include <sstream>
// include headers that implement a archive in simple text format
#include
Thank you, that makes my sample work. These points could be clearer in the docs, I would say. -Steve Sanders _____ From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Robert Ramey Sent: Monday, July 14, 2008 2:54 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] [serialization] Visual Studio 2008 + Boost 1.35:runtime casting not working The base class MUST be polymorphic - that is have at least one virtual function. AND the the pointer to the base class - not the derived class should be serialized. Robert Ramey
On Jul 14, 2008, at 5:40 PM, Steve Sanders wrote:
Thank you, that makes my sample work. These points could be clearer in the docs, I would say.
From: boost-users-bounces@lists.boost.org [mailto:boost-users- bounces@lists.boost.org] On Behalf Of Robert Ramey Sent: Monday, July 14, 2008 2:54 PM To: boost-users@lists.boost.org Subject: Re: [Boost-users] [serialization] Visual Studio 2008 + Boost 1.35:runtime casting not working
The base class MUST be polymorphic - that is have at least one virtual function.
AND the the pointer to the base class - not the derived class should be serialized.
How strict is the requirement that a base class has to be
polymorphically connected to the derived class? I have a class that
derives from a class template that uses the curiously-recurring
template pattern. Such base classes are usually without any kind of
virtual stuff, to allow inlining of parent methods and avoid the hit
virtual dispatch.
//==============================================
template < class Derived >
class counter_base
{
public:
void count() { ++counter; }
int current_count() const { return counter; }
protected:
counter_base() : counter( 0 ) {}
private:
int counter;
friend class boost::serialization::access;
template < class Archive >
void serialize( Archive &ar, unsigned const file_version )
{ ar & counter; }
};
class my_class
: private counter_base
Daryle Walker wrote:
How strict is the requirement that a base class has to be polymorphically connected to the derived class?
It's a fundamental requirement. Without a vtable it just won't work.
I have a class that derives from a class template that uses the curiously-recurring template pattern. Such base classes are usually without any kind of virtual stuff, to allow inlining of parent methods and avoid the hit virtual dispatch.
no problem. virtual dispatch only costs you time if you use it. It does cost a little space for the vtable - but with only one virtual function that shouldn't be too much. There are other options to look at. maybe you don't want to serialize through a base class pointer. Perhaps serializing something like boost::variant - (in the library) might be a better choice. your example below doesn't need to serialize through a pointer to the base class. Just use the BASE_OBJECT macro or type to invoke the base class serializaton. Robert Ramey
//============================================== template < class Derived > class counter_base { public: void count() { ++counter; } int current_count() const { return counter; } protected: counter_base() : counter( 0 ) {} private: int counter; friend class boost::serialization::access; template < class Archive > void serialize( Archive &ar, unsigned const file_version ) { ar & counter; } };
private counter_base
{ typedef counter_base base_type; typedef my_class self_type; class my_class public: explicit my_class( double factor = 1.0 ) : factor( factor ) {} double next() { count(); return factor * current_count(); } private: double factor; friend class boost::serialization::access; template < class Archive > void serialize( Archive &ar, unsigned const file_version ) { ar & ???; // what goes here for base_type (or base_type::counter)?
ar & BASE_OBJECT(counter_base
ar & factor; } }; //==============================================
[Sent it through the wrong mail account again!] On Jul 16, 2008, at 4:13 AM, Robert Ramey wrote:
Daryle Walker wrote:
How strict is the requirement that a base class has to be polymorphically connected to the derived class?
It's a fundamental requirement. Without a vtable it just won't work.
This is only for channeling through a base-class pointer, right? Just the standard pointer won't check the final type w/o some sort of polymorphic connection (or brute force w/ static_cast).
I have a class that derives from a class template that uses the curiously-recurring template pattern. Such base classes are usually without any kind of virtual stuff, to allow inlining of parent methods and avoid the hit virtual dispatch.
no problem. virtual dispatch only costs you time if you use it. It does cost a little space for the vtable - but with only one virtual function that shouldn't be too much.
There are other options to look at. maybe you don't want to serialize through a base class pointer. Perhaps serializing something like boost::variant - (in the library) might be a better choice.
your example below doesn't need to serialize through a pointer to the base class. Just use the BASE_OBJECT macro or type to invoke the base class serialization.
My class is like a function object, and will be used strictly as a
value object. There shouldn't any reason to access a base class,
especially via a pointer. (It uses the curiously-recursive template
pattern, so my class is the sole derived class of the base class'
particular instantiation.) The base class adds implementations of
common variant operations, with the derived class supplying the core
routines.
So I'll just define serialization in every class in the hierarchy,
and make sure each non-root class calls "ar &
boost::serialization::base_object
//============================================== template < class Derived > class counter_base { public: void count() { ++counter; } int current_count() const { return counter; } protected: counter_base() : counter( 0 ) {} private: int counter; friend class boost::serialization::access; template < class Archive > void serialize( Archive &ar, unsigned const file_version ) { ar & counter; } };
class my_class : private counter_base
{ typedef counter_base base_type; typedef my_class self_type; public: explicit my_class( double factor = 1.0 ) : factor( factor ) {} double next() { count(); return factor * current_count(); } private: double factor; friend class boost::serialization::access; template < class Archive > void serialize( Archive &ar, unsigned const file_version ) { ar & ???; // what goes here for base_type (or base_type::counter)? ar & BASE_OBJECT(counter_base , this); // I forget the exact syntax ar & factor; } }; //==============================================
-- Daryle Walker Mac, Internet, and Video Game Junkie darylew AT hotmail DOT com
Daryle Walker wrote:
[Sent it through the wrong mail account again!]
On Jul 16, 2008, at 4:13 AM, Robert Ramey wrote:
Daryle Walker wrote:
How strict is the requirement that a base class has to be polymorphically connected to the derived class?
It's a fundamental requirement. Without a vtable it just won't work.
This is only for channeling through a base-class pointer, right? Just the standard pointer won't check the final type w/o some sort of polymorphic connection (or brute force w/ static_cast).
correct
So I'll just define serialization in every class in the hierarchy, and make sure each non-root class calls "ar & boost::serialization::base_object
(*this)". Can I use a typedef for the base type, or do I have to use the original name expression? Does this all work for any kind of base: non-polymorphic, polymorphic, virtual inheritance, and/or multiple inheritance?
yes Robert Ramey
On Jul 16, 2008, at 2:07 PM, Robert Ramey wrote:
So I'll just define serialization in every class in the hierarchy, and make sure each non-root class calls "ar & boost::serialization::base_object
(*this)". Can I use a typedef for the base type, or do I have to use the original name expression? Does this all work for any kind of base: non-polymorphic, polymorphic, virtual inheritance, and/or multiple inheritance?
yes
I guess for multiple inheritance, one would serialize all the (direct) base classes. Do they have to be in declaration order? And for a virtual base class, wouldn't _every_ derived class have to serialize it in its code, since a derived class wouldn't know if it's the final type or not? How do you make sure the virtual base class gets serialized exactly once? Do you use reference counting here, or make sure that multiple-serialization is safe? -- Daryle Walker Mac, Internet, and Video Game Junkie darylew AT hotmail DOT com
Daryle Walker wrote:
On Jul 16, 2008, at 2:07 PM, Robert Ramey wrote:
So I'll just define serialization in every class in the hierarchy, and make sure each non-root class calls "ar & boost::serialization::base_object
(*this)". Can I use a typedef for the base type, or do I have to use the original name expression? Does this all work for any kind of base: non-polymorphic, polymorphic, virtual inheritance, and/or multiple inheritance?
yes
I guess for multiple inheritance, one would serialize all the (direct) base classes.
yep
Do they have to be in declaration order?
And for a virtual base class, wouldn't _every_ derived class have to serialize it in its code, since a derived class wouldn't know if it's the final type or not?
correct.
How do you make sure the virtual base class gets serialized exactly once?
boost serialization uses object tracking to avoid repetion and save space in the archive. You should look into "serialization traits" to be sure that its "turned on" for your class. Look at the test_diamond.cpp example.
Do you use reference counting here, or make sure that multiple-serialization is safe?
I where belt AND suspenders. a) We use object tracking to avoid repetition. b) the serialization library emits a compile time warning if you try to save a non-const object. This is intended to be sure that maintainig only one copy of the serialized object is sufficient. Robert Ramey
On Jul 16, 2008, at 4:32 PM, Robert Ramey wrote:
Daryle Walker wrote: [SNIP]
I guess for multiple inheritance, one would serialize all the (direct) base classes.
yep
Do they have to be in declaration order?
You didn't answer this one. (Unless the following "correct" is also for it.)
And for a virtual base class, wouldn't _every_ derived class have to serialize it in its code, since a derived class wouldn't know if it's the final type or not?
correct.
Of course, by "every," I meant just the derived classes that directly mention the virtual base class. But now that I think about it, would the other classes in the hierarchy need to explicitly serialize the virtual base class, although it's more of an implementation detail for them? (This means that one may have to change their serialization code if a base class adds or removes a virtual grand- base class.) -- Daryle Walker Mac, Internet, and Video Game Junkie darylew AT hotmail DOT com
participants (3)
-
Daryle Walker
-
Robert Ramey
-
Steve Sanders