
troy d. straszheim wrote:
// the variant. Is there a better idiom for this than // preprocessor metaprogramming inside a switch statement?
There is a better idiom, Richard Crossley sent me a very cool mpl::fold trick. (Thanks Richard!) Improved serialization/variant.hpp attached. troy d. straszheim #ifndef BOOST_SERIALIZATION_VARIANT_HPP #define BOOST_SERIALIZATION_VARIANT_HPP // // boost/seriaization/variant.hpp // non-intrusive serialization of variant types // // copyright (c) 2005 // troy d. straszheim <troy@resophonic.com> // http://www.resophonic.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) // // See http://www.boost.org for updates, documentation, and revision history. // // thanks to Robert Ramey, Peter Dimov, and Richard Crossley. // #include <boost/serialization/serialization.hpp> #include <boost/serialization/split_free.hpp> #include <boost/variant/apply_visitor.hpp> #include <boost/bind.hpp> #include <boost/ref.hpp> #include <boost/variant.hpp> #include <boost/variant/static_visitor.hpp> #include <boost/mpl/at.hpp> #include <boost/mpl/int.hpp> #include <boost/mpl/size.hpp> #include <boost/mpl/greater_equal.hpp> #include <boost/mpl/eval_if.hpp> #include <boost/mpl/identity.hpp> #include <boost/throw_exception.hpp> #include <boost/archive/archive_exception.hpp> #include <boost/preprocessor/repetition/repeat.hpp> #include <boost/serialization/split_free.hpp> #include <boost/mpl/fold.hpp> #include <boost/mpl/int.hpp> namespace boost { namespace serialization { namespace variant { struct stop_tag { }; template <typename Value = mpl::void_, typename Base = stop_tag> struct variant_in : Base { enum { index = 1 + Base::index }; template <typename Archive, typename Variant> static void exec(Archive& ar, int discriminator, Variant& var) { if (discriminator == index) { Value value; ar >> BOOST_SERIALIZATION_NVP(value); var = value; return; } Base::exec(ar,discriminator,var); } }; using boost::archive::archive_exception; template <> struct variant_in<mpl::void_, stop_tag> { enum { index = -1 }; template <typename Archive,typename V> static void exec(Archive& ar,int discriminator,V& v) { boost::throw_exception(archive_exception(archive_exception::stream_error)); } }; struct save_visitor : boost::static_visitor<> { template<class Archive, class T> void operator()(Archive & ar, T const & value ) const { ar << BOOST_SERIALIZATION_NVP(value); } }; } // namespace boost::serialization::variant template<class Archive,BOOST_VARIANT_ENUM_PARAMS(typename T)> void load(Archive & ar, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& v, unsigned int version) { typedef typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types types; int which; ar >> BOOST_SERIALIZATION_NVP(which); // fold<> from Richard Crossley. Wicked. The call to exec // starts in the most-derived part of the composite class // generated by fold and recursively works its way down. mpl::fold< types, variant::variant_in<>, variant::variant_in<mpl::_2,mpl::_1> >::type::exec(ar,which,v); } template<class Archive,BOOST_VARIANT_ENUM_PARAMS(typename T)> void save(Archive & ar, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const & v, unsigned int version) { int which = v.which(); ar << BOOST_SERIALIZATION_NVP(which); // thx Peter Dimov apply_visitor( bind( variant::save_visitor(), boost::ref(ar), _1 ), v ); } template<class Archive,BOOST_VARIANT_ENUM_PARAMS(typename T)> inline void serialize(Archive & ar, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> & v, unsigned int file_version) { split_free(ar,v,file_version); } } } #endif //BOOST_SERIALIZATION_VARIANT_HPP