C++ Boost

Serialization

Implementation Notes


Partial Function Template Ordering
Character Encoding
Template Invocation syntax
Partial Template Specialization
Specific Compiler/Library Issues
GCC 3.X, 4.X
GCC 2.95
Intel 8.0
Visual C++ 8.0
Visual C++ 7.1
Visual C++ 7.0
Visual C++ 6.0
Borland 5.64 and 5.51
Comeau 4.3.3
Code Warrior 9.x
Code Warrior 8.3
TRU64
Dinkumware Library
STLPort 4.5.3

Partial Function Template Ordering

Not all C++ compilers correctly support partial function template ordering (PFTO). For these compilers, the following code will fail to compile:

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
){
    ...
}
The serialization library works around this issue by using a different default definition of the first template:

template<class Archive, class T>
void serialize(
    Archive & ar, 
    T & t, 
    const unsigned long int file_version  // Note: change to long
){
    ...
}
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

serialize(ar, t, 0);
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.

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.

It turns out that using this "trick" can create problems with compilers that DO correctly support PFTO. For this reason we define a macro BOOST_PTFO which is defined to be long 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:


template<class Archive, class T>
void serialize(
    Archive & ar, 
    T & t, 
    const unsigned BOOST_PFTO int file_version  // Note: change to BOOST_PFTO
){
    ...
}

Character Encoding

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. This character encoding is implemented by changing the locale 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 boost::archive::no_codecvt when the archive is opened. In this case, the stream locale will not be changed by the serialization library.

Note that the code conversion included for wide character text and XML archives could alter std::string data stored in archives. Suppose a normal (multi-byte) character string is written to a wide character stream. Our system uses the current locale 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 locale on the platform that reads the archive is different than the locale 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 locale dependent multi-byte strings or be sure that the locale is set correctly before reading the archive.

To produce wide character text output (i.e. 16 bit characters on Win32 systems), do the following.

Naturally, the input process has to be symmetrical.

Partial Template Specialization

Compilers which fail to support partial template specialization will fail to compile the following code. To make this compile, the const has to be removed.

void f(A const* a, text_oarchive& oa)
{
  oa << a;
}

Template Invocation syntax

Some compilers may not recognize the syntax:

ar.template register_type<T>();
for "registering" derived pointers of polymorphic classes. The actual function prototype is:

template<T>
void register_type(T * t = NULL);
so that one may write ar.register_type(static_cast<T *>(NULL)) instead of the syntax described above.

Similarly, the expression


ar.template get_helper<Helper>();
that recovers a helper object of type Helper might pose problems, in which case the following alternative syntax can be used:

ar.get_helper(static_cast<Helper *>(NULL));

Specific Compiler/Library Issues

GCC 3.X, 4.X

GCC 2.95

All of the above plus:

Intel C++ 8.0

No known issues. All tests compile and run in debug and release modes.

Visual C++ 8.0

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:

    /wd4996
    

Visual C++ 7.1

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 demo_portable_iarchive.cpp would have to be reformulated as a library or dll similar to the pre-defined archives in order to function.

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.

This compiler can treat wchar_t as either a short integer or an intrinsic type. If /Zc:wchar_t is specified on the compile command line, wchar_t 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 - BUT - both the libray AND the application must be compiled with the same switch settings. Note that BJAM includes this switch by default. So if want to use the libraries that BJAM builds, you should include this switch when you compile your own applications.

Using the Visual C++ IDE
The library includes a VC++ 7.1 "Solution" - BoostSerializationLibrary along with a set of project files - one for each demo and test. Consider the following if you decide to use these configurations.

Visual C++ 7.0

Visual C++ 6.5

all the above issues for Visual C++ 7.0 plus:

Borland 5.64 and 5.51

Comeau 4.3.3

Code Warrior 9.x

Code Warrior 8.3

all the above issues for Code Warrior 9.x plus:

TRU64

All tests and demos pass except for test_variant. Boost Variant doesn't function wih this compiler

Dinkumware Library

Several compilers, including Visual C++ 6.0, use an older dinkumware library. These platforms have several issues:

STLPort 4.5.3


Revised 1 November, 2004

© 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)