#ifndef BOOST_SERIALIZATION_VARIANT_HPP #define BOOST_SERIALIZATION_VARIANT_HPP // MS compatible compilers support #pragma once #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 // variant.hpp // (C) Copyright 2005 Frank Birbacher // 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) // See http://www.boost.org for updates, documentation, and revision history. #include #include #include #include #include #include #include #include #include #include #include #include #include #include // function specializations must be defined in the appropriate // namespace - boost::serialization #if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION) #define STD _STLP_STD #else #define STD std #endif namespace boost { namespace serialization { namespace detail { template struct write_variant_value_to_archive : boost::static_visitor<> { write_variant_value_to_archive(OArchive& archive) : archive(archive) {} template void operator() (T const& t) const { //borland seems to fail without full namespace //according to collections_load_imp.hpp archive << boost::serialization::make_nvp("data", t); } private: OArchive& archive; }; namespace mpl = ::boost::mpl; /** select type in Types by Index but * return int on out-of-range */ template struct SelectWithDefault : mpl::eval_if< //check range mpl::less< mpl::int_, mpl::size >, //if ok, choose by Index mpl::at< Types, mpl::int_ >, //else return int mpl::identity > {}; } //namespace detail /////////////////////////////////////////////////////////////////////////////// //now some definitions for type lists //which are #undef-ed at the end of this file #ifdef BOOST_SERIALIZATION_VARIANT_TYPENAME_LIST_MACRO #error BOOST_SERIALIZATION_VARIANT_TYPENAME_LIST_MACRO already defined #endif #define BOOST_SERIALIZATION_VARIANT_TYPENAME_LIST_MACRO(z, n, d) \ typename T ## n , \ /**/ //Lists typename T0, typename T1, typename T2, ... //Up to BOOST_VARIANT_LIMIT_TYPES #ifdef BOOST_SERIALIZATION_VARIANT_TYPENAME_LIST #error BOOST_SERIALIZATION_VARIANT_TYPENAME_LIST already defined #endif #define BOOST_SERIALIZATION_VARIANT_TYPENAME_LIST() \ BOOST_PP_REPEAT( \ BOOST_PP_DEC(BOOST_VARIANT_LIMIT_TYPES), \ BOOST_SERIALIZATION_VARIANT_TYPENAME_LIST_MACRO, \ _ \ ) \ typename \ BOOST_PP_CAT(T, BOOST_PP_DEC(BOOST_VARIANT_LIMIT_TYPES)) \ /**/ #ifdef BOOST_SERIALIZATION_VARIANT_TYPE_LIST_MACRO #error BOOST_SERIALIZATION_VARIANT_TYPE_LIST_MACRO already defined #endif #define BOOST_SERIALIZATION_VARIANT_TYPE_LIST_MACRO(z, n, d) \ T ## n , \ /**/ //Lists T0, T1, T2, ... //Up to BOOST_VARIANT_LIMIT_TYPES #ifdef BOOST_SERIALIZATION_VARIANT_TYPE_LIST #error BOOST_SERIALIZATION_VARIANT_TYPE_LIST already defined #endif #define BOOST_SERIALIZATION_VARIANT_TYPE_LIST() \ BOOST_PP_REPEAT( \ BOOST_PP_DEC(BOOST_VARIANT_LIMIT_TYPES), \ BOOST_SERIALIZATION_VARIANT_TYPE_LIST_MACRO, \ _ \ ) \ BOOST_PP_CAT(T, BOOST_PP_DEC(BOOST_VARIANT_LIMIT_TYPES)) \ /**/ /////////////////////////////////////////////////////////////////////////////// // serialization is split up into save/load template< typename OArchive, BOOST_SERIALIZATION_VARIANT_TYPENAME_LIST() > void save( OArchive& ar, boost::variant< BOOST_SERIALIZATION_VARIANT_TYPE_LIST() > const &var, unsigned int ) { //TODO: identity problems because of saving stack variable? unsigned int which = var.which(); //borland seems to fail without full namespace //according to collections_load_imp.hpp ar << boost::serialization::make_nvp("which", which); detail::write_variant_value_to_archive writer(ar); apply_visitor(writer, var); } /////////////////////////////////////// // load template< typename IArchive, BOOST_SERIALIZATION_VARIANT_TYPENAME_LIST() > void load( IArchive& ar, boost::variant< BOOST_SERIALIZATION_VARIANT_TYPE_LIST() >& var, const unsigned int /*version*/ ) { namespace mpl = ::boost::mpl; //convienient typedefs / constants typedef variant< BOOST_SERIALIZATION_VARIANT_TYPE_LIST() > Variant; typedef typename Variant::types Types; const int TypesLen = mpl::size::type::value; unsigned int which; //borland seems to fail without full namespace //according to collections_load_imp.hpp ar >> boost::serialization::make_nvp("which", which); if( which >= TypesLen ) return; //TODO: catch errors //dispatch type by 'which' //for which>=TypesLen try to read an int; //the int type is provided by SelectWithDefault //the code for reading these ints should actually // not be executed, since always which::type t; \ ar >> boost::serialization::make_nvp("data", t); \ var = t; \ } break;\ /**/ BOOST_PP_REPEAT( BOOST_VARIANT_LIMIT_TYPES, BOOST_SERIALIZATION_VARIANT_SWITCH_MACRO, _ ) #undef BOOST_SERIALIZATION_VARIANT_SWITCH_MACRO }; } /////////////////////////////////////// // call to split template< typename Archive, BOOST_SERIALIZATION_VARIANT_TYPENAME_LIST() > inline void serialize( Archive& ar, boost::variant< BOOST_SERIALIZATION_VARIANT_TYPE_LIST() >& var, const unsigned int version ) { split_free(ar, var, version); } #undef BOOST_SERIALIZATION_VARIANT_TYPENAME_LIST_MACRO #undef BOOST_SERIALIZATION_VARIANT_TYPENAME_LIST #undef BOOST_SERIALIZATION_VARIANT_TYPE_LIST_MACRO #undef BOOST_SERIALIZATION_VARIANT_TYPE_LIST }} //namespace boost::serialization #endif