0

The following uses mpl::list to initialize a boost variant. Then it serialize the variant. It compiles and work fine on save but not load. The compile even failed for load. Does anyone know what the issue is? thanks

Attribute.h

#include <string>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>

template <class T>
class Attribute
{
public:
      Attribute() {}
      Attribute( const std::string& name, const T& t ) : name_( name ), t_( t ) {}

      std::string name() const { return name_; }
      const T& get() const { return t_; }
      void set( const T& t ) { t_ = t; }

      friend class boost::serialization::access;
      template<class Archive>
      void serialize( Archive& ar, const unsigned int version )
      {
            ar & BOOST_SERIALIZATION_NVP( name_ );
            ar & BOOST_SERIALIZATION_NVP( t_ );
      }

private:
      std::string name_;
      T t_;
};

AttributeAny.h

#include <boost/variant.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/variant/apply_visitor.hpp>

template <class T>
class AttributeAny
{
public:
      typedef typename boost::make_variant_over<T>::type Type;

      AttributeAny() {}
      AttributeAny( const Type& t ) : t_( t ) { }

private:
      template <class Archive>
      class SerializeVisitor : public boost::static_visitor<>
      {
      public:
            SerializeVisitor( Archive& ar ) : ar_( ar ) {}
            template <typename U>
            void operator()( const U& t ) const
            {
                  ar_ & BOOST_SERIALIZATION_NVP( t );
            }
      private:
            Archive& ar_;
      };

public:

      friend class boost::serialization::access;
      template<class Archive>
      void serialize( Archive& ar, const unsigned int version )
      {
            boost::apply_visitor( SerializeVisitor<Archive>( ar ), t_ );
      }

private:
      Type t_;
};

main.cpp

#include <iostream>
#include <sstream>
#include <boost/mpl/list.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include "mylib/Attribute.h"
#include "mylib/AttributeAny.h"


using namespace std;

class A
{
public:
      A() {}
      A( const std::string& name ) : name_( name ) {}
      std::string name() const { return name_; }

      friend class boost::serialization::access;
      template<class Archive>
      void serialize( Archive& ar, const unsigned int version )
      {
            ar & BOOST_SERIALIZATION_NVP( name_ );
      }

private:
      std::string name_;
};

using namespace std;

typedef AttributeAny<boost::mpl::list<
//            Attribute<double>
//          , Attribute<long>
            A // this, doesn't even work, on serialize load
> > Any;

int main()
{

      A a( "a" );
      Any any( a );
      Any any1( a );

      std::stringstream ss;
      boost::archive::xml_oarchive oa( ss );
      oa << BOOST_SERIALIZATION_NVP( a );
      cout << ss.str() << endl;

      // these 2 lines below cause compilation error
      // serialize save work just fine...
      boost::archive::xml_iarchive ia( ss );
      ia >> BOOST_SERIALIZATION_NVP( any1 );

      return 0;
}

Error compiling:

/usr/local/boost/boost_1_48_0/include/boost/archive/detail/check.hpp: In function ‘void boost::archive::detail::check_const_loading() [with T = const A]’:
/usr/local/boost/boost_1_48_0/include/boost/archive/detail/iserializer.hpp:577:   instantiated from ‘void boost::archive::load(Archive&, T&) [with Archive = boost::archive::xml_iarchive, T = const A]’
/usr/local/boost/boost_1_48_0/include/boost/archive/detail/common_iarchive.hpp:66:   instantiated from ‘void boost::archive::detail::common_iarchive<Archive>::load_override(T&, int) [with T = const A, Archive = boost::archive::xml_iarchive]’
/usr/local/boost/boost_1_48_0/include/boost/archive/basic_xml_iarchive.hpp:86:   instantiated from ‘void boost::archive::basic_xml_iarchive<Archive>::load_override(const boost::serialization::nvp<T>&, int) [with T = const A, Archive = boost::archive::xml_iarchive]’
/usr/local/boost/boost_1_48_0/include/boost/archive/xml_iarchive.hpp:93:   instantiated from ‘void boost::archive::xml_iarchive_impl<Archive>::load_override(T&, int) [with T = const boost::serialization::nvp<const A>, Archive = boost::archive::xml_iarchive]’
/usr/local/boost/boost_1_48_0/include/boost/archive/detail/interface_iarchive.hpp:60:   instantiated from ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator>>(T&) [with T = const boost::serialization::nvp<const A>, Archive = boost::archive::xml_iarchive]’
/usr/local/boost/boost_1_48_0/include/boost/archive/detail/interface_iarchive.hpp:67:   instantiated from ‘Archive& boost::archive::detail::interface_iarchive<Archive>::operator&(T&) [with T = const boost::serialization::nvp<const A>, Archive = boost::archive::xml_iarchive]’
~/ws/mylib/AttributeAny.h:34:   instantiated from ‘void AttributeAny<T>::SerializeVisitor<Archive>::operator()(const U&) const [with U = A, Archive = boost::archive::xml_iarchive, T = boost::mpl::list<A, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>]’
/usr/local/boost/boost_1_48_0/include/boost/variant/variant.hpp:858:   instantiated from ‘typename Visitor::result_type boost::detail::variant::invoke_visitor<Visitor>::internal_visit(T&, int) [with T = A, Visitor = const AttributeAny<boost::mpl::list<A, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> >::SerializeVisitor<boost::archive::xml_iarchive>]’
...
../src/test_mylib.cpp:61:   instantiated from here

/usr/local/boost/boost_1_48_0/include/boost/archive/detail/check.hpp:162: error: invalid application of ‘sizeof’ to incomplete type ‘boost::STATIC_ASSERTION_FAILURE<false>‘
/usr/local/boost/boost_1_48_0/include/boost/archive/detail/check.hpp:162: error: invalid application of ‘sizeof’ to incomplete type ‘boost::STATIC_ASSERTION_FAILURE<false>‘
make: *** [src/test_mylib.o] Error 1
surfcode
  • 445
  • 1
  • 5
  • 20

1 Answers1

0

You might want to try changing your function operator on your SerializeVisitor from

template <typename U>
void operator()( const U& t ) const

to

template <typename U>
void operator()( U& t ) const

Of course, boost already includes serialization support for boost::variant, in boost/serialization/variant.hpp, so why not just use that?

Mark Stijnman
  • 97
  • 1
  • 1