|
SerializationRationale |
typeid
information is not included in archivesI found that persistence is often used to refer to something quite different. Examples are storage of class instances (objects) in database schema [4] This library will be useful in other contexts besides implementing persistence. The most obvious case is that of marshalling data for transmission to another system.
Archive classes are NOT derived from streams even though they have similar syntax rules.
long long
,
__int64
,
etc.) resulted in messy and fragile code. Replacing this with templates
and letting the compiler generate the code for the primitive types actually
used, resolved this problem. Of course, the ripple effects of this design
change were significant, but in the end led to smaller, faster, more
maintainable code.
std::strings
are treated specially in text filesTreating strings as STL vectors would result in minimal code size. This was not done because:
std::string
and std::wstring
.
Presumably they optimize appropriately.
std::basic_string
are in fact handled
as vectors of the element type.
typeid
information is not included in archives
I originally thought that I had to save the name of the class specified by std::type_of::name()
in the archive. This created difficulties as std::type_of::name()
is not portable and
not guaranteed to return the class name. This makes it almost useless for implementing
archive portability. This topic is explained in much more detail in
[7] page 206. It turned out that it was not necessary.
As long as objects are loaded in the exact sequence as they were saved, the type
is available when loading. The only exception to this is the case of polymorphic
pointers never before loaded/saved. This is addressed with the register_type()
and/or export
facilities described in the reference.
In effect, export
generates a portable equivalent to
typeid
information.
BOOST_STATIC_ASSERT
.
Here, we refer to this as a compile time trap.
T t;
ar << t;
unless the tracking_level serialization trait is set to "track_never". The following
will compile without problem:
const T t
ar << t;
Likewise, the following code will trap at compile time:
T * t;
ar >> t;
if the tracking_level serialization trait is set to "track_never".
This behavior has been contraversial and may be revised in the future. The criticism
is that it will flag code that is in fact correct and force users to insert
const_cast
. My view is that:
class construct_from
{
...
};
void main(){
...
Y y;
construct_from x(y);
ar << x;
}
Suppose that there is no trap as described above.
void main(){
...
Y y;
construct_from x(y);
ar << x;
...
x.f(); // change x in some way
...
ar << x
}
Again no problem. He gets two different of copies in the archive, each one is different. That is he gets exactly what he expects and is naturally delighted.
class K {
shared_ptr <construct_from> z;
template <class Archive>
void serialize(Archive & ar, const unsigned version){
ar << z;
}
};
He builds and runs the program and tests his new functionality. It works great and he's delighted.
BOOST_CLASS_TRACKING(construct_from, track_never)
shared_ptr<construct_from>
is not going to have a single raw pointer shared amongst the instances. Each loaded
shared_ptr<construct_from>
is going to
have its own distinct raw pointer. This will break
shared_ptr
and cause a memory leak. Again,
The cause of this problem is very far removed from the point of discovery. It could
well be that the problem is not even discovered until after the archives are loaded.
Now we not only have difficult to find and fix program bug, but we have a bunch of
invalid archives and lost data.
ar << x;
const_cast
- because it looks bad. So he'll just make the following change an move on.
Y y;
const construct_from x(y);
ar << x;
Things work fine and he moves on.
Y y;
const construct_from x(y);
...
x.f(); // change x in some way ; compile error f() is not const
...
ar << x
He's mildly annoyed now he tries the following:
const
from const construct_from
above - damn now he
gets the trap. If he looks at the comment code where the
BOOST_STATIC_ASSERT
occurs, he'll do one of two things
const_cast
and fire off a complaint to the list and mabe they will fix it.
In this case, the story branches off to the previous scenario.
BOOST_CLASS_TRACKING(construct_from, track_never)
construct_from
trait has been set to
"track_never" so he should always get copies and the log should be what we expect.
BOOST_CLASS_TRACKING
that
was inserted. Now the second trap is avoided, But damn - the first trap is
popping up again. Eventually, after some code restructuring, the differing
requirements of serializating construct_from
are reconciled.
© Copyright Robert Ramey 2002-2004. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)