Boost logo

Boost Users :

Subject: Re: [Boost-users] [serialization] [units] class_id and class_name to describe quantity dimension in serilization archive
From: Alfredo Correa (correaa_at_[hidden])
Date: 2011-09-25 04:56:57


Hi François,

> I would suggest that nothing should be changed in the core
> Boost/Serialization XML lib,

Sure. I am just seen what is the consensus on this.
The suggestion was only based in the fact that the implementation of
boost.serialization.XML was based on that XML is more human readable
than text files.
Now I will continue answering your questions.

> even if what you propose is fancy
> and even if it is an option (who would choose the "name of the class" to be
> saved ?

In the same way "name of the class" is chosen arbitrarily for
derived-from-base class during serialization.
Furthermore it can be ignored on reading.

> How to make sure that the convention for class naming is
> the same while reading and writing ? I guess it addresses some new
> problems...).

In the same way the convention for class naming is the same for
derived-from-base classes. Again, it can be ignored on reading.

> Rather than acking the BS lib, what you asked for could be probably easily
> implemented by some specific I/O manager dedicated for your
> specific need during I/O operations.

the "hacking" I suggested (i.e. the explicit code) does not hack
Boost.Serialization but it hacks Boost.Units.serialization, and it is
within the framework of Boost.Serialization. (the standalone
serialization/load/save function can be anything the user wants... I
guess, although I was not sure if it should throw or not)

> When I serialize some heterogeneous sets of objects
> in any kind of archives (text/XML/eos::portable_binary), I first store/load
> a "serialization tag" (std::string) that identifies the type/class of the
> next object to be stored|loaded. It is thus my responsability to manage a
> set of known tags associated to the
> classes I need to serialize.

Do you mean something like this?

void serialize(Archive & ar, Object obj, unsigned){
  ar & typeof(obj.a).name(); // just one way to store type
information, check enforce can be added in the same way I did in my
quantity example
  ar & obj.a;
  ar & "type of b"; // just one way to store type information
  ar & obj.b;
}

It is actually a good idea, Thanks!. (It is indeed similar to what I
did by storing the information but only inside the tag for
boost.quantity.)

> So it turns out that any serializable data is confined in some kind
> of virtual container, together with some kind of class ID:
> <archive>
>  serial_tag #0
>  data_record #0
(snip)
> Of course, it implies some smarter management of the I/O
> operations and some hard-coded factory (in a basic implementation).
> But it is very convenient for debugging and compatible with all kind of
> archives.

I got lost with the "hard-coded factory" but I get the idea.
>
> This mechanism is clearly a brute force approach and maybe some people
> consider this as inelegant. Anyway I have used this in production code for
> years and it is very robust.
>
> Note that it is different from the BOOST_CLASS_EXPORT mechanism
> which implies all your objects must be serialized by a base pointer
> and inherited from a unique abstract class/interface.

Yes, I noticed the difference. In fact my suggestion was based in
BOOST_CLASS_EXPORT but for cases where 1) the class name is not really
necesary, e.g. there is not derived pointer 2) object serialized is
not a pointer even. I liked the fact that the type information in the
currently implemention appears in the xml tag, seemed elegant.

> Could it be possible for you to use a wrapper class with the additional
> meta-info you need rather than to rely on some intrusive modification of the
> core functionality of the lib ?

I didn't investigate the use of wrappers but seems logical if the
core library can not be changed.
I found the description of wrapper
http://www.boost.org/doc/libs/1_47_0/libs/serialization/doc/wrappers.html
quite obfuscated
>
> struct quantity_wrapper<...>
> {
>  boost::units::quantity<...> q;
>  std::string                 more_info;
>  void serialize(...);
> };
>

I see, that is the wrapper, what next? do I replace quantity_wrapper
in all the classes where quantity is a member?

class Object{
  quantity_wrapper< dim1 > a; // was quantity< dim1 >
  quantity_wrapper< dim2 > b; // was quantity< di21 >
};

or do I serialize my class creating temporary quantity objects, don't
I need to use a wrapper of reference instead?

struct quantity_wrapper< Unit>{
  boost::units::quantity< Unit >& q; <--- reference ???
  std::string more_info;
  quantity_wrapper< Unit >(quantity< Unit > q_) : q(q_),
more_info(to_string(Unit())){}
  void serialize(...);
};
and then
serialize(Archive ar, Object o, unsigned){
  ar & quantity_wrapper<dim1>(o.a); // a is quantity<dim1>
  ar & quantity_wrapper<dim2 >(o.b); // b is quantity< dim2 >
}
do I need to specialize is_wrapper<quantity_wrapper< ... > >::value is true?

Thank you François, your post was very helpful to clarify the ideas. I
need to workout the details now.

Alfredo


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