mirror of
https://github.com/boostorg/serialization.git
synced 2026-01-23 18:12:09 +00:00
443 lines
23 KiB
HTML
443 lines
23 KiB
HTML
<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<!--
|
|
(C) Copyright 2002-4 Robert Ramey - http://www.rrsd.com .
|
|
Use, modification and distribution is subject to 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)
|
|
-->
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
<link rel="stylesheet" type="text/css" href="../../../boost.css">
|
|
<link rel="stylesheet" type="text/css" href="style.css">
|
|
<title>Serialization - Implementation Notes</title>
|
|
</head>
|
|
<body link="#0000ff" vlink="#800080">
|
|
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary="header">
|
|
<tr>
|
|
<td valign="top" width="300">
|
|
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../boost.png" border="0"></a></h3>
|
|
</td>
|
|
<td valign="top">
|
|
<h1 align="center">Serialization</h1>
|
|
<h2 align="center">Implementation Notes</h2>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<hr>
|
|
<dl class="page-index">
|
|
<dt><a href="#functiontemplateordering">Partial Function Template Ordering</a>
|
|
<dt><a href="#charencoding">Character Encoding</a>
|
|
<dt><a href="#tempatesyntax">Template Invocation syntax</a>
|
|
<dt><a href="#partialtemplatespecialization">Partial Template Specialization</a>
|
|
<dt><a href="#othercompilerissues">Specific Compiler/Library Issues</a>
|
|
<dl class="page-index">
|
|
<dt><a href="#gcc3x">GCC 3.X, 4.X</a>
|
|
<dt><a href="#gcc295">GCC 2.95</a>
|
|
<dt><a href="#intel80">Intel 8.0</a>
|
|
<dt><a href="#vc80">Visual C++ 8.0</a>
|
|
<dt><a href="#vc71">Visual C++ 7.1</a>
|
|
<dt><a href="#vc70">Visual C++ 7.0</a>
|
|
<dt><a href="#vc6">Visual C++ 6.0</a>
|
|
<dt><a href="#borland">Borland 5.64 and 5.51</a>
|
|
<dt><a href="#comeau">Comeau 4.3.3</a>
|
|
<dt><a href="#codewarrior9">Code Warrior 9.x</a>
|
|
<dt><a href="#codewarrior">Code Warrior 8.3</a>
|
|
<dt><a href="#tru64">TRU64</a>
|
|
<dt><a href="#dinkumware">Dinkumware Library</a>
|
|
<dt><a href="#stlport">STLPort 4.5.3</a>
|
|
</dl>
|
|
</dl>
|
|
|
|
<h3><a name="functiontemplateordering">Partial Function Template Ordering</a></h3>
|
|
Not all C++ compilers correctly support partial function template ordering (PFTO).
|
|
For these compilers, the following code will fail to compile:
|
|
<pre><code>
|
|
template<class Archive, class T>
|
|
void serialize(
|
|
Archive & ar,
|
|
T & t,
|
|
const unsigned int file_version
|
|
){
|
|
...
|
|
}
|
|
|
|
template<class Archive, class T>
|
|
void serialize(
|
|
Archive & ar,
|
|
my_template<T> & t,
|
|
const unsigned int file_version
|
|
){
|
|
...
|
|
}
|
|
</pre></code>
|
|
The serialization library works around this issue by using a different
|
|
default definition of the first template:
|
|
<pre><code>
|
|
template<class Archive, class T>
|
|
void serialize(
|
|
Archive & ar,
|
|
T & t,
|
|
const unsigned long int file_version // Note: change to long
|
|
){
|
|
...
|
|
}
|
|
</pre></code>
|
|
Now, the second template is not matched with the first one so there
|
|
is no PFTO and no compile error. When the serialization library invokes
|
|
<pre><code>
|
|
serialize(ar, t, 0);
|
|
</pre></code>
|
|
the function declaration is first matched against templates with
|
|
an integer for the third argument. If there is a match, the matching
|
|
template is instantiated and later invoked. If there is no match,
|
|
an attempt is made to match other templates by converting arguments to other types.
|
|
In this case the third argument can be converted to long to match
|
|
the first template - which is the default. So in this case, the first
|
|
template will be instantiated and later invoked. We have managed to
|
|
use function overloading to achieve the same effect as PFTO
|
|
were it correctly implemented.
|
|
<p>
|
|
This depends upon undefined behavior of a compiler already
|
|
determined to be non-conforming. In other words, there is no
|
|
guarantee that this will work on all compilers. If a compiler does not
|
|
correctly support PFTO and this method cannot be used to workaround
|
|
it, non-intrusive serialization cannot be supported for that compiler.
|
|
As of this writing, such a compiler has not been encountered.
|
|
<p>
|
|
It turns out that using this "trick" can create problems with
|
|
compilers that DO correctly support PFTO. For this reason we
|
|
define a macro <code style="white-space: normal">BOOST_PTFO</code> which
|
|
is defined to be <code style="white-space: normal">long</code>
|
|
for non-conforming compilers and nothing for conforming ones. So
|
|
the default definition is really:
|
|
The serialization library works around this issue by using a different
|
|
default definition of the first template:
|
|
<pre><code>
|
|
template<class Archive, class T>
|
|
void serialize(
|
|
Archive & ar,
|
|
T & t,
|
|
const unsigned BOOST_PFTO int file_version // Note: change to BOOST_PFTO
|
|
){
|
|
...
|
|
}
|
|
</pre></code>
|
|
|
|
<h3><a name="charencoding">Character Encoding</a></h3>
|
|
The whole question of character encoding combined with wide characters
|
|
is much more complicated than it would seem to be. The current library
|
|
defines in 3 formats (text, binary, and XML), wide and narrow characters,
|
|
and attempts to be portable between compiler libraries. The results of
|
|
a rather long consideration of all these factors has been to set
|
|
default encoding according to the following rules.
|
|
<ul>
|
|
<li>All text archives (i.e. <code style="white-space: normal">text_?archive</code>) will produce
|
|
text output in the current stream <code style="white-space: normal">locale</code>. Generally this will
|
|
produce no changes in string data.
|
|
<li>To produce binary output with Microsoft compilers, the stream
|
|
will have to be opened with mode <code style="white-space: normal">ios::binary</code>.
|
|
Failure to do so will result in 0x0d characters (carriage-return)
|
|
characters being removed from the input stream if they are followed
|
|
by a 0x0a character (line-feed). This could corrupt the input
|
|
and make the file unreadable. On UNIX systems the <code style="white-space: normal">ios::binary</code>
|
|
is not required and is ignored if used.
|
|
<li>character XML archives (i.e. xml_oarchive) will produce XML output
|
|
with characters encoded according to the current stream <code style="white-space: normal">locale</code>.
|
|
<li>wide character XML archives (i.e. xml_woarchive) will produce
|
|
files encoded in UTF-8.
|
|
</ul>
|
|
This character encoding is implemented by changing the <code style="white-space: normal">locale</code> of the
|
|
i/o stream used by an archive when the archive is constructed, the stream
|
|
locale is changed back to its original value. This action can be overridden
|
|
by specifying <code style="white-space: normal">boost::archive::no_codecvt</code>
|
|
when the archive is opened. In this case, the stream <code style="white-space: normal">locale</code> will
|
|
not be changed by the serialization library.
|
|
<p>
|
|
Note that the code conversion included for wide character text and XML
|
|
archives could alter <code style="white-space: normal">std::string</code> data stored in archives.
|
|
Suppose a normal (multi-byte) character string
|
|
is written to a wide character stream. Our system uses the current <code style="white-space: normal">locale</code>
|
|
to translate it to a wide character string before writing it out.
|
|
Upon reading, it is translated back to a (multi-byte)string.
|
|
If the <code style="white-space: normal">locale</code> on the platform that reads the archive is different than
|
|
the <code style="white-space: normal">locale</code> on the platform that wrote the stream, the actual string data
|
|
may be altered by the serialization process. To avoid this, either
|
|
avoid usage of <code style="white-space: normal">locale</code> dependent multi-byte strings or be sure that
|
|
the <code style="white-space: normal">locale</code> is set correctly before reading the archive.
|
|
<p>
|
|
To produce wide character text output (i.e. 16 bit characters on Win32 systems),
|
|
do the following.
|
|
<ul>
|
|
<li>Open a wide character stream.
|
|
<li>Alter the stream <code style="white-space: normal">locale</code> to use
|
|
<code style="white-space: normal">boost::archive::codecvt_null<OStream::char_type></code>
|
|
<li>Create the archive with the flag <code style="white-space: normal">no_codecvt</code>.
|
|
</ul>
|
|
Naturally, the input process has to be symmetrical.
|
|
<h3><a name="partialtemplatespecialization">Partial Template Specialization</a></h3>
|
|
Compilers which fail to support partial template specialization will fail to compile
|
|
the following code. To make this compile, the <code style="white-space: normal">const</code> has to be removed.
|
|
<pre><code>
|
|
void f(A const* a, text_oarchive& oa)
|
|
{
|
|
oa << a;
|
|
}
|
|
</code></pre>
|
|
<h3><a name="tempatesyntax">Template Invocation syntax</a></h3>
|
|
Some compilers may not recognize the syntax:
|
|
<pre><code>
|
|
ar.template register_type<T>();
|
|
</code></pre>
|
|
for "registering" derived pointers of polymorphic classes. The actual
|
|
function prototype is:
|
|
<pre><code>
|
|
template<T>
|
|
void register_type(T * t = NULL);
|
|
</code></pre>
|
|
so that one may write <code style="white-space: normal">ar.register_type(static_cast<T *>(NULL))</code> instead of
|
|
the syntax described above.
|
|
</ul>
|
|
<h3><a name="othercompilerissues">Specific Compiler/Library Issues</a></h3>
|
|
<h4><a name="gcc3x">GCC 3.X, 4.X</a></h4>
|
|
<ul>
|
|
<li>GCC versions for Cygwin and MinGW fail to support wide character I/O.
|
|
So all tests using wide char I/O fail. Note that if wide character I/O support
|
|
is added with STLPort, all tests complete successfully.
|
|
<li>This compiler generates long warning messages related to the usage of
|
|
non virtual destructors in polymorphic classes. These warnings have been
|
|
carefully considered and the code that generates these warning has been
|
|
unchanged. In this case the warning should should be ignored as in certain
|
|
usages of the library, making the destructors virtual could lead to problems.
|
|
As an alternative, base class destructors have been made "protected" to
|
|
address the concerns that motivate these warning messages. When building
|
|
the serialization library and tests with bjam, these warnings are suppressed.
|
|
When building one's own applications, these warnings can be suppressed by
|
|
adding the following to the compiler command line:
|
|
<pre><code>
|
|
-Wno-non-virtual-dtor
|
|
-Wno-ctor-dtor-privacy
|
|
</code></pre>
|
|
</ul>
|
|
<h4><a name="gcc295">GCC 2.95</a></h4>
|
|
All of the above plus:<br>
|
|
<ul>
|
|
<li>The serialization library depends on the templated stream
|
|
implementation to function properly.
|
|
So STLPort must be used to build the library.
|
|
<li>Polymorphic archive tests fail.
|
|
<li>XML serialization only works with version 1.6x of spirit. In order to build
|
|
and use this library with this compiler, one must use version 1.6x rather than the
|
|
latest version shipped with boost. See <a href="release.html">Release Notes</a>.
|
|
</ul>
|
|
<h4><a name="intel80">Intel C++ 8.0</a></h4>
|
|
No known issues. All tests compile and run in debug and release modes.
|
|
|
|
<h4><a name="vc80">Visual C++ 8.0</a></h4>
|
|
This compiler emits warnings for calls to functions from the standard
|
|
library which are deemed security risks. The serialization depends upon
|
|
making some of these calls so programs which use the serialization library
|
|
will get warning messages. These messages can be suppressed from the command
|
|
line by including the following switch:
|
|
<pre><code>
|
|
/wd4996
|
|
</code></pre>
|
|
|
|
<h4><a name="vc71">Visual C++ 7.1</a></h4>
|
|
Derivation from an archive class defined in a DLL as described in ... will not work.
|
|
This is due to the way that VC++ handles templated code with __decl(dllexport) and
|
|
__decl(dllimport) specifications. Basically, this compiler requires that all the
|
|
instantiations have the same specification - even though they have different
|
|
template arguments. The example <code style="white-space: normal">
|
|
demo_portable_iarchive.cpp</code> would have to be reformulated as a library or dll
|
|
similar to the pre-defined archives in order to function.
|
|
<p>
|
|
This compiler does not have RTTI or exception handling turned on by default. Although
|
|
they are not strictly necessary to use the serialization package, the example and test
|
|
programs presume that they are enabled. So be sure your command line or IDE settings
|
|
enable these features if you want to build and run these programs.
|
|
<p>
|
|
This compiler can treat <code style="white-space: normal">wchar_t</code> as either
|
|
a short integer or an intrinsic type.
|
|
If <code style="white-space: normal">/Zc:wchar_t</code> is specified on the
|
|
compile command line, <code style="white-space: normal">wchar_t</code> will be
|
|
considered an intrinsic type - otherwise
|
|
it will be treated as a synonym for a 16 bit integer. The library can be used
|
|
either way - <strong>BUT</strong> - both the libray <strong>AND</strong> the application
|
|
must be compiled with the same switch settings. Note that <code style="white-space: normal">BJAM</code>
|
|
includes this switch by default. So if want to use the libraries that
|
|
<code style="white-space: normal">BJAM</code> builds, you should include this switch
|
|
when you compile your own applications.
|
|
<h5>Using the Visual C++ IDE</h5>
|
|
The library includes a VC++ 7.1 "Solution" - <code style="white-space: normal">BoostSerializationLibrary</code>
|
|
along with a set of project files - one for each demo and test. Consider the following if you
|
|
decide to use these configurations.
|
|
<ul>
|
|
<li>The projects assume that the tests have been built with bjam using the default
|
|
locations. This will result in a <code style="white-space: normal">bin</code> subdirectory
|
|
within one's main boost directory. Below this there is a whole structure which maintains
|
|
object and library files according to the type of build. The easiest way to build this is to
|
|
invoke the runtest script which uses bjam (see below). If the libraries are not in these locations,
|
|
the projects will have to be modified accordingly.
|
|
<li>There are project configurations for all the combinations of build variants that boost
|
|
supports. That is for release, debug, static, static multi-threading, etc..
|
|
<li>If you want to use/debug the DLL versions of libraries and corresponding tests, alter
|
|
the project file to define <code style="white-space: normal">BOOST_ALL_DYN_LINK=1</code>.
|
|
Note that for the executables to run, the <code style="white-space: normal">PATH</code>
|
|
environmental variable will have to include the directories that contain the DLL versions of
|
|
the boost libraries.
|
|
<li>If you have difficulties building your own projects and linking with the boost libraries,
|
|
compare the project settings of your own projects with the ones here. VC sometimes requires
|
|
consistent settings between projects and the libraries they use in order to link properly.
|
|
In particular, check support for exceptions, runtime typing(RTTI), and intrinsic support for
|
|
wide characters. The standard version of this library presumes that these facilities are
|
|
enabled. Projects generated by the IDE wizard do not have these features enabled by default.
|
|
<li>Frequently when trying to build a project or view project properties, one is presented with
|
|
a message box with the message "unspecified error". This seems to occur when one changes the
|
|
build configuration selection. It turns out this can be "fixed" by going to the "Build"
|
|
menu item, selecting "Configuration Manager" and selecting a build configuration for the project
|
|
you're working with.
|
|
<li>To test that boost libraries are built correctly, one can build and test them the way we do.
|
|
This entails:
|
|
<ol>
|
|
<li>downloading a copy of bjam.exe
|
|
<li>building process_jam_log
|
|
<li>building compiler_status
|
|
<li>invoking runtest.bat
|
|
</ol>
|
|
This will build the serialization library and run the tests on your system. If there are more than a
|
|
a couple of test failures, you likely won't be able to get your own projects working. If most of the
|
|
tests pass, you can be confident that your own projects will work once you get your project settings
|
|
in sync with those included here.
|
|
</ul>
|
|
|
|
<h4><a name="vc70">Visual C++ 7.0</a></h4>
|
|
<ul>
|
|
<li>The "pimpl" demo fails to link. Cause and workaround for this is unknown
|
|
<li>XML serialization only works with version 1.6x of spirit. In order to build and use this
|
|
library with this compiler, one must use version 1.6x rather than the latest version
|
|
shipped with boost. See <a href="release.html">Release Notes</a>.
|
|
<li>This compiler does not support partial template specialization.
|
|
The implementation of the new <code>shared_ptr</code> serialization depends upon
|
|
compiler support for partial template specialization. This compiler doesn't implement this
|
|
feature. In order to serialize <code style="white-space: normal">shared_ptr<A></code>,
|
|
invoke the macro <code style="white-space: normal">BOOST_SERIALIZATION_SHARED_PTR(A)</code>
|
|
in the header code.
|
|
<li>Lack of support for partial template specialization also creates problems for
|
|
serialization of <code style="white-space: normal">std::map</code>. In order to serialize
|
|
instances of this type include the invocation of BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION
|
|
for the key type of the map.
|
|
</ul>
|
|
<h4><a name="vc6">Visual C++ 6.5</a></h4>
|
|
all the above issues for Visual C++ 7.0 plus:
|
|
<ul>
|
|
<li>Out of line template definitions are not recognized and fail with a confusing
|
|
error message. To function save/load/serialize member function templates must be defined
|
|
within the class definition. This feature is essential to <code style="white-space: normal">demo_pimpl</code>. Hence,
|
|
this program will fail to compile. In this case the problem can't be worked around and
|
|
still demonstrate this facility.
|
|
<li>This compiler does not support <code style="white-space: normal">wchar_t</code> as a separate type. It defines
|
|
<code style="white-space: normal">wchar_t</code> as an alias for <code style="white-space: normal">short int</code>. In general things will still
|
|
function. However certain customizations, such as overloading archive operators for
|
|
saving/loading wide character arrays would produce surprises in this environment.
|
|
<li>Under certain circumstances, a program will fail to link with the message:
|
|
LIN1179 - "invalid or corrupt file: duplicate comdat". According
|
|
to <a href="http://groups.google.com/groups?th=8a05c82c4ffee280">
|
|
http://groups.google.com/groups?th=8a05c82c4ffee280
|
|
</a> (look for P78)
|
|
A LNK1179 error occurs when:
|
|
<ul>
|
|
<li>The template class takes at least two arguments.
|
|
<li>The template is used at least two times with identical first
|
|
and different second arguments.
|
|
<li>The static member variable is of an object type with at least one
|
|
base class. (In another scenario it also occurred using a member
|
|
without a base class.)
|
|
</ul>
|
|
Working around this in the implementation of the library for this compiler
|
|
entailed a ridiculous amount of effort. Even so, the effort wasn't entirely successful.
|
|
With this compiler, this message will still appear under the following conditions:
|
|
<ul>
|
|
<li>When serializing a class with multiple base classes. This problem causes two
|
|
failure in the test suite. I have been unable to devise a way to work around this.
|
|
<li>Using more than one kind of archive in the same code module. This should be easy
|
|
to work around in practice.
|
|
</ul>
|
|
<li>Code modules exceeding some undetermined size that use the library will fail with
|
|
<i>fatal error C1204: compiler limit : internal structure overflow</i>. This can be addressed
|
|
by dividing the module into smaller ones.
|
|
</ul>
|
|
<h4><a name="borland">Borland 5.64 and 5.51</a></h4>
|
|
<ul>
|
|
<li><code style="white-space: normal">enum</code> data members cannot be serialized.
|
|
Conversion to/from integers will work around the problem.
|
|
<li>If class serialize functions are not accessible either by making them public or by
|
|
including <code style="white-space: normal">friend</code> declarations as described in
|
|
<a href="serialization.html#member">Class Serialization - Member Function</a>, the code
|
|
will compile but fail at runtime.
|
|
<li>Tests using custom extended type which doesn't use RTTI fails. (5.64 only !).
|
|
<li>Tests built in release mode fail. This seems to be an issue with the boost test system
|
|
with this compiler.
|
|
<li>XML serialization only works with version 1.6x of spirit. In order to build
|
|
and use this library with this compiler, one must use version 1.6x rather than the
|
|
latest version shipped with boost. See <a href="release.html">Release Notes</a>.
|
|
</ul>
|
|
<h4><a name="comeau">Comeau 4.3.3</a></h4>
|
|
<ul>
|
|
<li>This compiler fails to make a DLL with export under windows.
|
|
<li>The associated library - libcomo fails when using a codecvt facet.
|
|
This generates a failure with all wide character archives.
|
|
<li>the test_set fails by going into an infinite memory leak.
|
|
</ul>
|
|
|
|
<h4><a name="codewarrior9">Code Warrior 9.x</a></h4>
|
|
<ul>
|
|
<li>Some tests and demos fail - still under investigation
|
|
</ul>
|
|
|
|
<h4><a name="codewarrior">Code Warrior 8.3</a></h4>
|
|
all the above issues for Code Warrior 9.x plus:
|
|
<ul>
|
|
<li>This compiler only supports templated streams with the static library version.
|
|
<li>The above inhibits the build of DLL versions of the library.
|
|
<li>Some demos fail - still under investigation
|
|
</ul>
|
|
|
|
<h4><a name="tru64">TRU64</a></h4>
|
|
All tests and demos pass except for test_variant. Boost Variant doesn't function
|
|
wih this compiler
|
|
|
|
<h4><a name="dinkumware">Dinkumware Library</a></h4>
|
|
Several compilers, including Visual C++ 6.0, use an older dinkumware library.
|
|
These platforms have several issues:
|
|
<ul>
|
|
<li>The dinkumware library shipped with this compiler does not change the locale facet
|
|
of an i/o stream unless the <code style="white-space: normal">imbue</code> function is called before the
|
|
stream is opened. In order to use this library with this environment to generate UTF-8
|
|
files, one cannot depend on the "automatic" setting of locale that archives implement. The
|
|
stream locale must be set explicitly on the stream before an archive is opened on it. The
|
|
archive should be opened with the <code style="white-space: normal">no_codecvt</code> flag. Note this problem will
|
|
occur on all compilers shipped with this library.
|
|
<li>Other issues have been worked around in the file.
|
|
<a href="../../../boost/archive/dinkumware.hpp" target="dinkumware_hpp">dinkumware.hpp</a>
|
|
</ul>
|
|
|
|
<h4><a name="stlport">STLPort 4.5.3</a></h4>
|
|
<ul>
|
|
<li>when built to use the dynamic linking versions of the C++ runtime code (<runtime-link>dynamic)
|
|
all tests fail to link. This is due to a missing symbol in the stlport library related
|
|
to custom codecvt facets.
|
|
<li>the test_set fails to run correctly. It seems the hashed set iterator doesn't
|
|
implement the ++ operator correctly. This causes the test to fail by consuming all available
|
|
memory. Given this, this test is commented out.
|
|
</ul>
|
|
|
|
<hr>
|
|
<p>Revised 1 November, 2004
|
|
<p><i>© Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 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)
|
|
</i></p>
|
|
</body>
|
|
</html>
|