c++ - Serializing a derived class from an interface -
new: can use this, access.hpp?
template<class archive, class t> inline void serialize_adl(archive &, t &, const unsigned int);
this suggests can define different serialize takes object parameter.
thus code change below work?
i think question how add serialize method on interface class, invoke serialize method on derived sub-class.
class interface { public: virtual void avirtual() = 0; private: friend class boost::serialization::access; template<class archive, class t> void serialize_adl(archive & ar, t & object, const unsigned int version) { // work????? ar & object; } }; template<class t> class derived : interface { public: derived(t in) : m_data(in) {} virtual void avirtual() { // } private: t m_data; friend class boost::serialization::access; template<class archive> void serialize(archive & ar, const unsigned int version) { ar & m_data; } };
i following error compiler:
error c2039: 'serialize' : not member of 'interface'
which unusual because object inside smart pointer, should know type is:
std::unique_ptr<interface> object = std::unique_ptr<interface>(new derived<int>(5));
and when try serialise:
archive >> *object;
thus error.
there's 2 issues @ play here:
you serializing template class. not problem , yes can intrusively (member
serialize
) or non-intrusively (free functionserialize
via adl). documentation (serializing templates) states implementation ofshared_ptr<t>
serialization example of non-intrusive variant here:you serializing base/derived classes through polymorphic pointer. serialization part nothing special (you can
register_type
or should fine usingbase_object<interface>(this)
inside derived'sserialize
function.on deserialization side of things, however, need anticipate full list of possible concrete instance types serialized through polymorphic pointer.
boost_export_class
macro easiest way achieve this. have list concrete instances of template wish support, though:boost_class_export(derived<std::string>) boost_class_export(derived<double>) boost_class_export(derived<int>) // include subtypes can expect in input archive
or
boost_class_export_guid(derived<std::string>, "4ef5a3ff-168a-4242-846b-4886f48424b5") boost_class_export_guid(derived<double>, "d0ed9de6-584f-476d-9898-8234bcb4efdb") boost_class_export_guid(derived<int>, "505538f0-2dd1-43bd-92a2-506ed9659bbe") // include subtypes can expect in input archive
the complexity of situation - , confusion - arises fact serializing derived class template through polymorphic pointer. @ same time. conceptually both tackled.
slightly unrelated,
- yes, can use free function serialize, see 3rd alternative version below. gains little though, , requires
m_data
publicly accessible.- do not use
serialize_adl
implementation detail
here 3 samples integrates everything:
live on coliru - raw
interface*
live on coliru - same
shared_ptr<interface>
live on coliru - same non-intrusive
serialize
function
listing first sample
#include <boost/serialization/serialization.hpp> #include <boost/serialization/base_object.hpp> #include <boost/serialization/export.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <sstream> class interface { public: virtual void avirtual() = 0; virtual ~interface() {} private: friend class boost::serialization::access; template<class archive> void serialize(archive&, unsigned) { } }; boost_serialization_assume_abstract(interface) template<class t> class derived : public interface { public: derived(t in = 0) : m_data(in) {} virtual void avirtual() { /*do something*/ } t const& getdata() const { return m_data; } private: t m_data; friend class boost::serialization::access; template<class archive> void serialize(archive& ar, unsigned) { ar & boost::serialization::base_object<interface>(*this); //// alternatively, if don't want make abstract base serializable: // boost::serialization::void_cast_register<derived, interface>(); ar & m_data; } }; boost_class_export(derived<std::string>) boost_class_export(derived<double>) boost_class_export(derived<int>) // include subtypes can expect in input archive int main() { std::stringstream ss; { boost::archive::text_oarchive oa(ss); interface* o = new derived<int>(42); oa << o; delete o; } std::cout << "serialized: '" << ss.str() << "'\n"; { boost::archive::text_iarchive ia(ss); interface* o = nullptr; ia >> o; if (auto p = dynamic_cast<derived<int>*>(o)) std::cout << "deserialized derived<int> data: " << p->getdata() << "\n"; delete o; } }
sample output:
serialized: '22 serialization::archive 11 0 1 1 12 derived<int> 1 0 0 42 ' deserialized derived<int> data: 42
Comments
Post a Comment