epoc32/include/stdapis/boost/archive/detail/oserializer.hpp
branchSymbian2
changeset 2 2fe1408b6811
equal deleted inserted replaced
1:666f914201fb 2:2fe1408b6811
       
     1 #ifndef BOOST_ARCHIVE_OSERIALIZER_HPP
       
     2 #define BOOST_ARCHIVE_OSERIALIZER_HPP
       
     3 
       
     4 // MS compatible compilers support #pragma once
       
     5 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
       
     6 # pragma once
       
     7 #pragma inline_depth(511)
       
     8 #pragma inline_recursion(on)
       
     9 #endif
       
    10 
       
    11 #if defined(__MWERKS__)
       
    12 #pragma inline_depth(511)
       
    13 #endif
       
    14 
       
    15 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
       
    16 // oserializer.hpp: interface for serialization system.
       
    17 
       
    18 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
       
    19 // Use, modification and distribution is subject to the Boost Software
       
    20 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
       
    21 // http://www.boost.org/LICENSE_1_0.txt)
       
    22 
       
    23 //  See http://www.boost.org for updates, documentation, and revision history.
       
    24 
       
    25 #include <cassert>
       
    26 
       
    27 #include <boost/config.hpp>
       
    28 #include <boost/detail/workaround.hpp>
       
    29 #include <boost/throw_exception.hpp>
       
    30 #include <boost/smart_cast.hpp>
       
    31 #include <boost/static_assert.hpp>
       
    32 #include <boost/static_warning.hpp>
       
    33 
       
    34 #include <boost/type_traits/is_pointer.hpp>
       
    35 #include <boost/type_traits/is_fundamental.hpp>
       
    36 #include <boost/type_traits/is_enum.hpp>
       
    37 #include <boost/type_traits/is_volatile.hpp>
       
    38 #include <boost/type_traits/is_const.hpp>
       
    39 #include <boost/type_traits/is_same.hpp>
       
    40 #include <boost/serialization/is_abstract.hpp>
       
    41 
       
    42 #include <boost/mpl/eval_if.hpp>
       
    43 #include <boost/mpl/and.hpp>
       
    44 #include <boost/mpl/less.hpp>
       
    45 #include <boost/mpl/greater_equal.hpp>
       
    46 #include <boost/mpl/equal_to.hpp>
       
    47 #include <boost/mpl/int.hpp>
       
    48 #include <boost/mpl/identity.hpp>
       
    49 #include <boost/mpl/list.hpp>
       
    50 #include <boost/mpl/empty.hpp>
       
    51 #include <boost/mpl/not.hpp>
       
    52 
       
    53  #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO   
       
    54      #include <boost/serialization/extended_type_info_typeid.hpp>   
       
    55  #endif 
       
    56 // the following is need only for dynamic cast of polymorphic pointers
       
    57 #include <boost/archive/detail/basic_oarchive.hpp>
       
    58 #include <boost/archive/detail/basic_oserializer.hpp>
       
    59 #include <boost/archive/detail/archive_pointer_oserializer.hpp>
       
    60 
       
    61 #include <boost/serialization/force_include.hpp>
       
    62 #include <boost/serialization/serialization.hpp>
       
    63 #include <boost/serialization/version.hpp>
       
    64 #include <boost/serialization/level.hpp>
       
    65 #include <boost/serialization/tracking.hpp>
       
    66 #include <boost/serialization/type_info_implementation.hpp>
       
    67 #include <boost/serialization/nvp.hpp>
       
    68 #include <boost/serialization/void_cast.hpp>
       
    69 
       
    70 #include <boost/archive/archive_exception.hpp>
       
    71 
       
    72 namespace boost {
       
    73 
       
    74 namespace serialization {
       
    75     class extended_type_info;
       
    76 } // namespace serialization
       
    77 
       
    78 namespace archive {
       
    79 
       
    80 // an accessor to permit friend access to archives.  Needed because
       
    81 // some compilers don't handle friend templates completely
       
    82 class save_access {
       
    83 public:
       
    84     template<class Archive>
       
    85     static void end_preamble(Archive & ar){
       
    86         ar.end_preamble();
       
    87     }
       
    88     template<class Archive, class T>
       
    89     static void save_primitive(Archive & ar, const  T & t){
       
    90         ar.end_preamble();
       
    91         ar.save(t);
       
    92     }
       
    93 };
       
    94 
       
    95 namespace detail {
       
    96 
       
    97 template<class Archive, class T>
       
    98 class oserializer : public basic_oserializer
       
    99 {
       
   100 private:
       
   101     // private constructor to inhibit any existence other than the 
       
   102     // static one
       
   103     explicit oserializer() :
       
   104         basic_oserializer(
       
   105             * boost::serialization::type_info_implementation<T>::type::get_instance()
       
   106         )
       
   107     {}
       
   108 public:
       
   109     virtual BOOST_DLLEXPORT void save_object_data(
       
   110         basic_oarchive & ar,    
       
   111         const void *x
       
   112     ) const BOOST_USED ;
       
   113     virtual bool class_info() const {
       
   114         return boost::serialization::implementation_level<T>::value 
       
   115             >= boost::serialization::object_class_info;
       
   116     }
       
   117     virtual bool tracking(const unsigned int flags) const {
       
   118 //        if(0 != (flags &  no_tracking))
       
   119 //            return false;
       
   120         return boost::serialization::tracking_level<T>::value == boost::serialization::track_always
       
   121             || boost::serialization::tracking_level<T>::value == boost::serialization::track_selectivly
       
   122             && serialized_as_pointer();
       
   123     }
       
   124     virtual unsigned int version() const {
       
   125         return ::boost::serialization::version<T>::value;
       
   126     }
       
   127     virtual bool is_polymorphic() const {
       
   128         typedef BOOST_DEDUCED_TYPENAME boost::serialization::type_info_implementation<
       
   129             T
       
   130         >::type::is_polymorphic::type typex;
       
   131         return typex::value;
       
   132     }
       
   133     static oserializer & instantiate(){
       
   134         static oserializer instance;
       
   135         return instance;
       
   136     }
       
   137     virtual ~oserializer(){}
       
   138 };
       
   139 
       
   140 template<class Archive, class T>
       
   141 BOOST_DLLEXPORT void oserializer<Archive, T>::save_object_data(
       
   142     basic_oarchive & ar,    
       
   143     const void *x
       
   144 ) const {
       
   145     // make sure call is routed through the highest interface that might
       
   146     // be specialized by the user.
       
   147     boost::serialization::serialize_adl(
       
   148         boost::smart_cast_reference<Archive &>(ar),
       
   149         * static_cast<T *>(const_cast<void *>(x)),
       
   150         version()
       
   151     );
       
   152 }
       
   153 
       
   154 // instantiation of this template creates a static object.  Note inversion of
       
   155 // normal argument order to workaround bizarre error in MSVC 6.0 which only
       
   156 // manifests iftself during compiler time.
       
   157 template<class T, class Archive>
       
   158 class pointer_oserializer : public archive_pointer_oserializer<Archive> 
       
   159 {
       
   160 private:
       
   161     virtual const basic_oserializer & get_basic_serializer() const {
       
   162         return oserializer<Archive, T>::instantiate();
       
   163     }
       
   164     virtual BOOST_DLLEXPORT void save_object_ptr(
       
   165         basic_oarchive & ar,
       
   166         const void * x
       
   167     ) const BOOST_USED ;
       
   168 #if defined(__GNUC__) || ( defined(BOOST_MSVC) && (_MSC_VER <= 1300) )
       
   169 public:
       
   170 #endif
       
   171     // private constructor to inhibit any existence other than the 
       
   172     // static one.  Note GCC doesn't permit constructor to be private
       
   173     explicit BOOST_DLLEXPORT pointer_oserializer() BOOST_USED;
       
   174     static const pointer_oserializer instance;
       
   175 public:
       
   176     #if ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
       
   177     // at least one compiler (CW) seems to require that serialize_adl
       
   178     // be explicitly instantiated. Still under investigation. 
       
   179     void (* const m)(Archive &, T &, const unsigned);
       
   180     boost::serialization::extended_type_info * (* e)();
       
   181     #endif
       
   182     static BOOST_DLLEXPORT const pointer_oserializer & instantiate() BOOST_USED;
       
   183     virtual ~pointer_oserializer(){}
       
   184 };
       
   185 
       
   186 template<class T, class Archive>
       
   187 BOOST_DLLEXPORT const pointer_oserializer<T, Archive> & 
       
   188 pointer_oserializer<T, Archive>::instantiate(){
       
   189     return instance;
       
   190 }
       
   191 
       
   192 // note: instances of this template to be constructed before the main
       
   193 // is called in order for things to be initialized properly.  For this
       
   194 // reason, hiding the instance in a static function as was done above
       
   195 // won't work here so we created a free instance here.
       
   196 template<class T, class Archive>
       
   197 const pointer_oserializer<T, Archive> pointer_oserializer<T, Archive>::instance;
       
   198 
       
   199 template<class T, class Archive>
       
   200 BOOST_DLLEXPORT void pointer_oserializer<T, Archive>::save_object_ptr(
       
   201     basic_oarchive & ar,
       
   202     const void * x
       
   203 ) const {
       
   204     assert(NULL != x);
       
   205     // make sure call is routed through the highest interface that might
       
   206     // be specialized by the user.
       
   207     T * t = static_cast<T *>(const_cast<void *>(x));
       
   208     const unsigned int file_version = boost::serialization::version<T>::value;
       
   209     Archive & ar_impl = boost::smart_cast_reference<Archive &>(ar);
       
   210     boost::serialization::save_construct_data_adl<Archive, T>(
       
   211         ar_impl, 
       
   212         t, 
       
   213         file_version
       
   214     );
       
   215     ar_impl << boost::serialization::make_nvp(NULL, * t);
       
   216 }
       
   217 
       
   218 template<class T, class Archive>
       
   219 #if ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
       
   220 BOOST_DLLEXPORT pointer_oserializer<T, Archive>::pointer_oserializer() :
       
   221     archive_pointer_oserializer<Archive>(
       
   222         * boost::serialization::type_info_implementation<T>::type::get_instance()
       
   223     ),
       
   224     m(boost::serialization::serialize_adl<Archive, T>),
       
   225     e(boost::serialization::type_info_implementation<T>::type::get_instance)
       
   226 #else
       
   227 BOOST_DLLEXPORT pointer_oserializer<T, Archive>::pointer_oserializer() :
       
   228     archive_pointer_oserializer<Archive>(
       
   229         * boost::serialization::type_info_implementation<T>::type::get_instance()
       
   230     )
       
   231 #endif
       
   232 {
       
   233     // make sure appropriate member function is instantiated
       
   234     oserializer<Archive, T> & bos = oserializer<Archive, T>::instantiate();
       
   235     bos.set_bpos(this);
       
   236 }
       
   237 
       
   238 template<class Archive, class T>
       
   239 struct save_non_pointer_type {
       
   240     // note this bounces the call right back to the archive
       
   241     // with no runtime overhead
       
   242     struct save_primitive {
       
   243         static void invoke(Archive & ar, const T & t){
       
   244             save_access::save_primitive(ar, t);
       
   245         }
       
   246     };
       
   247     // same as above but passes through serialization
       
   248     struct save_only {
       
   249         static void invoke(Archive & ar, const T & t){
       
   250             // make sure call is routed through the highest interface that might
       
   251             // be specialized by the user.
       
   252             boost::serialization::serialize_adl(
       
   253                 ar, 
       
   254                 const_cast<T &>(t), 
       
   255                 ::boost::serialization::version<T>::value
       
   256             );
       
   257         }
       
   258     };
       
   259     // adds class information to the archive. This includes
       
   260     // serialization level and class version
       
   261     struct save_standard {
       
   262         static void invoke(Archive &ar, const T & t){
       
   263             ar.save_object(& t, oserializer<Archive, T>::instantiate());
       
   264         }
       
   265     };
       
   266 
       
   267     // adds class information to the archive. This includes
       
   268     // serialization level and class version
       
   269     struct save_conditional {
       
   270         static void invoke(Archive &ar, const T &t){
       
   271             //if(0 == (ar.get_flags() & no_tracking))
       
   272                 save_standard::invoke(ar, t);
       
   273             //else
       
   274             //   save_only::invoke(ar, t);
       
   275         }
       
   276     };
       
   277 
       
   278     typedef 
       
   279         BOOST_DEDUCED_TYPENAME mpl::eval_if<
       
   280         // if its primitive
       
   281             mpl::equal_to<
       
   282                 boost::serialization::implementation_level<T>,
       
   283                 mpl::int_<boost::serialization::primitive_type>
       
   284             >,
       
   285             mpl::identity<save_primitive>,
       
   286         // else
       
   287         BOOST_DEDUCED_TYPENAME mpl::eval_if<
       
   288             // class info / version
       
   289             mpl::greater_equal<
       
   290                 boost::serialization::implementation_level<T>,
       
   291                 mpl::int_<boost::serialization::object_class_info>
       
   292             >,
       
   293             // do standard save
       
   294             mpl::identity<save_standard>,
       
   295         // else
       
   296         BOOST_DEDUCED_TYPENAME mpl::eval_if<
       
   297                 // no tracking
       
   298             mpl::equal_to<
       
   299                 boost::serialization::tracking_level<T>,
       
   300                 mpl::int_<boost::serialization::track_never>
       
   301             >,
       
   302             // do a fast save
       
   303             mpl::identity<save_only>,
       
   304         // else
       
   305             // do a fast save only tracking is turned off
       
   306             mpl::identity<save_conditional>
       
   307     > > >::type typex; 
       
   308 
       
   309     static void invoke(Archive & ar, const T & t){
       
   310         // check that we're not trying to serialize something that
       
   311         // has been marked not to be serialized.  If this your program
       
   312         // traps here, you've tried to serialize a class whose trait
       
   313         // has been marked "non-serializable". Either reset the trait
       
   314         // (see level.hpp) or change program not to serialize items of this class
       
   315         BOOST_STATIC_ASSERT((
       
   316             mpl::greater_equal<
       
   317                 boost::serialization::implementation_level<T>, 
       
   318                 mpl::int_<boost::serialization::primitive_type>
       
   319             >::value
       
   320         ));
       
   321         typex::invoke(ar, t);
       
   322     };
       
   323 };
       
   324 
       
   325 template<class Archive, class TPtr>
       
   326 struct save_pointer_type {
       
   327     template<class T>
       
   328     struct abstract
       
   329     {
       
   330         static const basic_pointer_oserializer * register_type(Archive & /* ar */){
       
   331             // it has? to be polymorphic
       
   332             BOOST_STATIC_ASSERT(
       
   333                 boost::serialization::type_info_implementation<T>::type::is_polymorphic::value
       
   334             );
       
   335             return static_cast<const basic_pointer_oserializer *>(NULL);
       
   336         }
       
   337     };
       
   338 
       
   339     template<class T>
       
   340     struct non_abstract
       
   341     {
       
   342         static const basic_pointer_oserializer * register_type(Archive & ar){
       
   343             return ar.register_type(static_cast<T *>(NULL));
       
   344         }
       
   345     };
       
   346 
       
   347     template<class T>
       
   348     static const basic_pointer_oserializer * register_type(Archive &ar, T & /*t*/){
       
   349         // there should never be any need to save an abstract polymorphic 
       
   350         // class pointer.  Inhibiting code generation for this
       
   351         // permits abstract base classes to be used - note: exception
       
   352         // virtual serialize functions used for plug-ins
       
   353         typedef 
       
   354             BOOST_DEDUCED_TYPENAME mpl::eval_if<
       
   355                 serialization::is_abstract<T>,
       
   356                 mpl::identity<abstract<T> >,
       
   357                 mpl::identity<non_abstract<T> >       
       
   358             >::type typex;
       
   359         return typex::register_type(ar);
       
   360     }
       
   361 
       
   362     template<class T>
       
   363     struct non_polymorphic
       
   364     {
       
   365         static void save(
       
   366             Archive &ar, 
       
   367             const T & t, 
       
   368             const basic_pointer_oserializer * bpos_ptr
       
   369         ){
       
   370             // save the requested pointer type
       
   371             ar.save_pointer(& t, bpos_ptr);
       
   372         }
       
   373     };
       
   374 
       
   375     template<class T>
       
   376     struct polymorphic
       
   377     {
       
   378         static void save(
       
   379             Archive &ar, 
       
   380             const T & t, 
       
   381             const basic_pointer_oserializer * bpos_ptr
       
   382         ){
       
   383             const boost::serialization::extended_type_info * this_type
       
   384                 = boost::serialization::type_info_implementation<T>::type::get_instance();
       
   385             // retrieve the true type of the object pointed to
       
   386             // if this assertion fails its an error in this library
       
   387             assert(NULL != this_type);
       
   388             const boost::serialization::extended_type_info * true_type 
       
   389                 = boost::serialization::type_info_implementation<T>::type::get_derived_extended_type_info(t);
       
   390             // note:if this exception is thrown, be sure that derived pointer
       
   391             // is either regsitered or exported.
       
   392             if(NULL == true_type){
       
   393                 boost::throw_exception(
       
   394                     archive_exception(archive_exception::unregistered_class)
       
   395                 );
       
   396             }
       
   397 
       
   398             // if its not a pointer to a more derived type
       
   399             const void *vp = static_cast<const void *>(&t);
       
   400             if(*this_type == *true_type){
       
   401                 ar.save_pointer(vp, bpos_ptr);
       
   402                 return;
       
   403             }
       
   404             // convert pointer to more derived type. if this is thrown
       
   405             // it means that the base/derived relationship hasn't be registered
       
   406             vp = serialization::void_downcast(*true_type, *this_type, &t);
       
   407             if(NULL == vp){
       
   408                 boost::throw_exception(
       
   409                     archive_exception(archive_exception::unregistered_cast)
       
   410                 );
       
   411             }
       
   412 
       
   413             // sice true_type is valid, and this only gets made if the 
       
   414             // pointer oserializer object has been created, this should never
       
   415             // fail
       
   416             bpos_ptr = archive_pointer_oserializer<Archive>::find(* true_type);
       
   417             assert(NULL != bpos_ptr);
       
   418             if(NULL == bpos_ptr)
       
   419                 boost::throw_exception(
       
   420                     archive_exception(archive_exception::unregistered_class)
       
   421                 );
       
   422             ar.save_pointer(vp, bpos_ptr);
       
   423         }
       
   424     };
       
   425 
       
   426     template<class T>
       
   427     static void save(
       
   428         Archive & ar, 
       
   429         const T &t,
       
   430         const basic_pointer_oserializer * bpos_ptr
       
   431     ){
       
   432         typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
       
   433             BOOST_DEDUCED_TYPENAME boost::serialization::
       
   434                 type_info_implementation<T>::type::is_polymorphic,
       
   435             mpl::identity<polymorphic<T> >,
       
   436             mpl::identity<non_polymorphic<T> >
       
   437         >::type typey;
       
   438         typey::save(ar, const_cast<T &>(t), bpos_ptr);
       
   439     }
       
   440 
       
   441     template<class T>
       
   442     static void const_check(T & t){
       
   443         BOOST_STATIC_ASSERT(! boost::is_const<T>::value);
       
   444     }
       
   445 
       
   446     static void invoke(Archive &ar, const TPtr t){
       
   447         #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
       
   448             // if your program traps here, its because you tried to do
       
   449             // something like ar << t where t is a pointer to a const value
       
   450             // void f3(A const* a, text_oarchive& oa)
       
   451             // {
       
   452             //     oa << a;
       
   453             // }
       
   454             // with a compiler which doesn't support remove_const
       
   455             // const_check(* t);
       
   456         #else
       
   457             // otherwise remove the const
       
   458         #endif
       
   459         const basic_pointer_oserializer * bpos_ptr =  register_type(ar, * t);
       
   460         if(NULL == t){
       
   461             basic_oarchive & boa = boost::smart_cast_reference<basic_oarchive &>(ar);
       
   462             boa.save_null_pointer();
       
   463             save_access::end_preamble(ar);
       
   464             return;
       
   465         }
       
   466         save(ar, * t, bpos_ptr);
       
   467     };
       
   468 };
       
   469 
       
   470 template<class Archive, class T>
       
   471 struct save_enum_type
       
   472 {
       
   473     static void invoke(Archive &ar, const T &t){
       
   474         // convert enum to integers on save
       
   475         const int i = static_cast<int>(t);
       
   476         ar << boost::serialization::make_nvp(NULL, i);
       
   477     }
       
   478 };
       
   479 
       
   480 template<class Archive, class T>
       
   481 struct save_array_type
       
   482 {
       
   483     static void invoke(Archive &ar, const T &t){
       
   484         save_access::end_preamble(ar);
       
   485         // consider alignment
       
   486         int count = sizeof(t) / (
       
   487             static_cast<const char *>(static_cast<const void *>(&t[1])) 
       
   488             - static_cast<const char *>(static_cast<const void *>(&t[0]))
       
   489         );
       
   490         ar << BOOST_SERIALIZATION_NVP(count);
       
   491         int i;
       
   492         for(i = 0; i < count; ++i)
       
   493             ar << boost::serialization::make_nvp("item", t[i]);
       
   494     }
       
   495 };
       
   496 
       
   497 // note bogus arguments to workaround msvc 6 silent runtime failure
       
   498 // declaration to satisfy gcc
       
   499 template<class Archive, class T>
       
   500 BOOST_DLLEXPORT const basic_pointer_oserializer &
       
   501 instantiate_pointer_oserializer(
       
   502     Archive * /* ar = NULL */,
       
   503     T * /* t = NULL */
       
   504 ) BOOST_USED ;
       
   505 // definition
       
   506 template<class Archive, class T>
       
   507 BOOST_DLLEXPORT const basic_pointer_oserializer &
       
   508 instantiate_pointer_oserializer(
       
   509     Archive * /* ar = NULL */,
       
   510     T * /* t = NULL */
       
   511 ){
       
   512     // note: reversal of order of arguments to work around msvc 6.0 bug
       
   513     // that manifests itself while trying to link.
       
   514     return pointer_oserializer<T, Archive>::instantiate();
       
   515 }
       
   516 
       
   517 } // detail
       
   518 
       
   519 template<class Archive, class T>
       
   520 inline void save(Archive & ar, const T &t){
       
   521     typedef 
       
   522         BOOST_DEDUCED_TYPENAME mpl::eval_if<is_pointer<T>,
       
   523             mpl::identity<detail::save_pointer_type<Archive, T> >,
       
   524         //else
       
   525         BOOST_DEDUCED_TYPENAME mpl::eval_if<is_enum<T>,
       
   526             mpl::identity<detail::save_enum_type<Archive, T> >,
       
   527         //else
       
   528         BOOST_DEDUCED_TYPENAME mpl::eval_if<is_array<T>,
       
   529             mpl::identity<detail::save_array_type<Archive, T> >,
       
   530         //else
       
   531             mpl::identity<detail::save_non_pointer_type<Archive, T> >
       
   532         >
       
   533         >
       
   534         >::type typex;
       
   535     typex::invoke(ar, t);
       
   536 }
       
   537 
       
   538 #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
       
   539 
       
   540 template<class T>
       
   541 struct check_tracking {
       
   542     typedef BOOST_DEDUCED_TYPENAME mpl::if_<
       
   543         // if its never tracked.
       
   544         BOOST_DEDUCED_TYPENAME mpl::equal_to<
       
   545             serialization::tracking_level<T>,
       
   546             mpl::int_<serialization::track_never>
       
   547         >,
       
   548         // it better not be a pointer
       
   549         mpl::not_<is_pointer<T> >,
       
   550     //else
       
   551         // otherwise if it might be tracked.  So there shouldn't
       
   552         // be any problem making a const
       
   553         is_const<T>
       
   554     >::type typex;
       
   555     BOOST_STATIC_CONSTANT(bool, value = typex::value);
       
   556 };
       
   557 
       
   558 template<class Archive, class T>
       
   559 inline void save(Archive & ar, T &t){
       
   560     // if your program traps here, it indicates taht your doing one of the following:
       
   561     // a) serializing an object of a type marked "track_never" through a pointer.
       
   562     // b) saving an non-const object of a type not markd "track_never)
       
   563     // Either of these conditions may be an indicator of an error usage of the
       
   564     // serialization library and should be double checked.  See documentation on
       
   565     // object tracking.
       
   566     BOOST_STATIC_ASSERT(check_tracking<T>::value);
       
   567         save(ar, const_cast<const T &>(t));
       
   568 }
       
   569 #endif
       
   570 
       
   571 } // namespace archive
       
   572 } // namespace boost
       
   573 
       
   574 #endif // BOOST_ARCHIVE_OSERIALIZER_HPP