I need to serialize all the options on my CommunicationLayer, which is basically a wrapper around serial port, which I will use in an initialization file of sorts.
This class doesn't have a default constructor, but implements a pure virtual class. When I first ran this I got the exception that I didn't register/export the derived class. So I did that. But when I added the export I got the exception that it couldn't find a save/load function:
no matching function for call to ‘save(boost_1_69_0::archive::xml_oarchive&, const amp::communication::RS485CommunicationLayer&, const boost_1_69_0::serialization::version_type&)’
save(ar, t, v);
This is true! But I can't use the save/load and use save_construct_data and load_construct_data, because the absence of a default constructor. How do I tell boost/serde to use these instead?? Is it the SPLIT_FREE macro?
I'm trying to work myself through the documentation, but it's really hard to find everything.
Following are the base and derived classes, I tried to shorten the derived class as much as possible.
//BASE
class ICommunicationLayer {
friend class boost::serialization::access;
template<class Archive>
inline void serialize(Archive & ar, const unsigned int file_version) {};
public:
virtual ~ICommunicationLayer();
virtual std::size_t write(const char* const buffer, std::size_t buffSize) = 0;
virtual std::size_t readUntil(std::vector<char>& buffer, char delim, std::chrono::microseconds timeout) = 0;
};
// DERIVED
#include "ICommunicationLayer.h"
#include <boost/asio.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/split_free.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/nvp.hpp>
namespace amp {
namespace communication {
class RS485CommunicationLayer final : public ICommunicationLayer {
public:
RS485CommunicationLayer(
const std::string& path,
unsigned int baud_rate,
// other options
);
~RS485CommunicationLayer();
std::size_t write(const char* const buffer, const size_t size) override;
std::size_t readUntil(std::vector<char>& buffer, char delim,std::chrono::microseconds timeout) override;
std::string getPath() const;
private:
friend class boost::serialization::access;
std::string path;
// rest of impl
};
} /* namespace communication */
} /* namespace amp */
BOOST_SERIALIZATION_SPLIT_FREE(amp::communication::RS485CommunicationLayer)
BOOST_CLASS_EXPORT(amp::communication::RS485CommunicationLayer)
namespace boost_1_69_0 {
namespace serialization {
template<class Archive>
inline void save_construct_data(Archive& ar, const amp::communication::RS485CommunicationLayer* comLayer, const unsigned int version) {
ar << boost::serialization::make_nvp(
BOOST_PP_STRINGIZE(amp::communication::ICommunicationLayer),
boost::serialization::base_object<amp::communication::ICommunicationLayer>(*comLayer)
);
ar << boost::serialization::make_nvp("path", const_cast<std::string>(comLayer->getPath());
// other options
}
template<class Archive>
inline void load_construct_data(Archive& ar, amp::communication::RS485CommunicationLayer* comLayer, const unsigned int version) {
ar >> boost::serialization::base_object<amp::communication::ICommunicationLayer>(*comLayer);
std::string path;
ar >> path;
// other options
new(comLayer) amp::communication::RS485CommunicationLayer(path, baudrate, /* other options */);
}
}
}