[serialization] serializing a pointer without causing object tracking

Hi everyone, Hi Robert, in case you'd like to answer this one, because I have a rather specific question about your library. Thank you in advance! I'd like to serialize an object and later reconstruct it from the serialized data: void save(T const &t){ ar << t; } T* load(){ T *t=new T(); //error ar >> *t; } T might not have a default constructor. so load_construct_data should be used. apparently the way to do this is to serialize through a pointer: void save(T const *t){ ar << t; } T *load(){ T *t; ar >> t; } this works, but it causes the type T to be tracked, if its object tracking is set to track_selectively. I don't want that. but I can't set it to track_never either, because if the type is serialized at another point in the program through a pointer, the type should be tracked. is there a solution to this? is there a serialization wrapper that says "don't track this type just because of this pointer"? what comes to mind as a solution is serializing as an object, and calling load/save_construct_data manually. but then there is another problem: void save(T const &t){ save_construct_data(t,version<T>::value); ar << t; } void load(T *unconstructed_t){ load_construct_data(unconstructed_t, ??? ); ar >> *t; } if the implementation level of T is object_class_info, the object version is loaded from the preamble when the object itself is loaded. there is no in between loading the version and loading the object, it's entirely handled in the non-header part of the library. so basically I have a solution when the implementation level is object_serializable (no version info, call load_construct_data manually), and when tracking is set to track_never (serialize as a pointer). but not for the default case, object_class_info with track_selectively. am I missing something? Stefan

Stefan Strasser wrote:
Hi everyone, Hi Robert, in case you'd like to answer this one, because I have a rather specific question about your library. Thank you in advance!
I'd like to serialize an object and later reconstruct it from the serialized data:
void save(T const &t){ ar << t; } T* load(){ T *t=new T(); //error ar >> *t; }
T might not have a default constructor. so load_construct_data should be used. apparently the way to do this is to serialize through a pointer:
void save(T const *t){ ar << t; } T *load(){ T *t; ar >> t; }
this works, but it causes the type T to be tracked, if its object tracking is set to track_selectively. I don't want that. but I can't set it to track_never either, because if the type is serialized at another point in the program through a pointer, the type should be tracked.
is there a solution to this? is there a serialization wrapper that says "don't track this type just because of this pointer"?
so you want "don't track this particular save - but leave others as normal" Try something like class A .... class UntrackedA : public A { ... }; BOOST_SERIALIZATION_TRACK(UntrackedA, track_never); .. A a; const Untracked & A ua(a); ar << ua; ... Untracked & A ua2(a); ar >> ua2; That would what would first occur to me. Robert Ramey

Am 30.03.2013 19:03, schrieb Robert Ramey:
is there a solution to this? is there a serialization wrapper that says "don't track this type just because of this pointer"?
so you want "don't track this particular save - but leave others as normal"
Try something like
class A ....
class UntrackedA : public A { ... };
BOOST_SERIALIZATION_TRACK(UntrackedA, track_never);
interesting idea. does this eventually track the object if the base class of UntrackedA is track_selectively and saved through a pointer anywhere else? for example, an object graph that stores a pointer to its own root (through intermediaries in practice): class A{ //tracking level: selectively void serialize(...){ ar & a; } A *a; //==this }; class UntrackedA : A{ //tracking level: never void serialize(...){ ar & base_object<A>(*this); } } void save(UntrackedA *a){ ar << a; } is "a" serialized twice, or tracked because of track_selectively and the pointer serialization in A::serialize?

Stefan Strasser wrote:
Am 30.03.2013 19:03, schrieb Robert Ramey:
is there a solution to this? is there a serialization wrapper that says "don't track this type just because of this pointer"?
so you want "don't track this particular save - but leave others as normal" Try something like
class A ....
class UntrackedA : public A { ... };
BOOST_SERIALIZATION_TRACK(UntrackedA, track_never);
interesting idea. does this eventually track the object if the base class of UntrackedA is track_selectively and saved through a pointer anywhere else?
for example, an object graph that stores a pointer to its own root (through intermediaries in practice):
class A{ //tracking level: selectively void serialize(...){ ar & a; } A *a; //==this };
class UntrackedA : A{ //tracking level: never void serialize(...){ ar & base_object<A>(*this); } }
void save(UntrackedA *a){ ar << a; }
is "a" serialized twice, or tracked because of track_selectively and the pointer serialization in A::serialize?
lol - I didn't think about this when I responded though I'm sure I did it when I made the code. I'm going to speculate since it's easier than doing any work. class UntrackedA : public A { // instead of this: void serialize(Archive & ar, unsigned int file_version){ boost::serialization:base_object<A>(*this); } // consider this void serialize(Archive & ar, unsigned int file_version){ ar & m_a; // where m_a is a member of a ar & m_b; // other member of a etc ... } ... }; Robert Ramey

Robert Ramey wrote:
Stefan Strasser wrote:
Am 30.03.2013 19:03, schrieb Robert Ramey:
is there a solution to this? is there a serialization wrapper that says "don't track this type just because of this pointer"?
so you want "don't track this particular save - but leave others as normal" Try something like
class A ....
class UntrackedA : public A { ... };
BOOST_SERIALIZATION_TRACK(UntrackedA, track_never);
interesting idea. does this eventually track the object if the base class of UntrackedA is track_selectively and saved through a pointer anywhere else?
for example, an object graph that stores a pointer to its own root (through intermediaries in practice):
class A{ //tracking level: selectively void serialize(...){ ar & a; } A *a; //==this };
class UntrackedA : A{ //tracking level: never void serialize(...){ ar & base_object<A>(*this); } }
void save(UntrackedA *a){ ar << a; }
is "a" serialized twice, or tracked because of track_selectively and the pointer serialization in A::serialize?
lol - I didn't think about this when I responded though I'm sure I did it when I made the code. I'm going to speculate since it's easier than doing any work.
class UntrackedA : public A { // instead of this: void serialize(Archive & ar, unsigned int file_version){ boost::serialization:base_object<A>(*this); } // consider this void serialize(Archive & ar, unsigned int file_version){ ar & m_a; // where m_a is a member of a ar & m_b; // other member of a etc ... } ...
better yet try this: class UntrackedA : public A { }; just use the base class implementation of serialize function via inheritance Robert Ramey
Robert Ramey

I had the same problem, where I did not want a particular serialized
object to be tracked. It happened when I serialize an object that is
created on the stack and the class is usually tracked but I don't want the
instance on the stack to be tracked.
I've done a little template class that directly calls the serialize method
of the target class, and it works well...
template<typename T>
struct NoTracking : public T, public wrapper_traits<
NoTracking<T>,
object_class_info,
track_never,
version<T>::value >
{
NoTracking() : T() { }
template<typename T0>
NoTracking(const T0& t0) : T(t0) { }
template
Stefan Strasser wrote:
Am 30.03.2013 19:03, schrieb Robert Ramey:
is there a solution to this? is there a serialization wrapper that says "don't track this type just because of this pointer"?
so you want "don't track this particular save - but leave others as normal" Try something like
class A ....
class UntrackedA : public A { ... };
BOOST_SERIALIZATION_TRACK(UntrackedA, track_never);
interesting idea. does this eventually track the object if the base class of UntrackedA is track_selectively and saved through a pointer anywhere else?
for example, an object graph that stores a pointer to its own root (through intermediaries in practice):
class A{ //tracking level: selectively void serialize(...){ ar & a; } A *a; //==this };
class UntrackedA : A{ //tracking level: never void serialize(...){ ar & base_object<A>(*this); } }
void save(UntrackedA *a){ ar << a; }
is "a" serialized twice, or tracked because of track_selectively and the pointer serialization in A::serialize?
lol - I didn't think about this when I responded though I'm sure I did it when I made the code. I'm going to speculate since it's easier than doing any work.
class UntrackedA : public A { // instead of this: void serialize(Archive & ar, unsigned int file_version){ boost::serialization:base_object<A>(*this); } // consider this void serialize(Archive & ar, unsigned int file_version){ ar & m_a; // where m_a is a member of a ar & m_b; // other member of a etc ... } ...
better yet try this: class UntrackedA : public A { }; just use the base class implementation of serialize function via inheritance Robert Ramey
Robert Ramey
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Thanks for both your answers! Your proposals:
Robert Ramey wrote: just use the base class implementation of serialize function via inheritance
and Am 02.04.2013 16:35, schrieb Guy Premont:
template<class Archive> void serialize(Archive & ar, const unsigned int version) { boostVx::serialization::serialize(ar, static_cast
(*this), version); } };
...have the problem that even though it prevents tracking the actual
object reference of type T - which might be track_selectively - never
reaches the serialization library. only a pointer of type NoTracking<T>
is passed on, which is track_never. (note: serialization::serialize()
does not call basic_oarchive::save_object())
so if the object graph stores a pointer to the root object, the root
object is serialized twice and duplicated on deserialization.
this might seem like an outlandish example, but a simple tree with nodes
that have parent pointers is one.
on the other hand, if the object reference DOES reach the serialization
library it is just like serializing the object, instead of a pointer,
and I have the problem described in my initial email (load_construct_data).
the only solution I could come up with is duplicating some
implementation details in "namespace archive" and create a
nontracking_pointer_oserializer and call basic_oarchive::save_pointer()
directly:
A *a=new A;
nontracking_pointer_oserializer
participants (3)
-
Guy Premont
-
Robert Ramey
-
Stefan Strasser