|
Boost : |
From: troy d. straszheim (troy_at_[hidden])
Date: 2005-02-08 23:39:23
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_at_[hidden]>
// 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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk