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_mapboost::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
#include
#include
#include
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 AbstractTemplatestd::string
{
public:
Derived(const std::string& n):AbstractTemplatestd::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():AbstractTemplatestd::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(AbstractTemplatestd::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
{
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");
AbstractTemplatestd::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_caststd::string*>(ab);
d = dynamic_cast(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;
}