Boost logo

Boost :

From: troy d. straszheim (troy_at_[hidden])
Date: 2005-02-10 08:42:12


Richard Crossley wrote:
> Why use bind here at all?

I think it's easier to read without it, too.

Robert Ramey wrote:
> On my machine the results for test_variant are:
>
> fail borland 5.51
> fail borland 5.64
> fail msvc 6
> fail VC 8.0
>
> pass VC 7.1
> pass gcc 3.3
>

I don't have access to any of those failing compilers... Attached is
another version that doesn't use bind(), which makes the code
essentially what Richard sent me modulo some cosmetic changes. We'd
come up with largely the same solution, but Richard totally beat me in
the style department.

What effect does that have on the problematic compilers?

-t


#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]>
// Richard Crossley <rdc_at_[hidden]>
//
// 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.
//

#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));
        }
      };

      template<typename Archive>
      struct save_visitor : static_visitor<>
      {
        save_visitor(Archive &ar) : archive_(ar) { }

        template<typename T>
        void operator()(T const & value ) const
        {
          archive_ << BOOST_SERIALIZATION_NVP(value);
        }

        Archive& archive_;
      };

    } // 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. The
      // variant gets assigned only when the compile-time Base::index
      // member of variant_in is equal to the runtime "which". The
      // trick is: at the level that this condition is satisfied and
      // the logic fires, the template parameter T of
      // variant_in<T,Base> is the type we need to create and asssign
      // to the variant.
      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);
      apply_visitor( variant::save_visitor<Archive>(ar), 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