Hi again
Currently I am trying to serialize some of my classes using shared_ptr's. Unfortunately, trying to do so throws the following assertion error when deserializing:
../basic_iarchive.cpp:390: const boost::archive::detail::basic_pointer_iserializer*
boost::archive::detail::basic_iarchive_impl::load_ pointer
(boost::archive::detail::basic_iarchive&, void*&, const
boost::archive::detail::basic_pointer_iserializer* , const
boost::archive::detail::basic_pointer_iserializer* (*)(const
boost::serialization::extended_type_info&)): Assertion `new_cid == cid' failed.
Aborted
Investigating this, I realized that I forgot to include <boost/serialization/shared_ptr.hpp> and was surprised that the code compiled nevertheless properly. Including the header didn't provide any improvement, either, and judging from the program file size, which remained the same, I assumed that the routines in this header were not even used at all, even after inclusion.
My first concern would be: Is this a legal way to serialize a shared_ptr:
Code:
typedef boost::shared_ptr<ProtocolFactory> ProtocolFactoryPtr;
// ...
vector<ProtocolFactoryPtr> factories = list_of(ProtocolFactoryPtr(new Iec1107OverSerialFactory()));
ProtocolFactoryPtr iec1107(new MeteringProtocolCompositeFactory(factories));
ofstream ofs("testIt.xml");
archive::xml_oarchive oxml(ofs);
oxml << serialization::make_nvp("supportedProtocols", iec1107);
// ...
ProtocolFactoryPtr newProtocolFactory;
ifstream ifs("testIt.xml");
archive::xml_iarchive ixml(ifs);
ixml >> serialization::make_nvp("supportedProtocols", newProtocolFactory);
Notice that ProtocolFactory is an abstract base class of Iec1107OverSerialFactory and MeteringProtocolCompositeFactory, which itself contains a shared_ptr-vector (vector<ProtocolFactoryPtr>). The three relevant classes are serialized as follows:
ProtocolFactory:
Code:
template<class archive> void serialize(archive &, const unsigned int)
{
}
Iec1107OverSerialFactory:
Code:
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/nvp.hpp>
BOOST_CLASS_EXPORT(Iec1107OverSerialFactory) // Boost must include Serialization info for this class even if its not directly referencd (e.g. by its base class)
template<class Archive> void Iec1107OverSerialFactory::serialize(Archive &ar, const unsigned int version) {
using boost::serialization::make_nvp;
ar & make_nvp("ProtocolFactory", boost::serialization::base_object<ProtocolFactory>(*this));
}
MeteringProtocolCompositeFactory:
Code:
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/nvp.hpp>
BOOST_CLASS_EXPORT(MeteringProtocolCompositeFactory) // Boost must include Serialization info for this class even if its not directly referencd (e.g. by its base class)
namespace boost {
namespace serialization {
template<class Archive> inline void save_construct_data(Archive &ar, const MeteringProtocolCompositeFactory *pf, const unsigned int version) {
using boost::serialization::make_nvp;
ar & make_nvp("IncludedProtocols", pf->getFactories());
}
template<class Archive> inline void load_construct_data(Archive &ar, MeteringProtocolCompositeFactory *pf, const unsigned int version) {
using boost::serialization::make_nvp;
std::vector<ProtocolFactoryPtr> factories;
ar & make_nvp("IncludedProtocols", factories);
::new(pf)MeteringProtocolCompositeFactory(factories);
}
}
}
template<class Archive> void MeteringProtocolCompositeFactory::serialize(Archive &ar, const unsigned int version) {
using boost::serialization::make_nvp;
ar & make_nvp("ProtocolFactory", boost::serialization::base_object<ProtocolFactory>(*this));
}
My second concern is the <boost/serialization/shared_ptr.hpp> header itself. Why isn't it required / used when executing "oxml << serialization::make_nvp("supportedProtocols", iec1107);" or "ixml >> serialization::make_nvp("supportedProtocols", newProtocolFactory);"?
Thank you for any help and best regards
Kessi