|  | SerializationSerializable Concept | 
const Members
      serialize into 
      save/load
      T is Serializable 
if and only if one of the following is true:
serialize
    serialize
    
template<class Archive, class T>
inline void serialize(
    Archive & ar, 
    T & t, 
    const unsigned int file_version
){
    // invoke member function for class T
    t.serialize(ar, file_version);
}
serialize 
presumes the existence of a class member function template of the following 
signature:
template<class Archive>
void serialize(Archive &ar, const unsigned int version){
    ...
}
friend class boost::serialization::access;
It may not be immediately obvious how this one template serves for both
saving data to an archive as well as loading data from the archive.
The key is that the & operator is 
defined as <<
for output archives and as >> input archives.  The
"polymorphic" behavior of the & permits the same template
to be used for both save and load operations.  This is very convenient in that it
saves a lot of typing and guarantees that the saving and loading of class
data members are always in sync.  This is the key to the whole serialization
system.
my_class, the
override would be specified as:
// namespace selection
template<class Archive>
inline void serialize(
    Archive & ar, 
    my_class & t, 
    const unsigned int file_version
){
    ...
}
private, it won't be
possible to serialize them.  So in some instances, minor modifications to the
class to be serialized will be necessary even when using this "non-intrusive"
method.  In practice this may not be such a problem as many libraries 
(E.G. STL) expose enough information to permit implementation of non-intrusive
serialization with absolutly no changes to the library.
boost::serialization.  If portability is not a concern and the
compiler being used supports ADL (Argument Dependent Lookup) the free functions and
templates can be in any of the following namespaces:
boost::serialization
Note that, at first glance, this suggestion may seem to be wrong for compilers which implement two phase lookup. In fact, the serialization library used a perhaps overly clever method to support this rule even for such compilers. Those with an interest in studying this further will find more information in serialization.hpp
operator & to all the data members of the class.
{
    // save/load class member variables
    ar & member1;
    ar & member2;
}
template<class Base, class Derived>
Base & base_object(Derived &d);
T the base class state should be 
serialized like this:
{
    // invoke serialization of the base class 
    ar & boost::serialization::base_object<base_class_of_T>(*this);
    // save/load class member variables
    ar & member1;
    ar & member2;
}
*this to the base class.
This might seem to work but may fail to invoke code necessary for
proper serialization.
Note that this is NOT the same as calling the serialize
function of the base class. This might seem to work but will circumvent
certain code used for tracking of objects, and registering base-derived
relationships and other bookkeeping that is required for the serialization
system to function as designed.  For this reason, all serialize
member functions should be private.
const Membersconst members to an archive 
requires no special considerations.
Loading const members can be addressed by using a
const_cast:
    ar & const_cast<T &>(t);
const
keyword. const members are intialized when a class instance
is constructed and not changed thereafter.  However, this may
be most appropriate in many cases.  Ultimately, it comes down to 
the question about what const means in the context
of serialization. 
boost::shared_ptr<T> and for
std::list<T>. If I have defined serialization for my own
class my_t, then serialization for 
std::list< boost::shared_ptr< my_t> > is already available
for use.
For an example that shows how this idea might be implemented for your own
class templates, see
demo_auto_ptr.cpp.
This shows how non-intrusive serialization
for the template auto_ptr from the standard library
can be implemented.
A somewhat trickier addition of serialization to a standard template can be found in the example shared_ptr.hpp
In the specification of serialization for templates, its common
to split serialize 
into a load/save pair. 
Note that the convenience macro described 
above
isn't helpful in these cases as the number and kind of
template class arguments won't match those used when splitting
serialize for a simple class.  Use the override
syntax instead.
{
    // invoke serialization of the base class 
    ar & boost::serialization::base_object<base_class_of_T>(*this);
    // save/load class member variables
    ar & member1;
    ar & member2;
    // if its a recent version of the class
    if(1 < file_version)
        // save load recently added class members
        ar & member3;
}
serialize into Save/Load
template<class Archive>
void save(Archive & ar, const unsigned int version) const
{
    // invoke serialization of the base class 
    ar << boost::serialization::base_object<const base_class_of_T>(*this);
    ar << member1;
    ar << member2;
    ar << member3;
}
template<class Archive>
void load(Archive & ar, const unsigned int version)
{
    // invoke serialization of the base class 
    ar >> boost::serialization::base_object<base_class_of_T>(*this);
    ar >> member1;
    ar >> member2;
    if(version > 0)
        ar >> member3;
}
template<class Archive>
void serialize(
    Archive & ar,
    const unsigned int file_version 
){
    boost::serialization::split_member(ar, *this, file_version);
}
save
and load.  Since the new serialize template
is always the same it can be generated by invoking the macro
BOOST_SERIALIZATION_SPLIT_MEMBER() defined in the header file
boost/serialization/split_member.hpp
.
So the entire serialize function above can be replaced with:
BOOST_SERIALIZATION_SPLIT_MEMBER()
serialize function template.
To use save and 
load function templates rather than 
serialize:
namespace boost { namespace serialization {
template<class Archive>
void save(Archive & ar, const my_class & t, unsigned int version)
{
    ...
}
template<class Archive>
void load(Archive & ar, my_class & t, unsigned int version)
{
    ...
}
}}
serialize function template:
namespace boost { namespace serialization {
template<class Archive>
inline void serialize(
    Archive & ar,
    my_class & t,
    const unsigned int file_version
){
    split_free(ar, t, file_version); 
}
}}
BOOST_SERIALIZATION_SPLIT_FREE(my_class)
serialize function into save/load
has been provided, the usage of the serialize
function with the corresponding & operator
is preferred.  The key to the serialization implementation is that objects are saved 
and loaded in exactly the same sequence.  Using the & 
operator and serialize
function guarantees that this is always the case and will minimize the
occurrence of hard to find errors related to synchronization of 
save and load 
functions.
Also note that BOOST_SERIALIZATION_SPLIT_FREE
must be used outside of any namespace.
To properly save and restore an object through a pointer the following situations must be addressed:
Saving a pointer:
<< 
and >> operators
// load data required for construction and invoke constructor in place
template<class Archive, class T>
inline void load_construct_data(
    Archive & ar, T * t, const unsigned int file_version
){
    // default just uses the default constructor to initialize
    // previously allocated memory. 
    ::new(t)T();
}
load_construct_data invokes the
default constructor "in-place" to initialize the memory.
If there is no such default constructor, the function templates
load_construct_data and 
perhaps save_construct_data
will have to be overridden.  Here is a simple example:
class my_class {
private:
    friend class boost::serialization::access;
    const int m_attribute;  // some immutable aspect of the instance
    int m_state;            // mutable state of this instance
    template<class Archive>
    void serialize(Archive &ar, const unsigned int file_version){
        ar & m_state;
    }
public:
    // no default construct guarentees that no invalid object
    // ever exists
    my_class(int attribute) :
        m_attribute(attribute),
        m_state(0)
    {}
};
namespace boost { namespace serialization {
template<class Archive>
inline void save_construct_data(
    Archive & ar, const my_class * t, const unsigned int file_version
){
    // save data required to construct instance
    ar << t->m_attribute;
}
template<class Archive>
inline void load_construct_data(
    Archive & ar, my_class * t, const unsigned int file_version
){
    // retrieve data from archive required to construct new instance
    int attribute;
    ar >> attribute;
    // invoke inplace constructor to initialize instance of my_class
    ::new(t)my_class(attribute);
}
}} // namespace ...
class base {
    ...
};
class derived_one : public base {
    ...
};
class derived_two : public base {
    ...
};
main(){
    ...
    base *b;
    ...
    ar & b; 
}
b what kind of object should be saved? 
When loading b what kind of object should be created? 
Should it be an object of class derived_one,
derived_two, or maybe base?
It turns out that the kind of object serialized depends upon whether the base class
(base in this case) is polymophic or not.
If base is not polymorphic, that is if it has no
virtual functions, then an object of the type base
will be serialized. Information in any derived classes will be lost. If this is what is desired
(it usually isn't) then no other effort is required.
If the base class is polymorphic, an object of the most derived type
(derived_one
or derived_two
in this case) will be serialized.  The question of which type of object is to be
serialized is (almost) automatically handled by the library.
The system "registers" each class in an archive the first time an object of that class it is serialized and assigns a sequential number to it. Next time an object of that class is serialized in that same archive, this number is written in the archive. So every class is identified uniquely within the archive. When the archive is read back in, each new sequence number is re-associated with the class being read. Note that this implies that "registration" has to occur during both save and load so that the class-integer table built on load is identical to the class-integer table built on save. In fact, the key to whole serialization system is that things are always saved and loaded in the same sequence. This includes "registration".
Expanding our previous example:
main(){
    derived_one d1;
    derived_two d2:
    ...
    ar & d1;
    ar & d2;
    // A side effect of serialization of objects d1 and d2 is that
    // the classes derived_one and derived_two become known to the archive.
    // So subsequent serialization of those classes by base pointer works
    // without any special considerations.
    base *b;
    ...
    ar & b; 
}
b is read it is
preceded by a unique (to the archive) class identifier which
has previously been related to class derived_one or
derived_two.
If a derived class has NOT been automatically "registered" as described
above, an 
unregistered_class exception 
will be thrown when serialization is invoked.
This can be addressed by registering the derived class explicitly. All archives are derived from a base class which implements the following template:
template<class T>
register_type();
main(){
    ...
    ar.template register_type<derived_one>();
    ar.template register_type<derived_two>();
    base *b;
    ...
    ar & b; 
}
So we have another method:
#include <boost/serialization/export.hpp>
...
BOOST_CLASS_EXPORT_GUID(derived_one, "derived_one")
BOOST_CLASS_EXPORT_GUID(derived_two, "derived_two")
main(){
    ...
    base *b;
    ...
    ar & b; 
}
BOOST_CLASS_EXPORT_GUID associates a string literal
with a class. In the above example we've used a string rendering
of the class name. If a object of such an "exported" class is serialized
through a pointer and is otherwise unregistered, the "export" string is 
included in the archive. When the archive 
is later read, the string literal is used to find the class which 
should be created by the serialization library.
This permits each class to be in a separate header file along with its 
string identifier. There is no need to maintain a separate "pre-registration" 
of derived classes that might be serialized.  This method of
registration is referred to as "key export".  More information on this
topic is found in the section Class Traits - 
Export Key.
template<class Archive, class T>.
This means that serialization code must be instantiated for each
combination of archive and data type that is serialized in the program.
Polymorphic pointers of derived classes may never be referred to 
explictly by the program so normally code to serialize such classes
would never be instantiated.  So in addition to including export key
strings in an archive, BOOST_CLASS_EXPORT_GUID explicitly
instantiates the class serialization code for all archive classes used 
by the program.  
track_selectively.
That is, track objects if and only if they are serialized through pointers anywhere
in the program. Any  objects that are "registered" by any of the above means are presumed
to be serialized through pointers somewhere in the program and therefore
would be tracked. In certain situations this could lead to an inefficiency.
Suppose we have a class module used by multiple programs.  Because
some programs serializes polymorphic pointers to objects of this class, we 
export a class
identifier by specifying BOOST_CLASS_EXPORT in the
class header.  When this module is included by another program,
objects of this class will always be tracked even though it
may not be necessary.  This situation could be addressed by using 
track_never  
in those programs.
It could also occur that even though a program serializes through 
a pointer, we are more concerned with efficiency than avoiding the
the possibility of creating duplicate objects.  It could be
that we happen to know that there will be no duplicates.  It could
also be that the creation of a few duplicates is benign and not
worth avoiding given the runtime cost of tracking duplicates.
Again, track_never  
can be used.
boost::serialization::base_object<Base>(Derived &)
is to ensure that the base/derived pair is added to the table
before the main function is entered.
This is very convenient and results in a clean syntax.  The only
problem is that it can occur where a derived class serialized
through a pointer has no need to invoke the serialization of
its base class.  In such a case, there are two choices.  The obvious
one is to invoke the base class serialization with base_object
and specify an empty function for the base class serialization.
The alternative is to "register" the Base/Derived relationship
explicitly by invoking the template 
void_cast_register<Derived, Base>();.
Note that this usage of the term "register" is not related
to its usage in the previous section.  Here is an example of how this is done:
#include <sstream>
#include <boost/serialization/serialization.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/export.hpp>
class base {
    friend class boost::serialization::access;
    //...
    // only required when using method 1 below
    // no real serialization required - specify a vestigial one
    template<class Archive>
    void serialize(Archive & ar, const unsigned int file_version){}
};
class derived : public base {
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int file_version){
        // method 1 : invoke base class serialization
        ar & boost::serialization::base_object<base>(*this);
        // method 2 : explicitly register base/derived relationship
        boost::serialization::void_cast_register<derived, base>(
            static_cast<derived *>(NULL),
            static_cast<base *>(NULL)
        )
    }
};
BOOST_CLASS_EXPORT_GUID(derived, "derived")
main(){
    //...
    std::stringstream ss;
    boost::archive::text_iarchive ar(ss);
    base *b;
    ar >> b; 
}
In order for this template to be invoked in code compiled by non-conforming compilers, the following syntax may be used:
boost::serialization::void_cast_register(
    static_cast<Derived *>(NULL),
    static_cast<Base *>(NULL)
);
class object;
class my_class {
private:
    friend class boost::serialization::access;
    int member1;
    object & member2;
    template<class Archive>
    void serialize(Archive &ar, const unsigned int file_version);
public:
    my_class(int m, object & o) :
        member1(m), 
        member2(o)
    {}
};
namespace boost { namespace serialization {
template<class Archive>
inline void save_construct_data(
    Archive & ar, const my_class * t, const unsigned int file_version
){
    // save data required to construct instance
    ar << t.member1;
    // serialize reference to object as a pointer
    ar << & t.member2;
}
template<class Archive>
inline void load_construct_data(
    Archive & ar, my_class * t, const unsigned int file_version
){
    // retrieve data from archive required to construct new instance
    int m;
    ar >> m;
    // create and load data through pointer to object
    // tracking handles issues of duplicates.
    object * optr;
    ar >> optr;
    // invoke inplace constructor to initialize instance of my_class
    ::new(t)my_class(m, *optr);
}
}} // namespace ...
T is a serializable type, 
then any native C++ array of type T is a serializable type.
That is, if T
is a serializable type, then the following
is automatically available and will function as expected:
T t[4];
ar << t;
    ...
ar >> t;
std::list, use:
#include <boost/serialization/list.hpp>
#include <list>
std::pair).
As of this writing, the library contains serialization of the following boost classes:
© 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)