Boost logo

Boost Users :

Subject: Re: [Boost-users] [Serialization] XML serialization of class withabstract template ancestors
From: Robert Ramey (ramey_at_[hidden])
Date: 2009-10-29 23:19:06


I would be very suspicious of

BOOST_SERIALIZATION_BASE_OBJECT_NVP(AbstractTemplate<std::string>)

since the "name" is taken from the argument. Look at this macro definition and
expand it by hand.

If you car run under the debugger that would also indicate the call tree which
would be useful.

Robert Ramey
  "Terry Roberts" <terryr_at_[hidden]> wrote in message news:1ecb94bb0910291517s7adf23fqa5c51720d254e0b6_at_mail.gmail.com...
  Hi,

  I'm having some trouble using the Serialization library with a class derived from an abstract template (example code below). What I'd like to do is serialize instances of the derived type through a base class pointer (polymorphic) using the XML archive. The code below works fine using both the text and binary archives, but fails at runtime with the XML archive. The exception thrown is boost::archive::xml_archive_exception with the message "uninitialized exception".

  My environment:
  GCC 4.1.2 on RHEL 5.3
  Boost v1.37

  I've also attempted to use Boost 1.40 (although I didn't see anything to suggest relevant changes), which results in link errors (undefined references to members of boost::archive::detail::archive_serializer_map<boost::archive::xml_iarchive> and boost::serialization::void_cast_detail::void_caster among others).

  Any help would be appreciated. Thanks.

  #include <iostream>
  #include <string>
  #include <sstream>
  #include <boost/serialization/serialization.hpp>
  #include <boost/archive/xml_iarchive.hpp>
  #include <boost/archive/xml_oarchive.hpp>
  #include <boost/serialization/export.hpp>

  class AbstractBase
  {
  public:
    AbstractBase(const std::string& n):name(n) {}
    virtual ~AbstractBase() {}

    virtual std::ostream& print(std::ostream& os) const = 0;

  protected:
    AbstractBase():name("UNKNOWN BASE") {}

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

    std::string name;
  };

  template <class T>
  class AbstractTemplate : public AbstractBase
  {
  public:
    AbstractTemplate(const std::string& n):AbstractBase(n) {}
    virtual ~AbstractTemplate() {}

    virtual void doSomething(const T& t) = 0;

  protected:
    AbstractTemplate():AbstractBase("UKNOWN TEMPLATE") {}

    friend class boost::serialization::access;
    template<class Archive> void serialize(Archive& ar, const uint32_t version)
    {
      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(AbstractBase);
    }
  };

  class Derived : public AbstractTemplate<std::string>
  {
  public:
    Derived(const std::string& n):AbstractTemplate<std::string>(n) {}
    virtual ~Derived() {}

    std::ostream& print(std::ostream& os) const { return os << "Derived name: " << name << std::endl; }

    void doSomething(const std::string& str) { print(std::cout << str << ": "); }

  protected:
    Derived():AbstractTemplate<std::string>("UNKNOWN DERIVED") {}

    friend class boost::serialization::access;
    template<class Archive> void serialize(Archive& ar, const uint32_t version)
    {
      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(AbstractTemplate<std::string>);
    }
  };

  BOOST_CLASS_EXPORT(Derived)

  namespace boost {

  template <>
  struct is_abstract<AbstractBase >
  {
    typedef mpl::bool_<true> type;
    BOOST_STATIC_CONSTANT(bool, value = true);
  };

  template<class T>
  struct is_abstract<AbstractTemplate<T> >
  {
    typedef mpl::bool_<true> type;
    BOOST_STATIC_CONSTANT(bool, value = true);
  };

  } // namepsace boost

  int main(int argc, char** argv)
  {
    static const char XML_NAME[] = "Stuff";

    Derived* d = new Derived("test 1");
    AbstractTemplate<std::string>* at = d;
    AbstractBase* ab = d;

    std::cout << "before serialization:" << std::endl;
    d->doSomething("something");
    at->print(std::cout);
    ab->print(std::cout);

    /* serialization */
    std::stringstream ss;

    {
      boost::archive::xml_oarchive xmlOut(ss);
      xmlOut << boost::serialization::make_nvp(XML_NAME, ab);
    }

    delete ab;
    ab = NULL;

    std::cout << "Serialization:" << std::endl
          << ss.str() << std::endl;

    /* deserialization */
    {
      boost::archive::xml_iarchive xmlIn(ss);
      xmlIn >> boost::serialization::make_nvp(XML_NAME, ab);
    }

    at = dynamic_cast<AbstractTemplate<std::string>*>(ab);
    d = dynamic_cast<Derived*>(ab);

    if ((ab == NULL)
      || (at == NULL)
      || (d == NULL))
    {
      std::cout << "deserialization failed" << std::endl;
      return EXIT_FAILURE;
    }

    std::cout << "after deserialization:" << std::endl;
    d->doSomething("something");
    at->print(std::cout);
    ab->print(std::cout);
    delete ab;

    return EXIT_SUCCESS;
  }

------------------------------------------------------------------------------

  _______________________________________________
  Boost-users mailing list
  Boost-users_at_[hidden]
  http://lists.boost.org/mailman/listinfo.cgi/boost-users



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net