[serialization] The constant object problem

Hello everybody, I've read the rationale for only allowing const trackable objects, but here is my problem : I want to serialize the following class : class C : boost::noncopyable { public: void setData(string s) {data = s;} //... }; int main() { C c; c.setData("Hello world"); vector <C*> v; v.push_back(&c); //... ar << c << c; } To have a c with meaningfull data, it cannot be const. I cannot create a local object that is a copy of the object (it is noncopyable) I do not think making the object untracked would be a good idea in this case (I might be wrong ?) So far, the best way I found to be able to serialize this object is : C const & cForSerialize = c; ar << cForSerialize << cForSerialize; But I do not think this is really elegant code. Is there a better alternative ? -- Loïc

A couple of comments/questions:
int main() { C c; c.setData("Hello world"); vector <C*> v; v.push_back(&c); // how do you expect to load (de-serialize) this? //... ar << c << c; // why have more than one here? }
To have a c with meaningfull data, it cannot be const.
but a reference to a const can be passed
I cannot create a local object that is a copy of the object (it is noncopyable)
use a reference
I do not think making the object untracked would be a good idea in this case (I might be wrong ?)
why not? What's the point of storing multiple copies if they are all the same?
So far, the best way I found to be able to serialize this object is :
C const & cForSerialize = c; ar << cForSerialize << cForSerialize;
But I do not think this is really elegant code. Is there a better alternative ?
factor our a save_function save_all(const C & c){ ar << c << c; } then use save(c) - only one possibility. Robert Ramey

On Tue, 23 Aug 2005 22:49:14 +0200, Loïc Joly wrote
Hello everybody,
I've read the rationale for only allowing const trackable objects, but here is my problem :
You'll probably want to search the mail archive -- there's been a long 'debate' about the merits of the enforcement of this in 1.33. As I expected it has taken only a few days to draw your email and a bug tracker request on the subject...
I want to serialize the following class :
class C : boost::noncopyable { public: void setData(string s) {data = s;} //... };
int main() { C c; c.setData("Hello world"); vector <C*> v; v.push_back(&c); //... ar << c << c; }
To have a c with meaningfull data, it cannot be const. I cannot create a local object that is a copy of the object (it is noncopyable) I do not think making the object untracked would be a good idea in this case (I might be wrong ?) So far, the best way I found to be able to serialize this object is :
C const & cForSerialize = c; ar << cForSerialize << cForSerialize;
But I do not think this is really elegant code. Is there a better alternative ?
So we could direct people to the docs we add the the following to the date-time docs: NOTE: due to a change in the serialization library interface, it is now required that all streamable objects be const prior to writing to the archive. The following template function will allow for this (and is used in the date_time tests). At this time no special steps are necessary to read from an archive. template<class archive_type, class T> void save_to(archive_type& ar, const T& val) { ar << val; } http://www.boost.org/doc/html/date_time/serialization.html Jeff

I just ported all our code using Boost.Serialization over to 1.33 today and came across similar problems so I thought I'd add some comments as additional data points. In all cases the problems were trivial to fix (making Save() member functions const for example) and only came across a single case of serialising a local variable in our code, the fix there was also relatively trivial, so all in all this didn't cause us much grief at all. The bigger problem I have is with the added included dependancy order (archives must be included before any other serialisation files) which caused a big rearrangment of our headers and was a pain to deal with. Luckily for us these were all internal headers but it just reminds me of the problems with header dependancy that boost\serialisation\shared_ptr.hpp had and that have been happily resolved in this release. This is a much bigger issue for me and something that really should be readdressed. cheers Martin -- No virus found in this outgoing message. Checked by AVG Anti-Virus. Version: 7.0.338 / Virus Database: 267.10.15/80 - Release Date: 23/08/2005

Martin Slater wrote:
I just ported all our code using Boost.Serialization over to 1.33 today and came across similar problems so I thought I'd add some comments as additional data points. In all cases the problems were trivial to fix (making Save() member functions const for example) and only came across a single case of serialising a local variable in our code, the fix there was also relatively trivial, so all in all this didn't cause us much grief at all.
OK - good to know - one more data point. I wonder if that local variable was being tracked. In this case you fixed a potential error.
The bigger problem I have is with the added included dependancy order (archives must be included before any other serialisation files) which caused a big rearrangment of our headers and was a pain to deal with. Luckily for us these were all internal headers but it just reminds me of the problems with header dependancy that boost\serialisation\shared_ptr.hpp had and that have been happily resolved in this release. This is a much bigger issue for me and something that really should be readdressed.
This is caused by two circumstances: a) for boost/serialization/export.hpp relies on previious inclusion of archive headers to know what archives to instantiate code for. This the same as version 1.32 b) The new requirement to support auto-linking. Auto-linking is forced by including a header whether or not the code is actually needed. The new headers skip those portions which provoke auto-linking if no archive headers are included. This permits headers to include serialization and still be included in other programs which don't use serialization without required link in a library which is not used. I've resolve to make the rule "include archive headers before serialization headers\" conditional on the usage of auto-linking. I'm not sure this is a great thing. It will address the concerns of those who have had an issue with this. But it will also require that a program which is developed on say GCC will have to suppress auto-linking with a compile time define when the program is compiled on a VC or borland. I'm still mulling this over. Robert Ramey

a) for boost/serialization/export.hpp relies on previious inclusion of archive headers to know what archives to instantiate code for. This the same as version 1.32
I've never added a new archive so I have never needed to include this so to me this is an implemenation detail that I shouldnt need to worry about until I implement a new archive type.
b) The new requirement to support auto-linking. Auto-linking is forced by including a header whether or not the code is actually needed. The new headers skip those portions which provoke auto-linking if no archive headers are included. This permits headers to include serialization and still be included in other programs which don't use serialization without required link in a library which is not used.
I've resolve to make the rule "include archive headers before serialization headers\" conditional on the usage of auto-linking. I'm not sure this is a great thing. It will address the concerns of those who have had an issue with this. But it will also require that a program which is developed on say GCC will have to suppress auto-linking with a compile time define when the program is compiled on a VC or borland. I'm still mulling this over.
I think this means that effectively auto-linking is just not worth it, I for one will immediately disable it as the pain the refactoring caused far outweighs adding a library to the link command. A simple solution would be to add serialization/auto_link.hpp that had to be included to get the auto linking feature, not ideal but far better than the include dependancy and could be a stopgap for 1.33.1 until a better solution is reached. cheers Martin -- No virus found in this outgoing message. Checked by AVG Anti-Virus. Version: 7.0.344 / Virus Database: 267.10.17/84 - Release Date: 29/08/2005

Martin Slater wrote:
a) for boost/serialization/export.hpp relies on previious inclusion of archive headers to know what archives to instantiate code for. This the same as version 1.32
I've never added a new archive so I have never needed to include this so to me this is an implemenation detail that I shouldnt need to worry about until I implement a new archive type.
This is not an question of a new archive type. The question is which archives_classes should code be instantiated for. Code for derived pointers serialized through a base class pointer is never explicitly called from the program. Without explicit instantiation it won't get generated. One option is to always generate code for all known archives. I rejected this due to code bloat considerations. The option I chose was to instantiate code for the archives actually used by the program. This is detected by checking the inclusion guards for archives. In order for this to work the archive headers have to come before export.hpp if BOOST_CLASS_EXPORT is used.
I'm still mulling this over.
I've spent some more time on this and I believe that I've managed to resolve the issues of header dependency so that the situation will be the same as 1.32. That is - no requirement regarding header sequence except for export.hpp as mentioned above. I'm testing this now and I'm hopeful this will be satisfactory to all concerned. Robert Ramey
participants (4)
-
Jeff Garland
-
Loïc Joly
-
Martin Slater
-
Robert Ramey