There's no builtin way, but you can, of course, always abstract any interface you wish, with the right set of trade-offs.
Here's one imagined solution that uses a custom PolyArchive
that could be a reference to either the polymorphic_oarchive
or polymorphic_iarchive
:
#include <boost/serialization/serialization.hpp>
#include <boost/archive/polymorphic_oarchive.hpp>
#include <boost/archive/polymorphic_iarchive.hpp>
#include <boost/archive/polymorphic_text_oarchive.hpp>
#include <boost/archive/polymorphic_text_iarchive.hpp>
#include <boost/variant.hpp>
#include <sstream>
using PolyArchive = boost::variant<
boost::archive::polymorphic_oarchive&,
boost::archive::polymorphic_iarchive&
>;
struct /*abstract*/ ISerializable {
virtual void serialize(PolyArchive, unsigned) = 0;
};
struct MyClass : ISerializable {
std::string data_member = "Morgana"; // something to serialize
// the one method we need to implement
virtual void serialize(PolyArchive ar, unsigned) override;
};
Now, let's do the implementation a bit with a bit of C++14 fairy-dust:
void MyClass::serialize(PolyArchive ar, unsigned) {
boost::apply_visitor(make_visitor([=](auto& ar) {
ar & data_member;
}), ar);
}
The astute reader will spot that the user still supplies the template method, but hides it inside a virtual method that actually takes a PolyArchive
at compile time.
Full Demo
See it Live On Coliru, printing:
Serialized: 22 serialization::archive 11 0 0 7 Morgana
Roundtripped: 22 serialization::archive 11 0 0 7 Morgana
Code:
#include <boost/serialization/serialization.hpp>
#include <boost/archive/polymorphic_oarchive.hpp>
#include <boost/archive/polymorphic_iarchive.hpp>
#include <boost/archive/polymorphic_text_oarchive.hpp>
#include <boost/archive/polymorphic_text_iarchive.hpp>
#include <boost/variant.hpp>
#include <sstream>
using PolyArchive = boost::variant<
boost::archive::polymorphic_oarchive&,
boost::archive::polymorphic_iarchive&
>;
struct /*abstract*/ ISerializable {
virtual void serialize(PolyArchive, unsigned) = 0;
};
struct MyClass : ISerializable {
std::string data_member = "Morgana"; // something to serialize
// the one method we need to implement
virtual void serialize(PolyArchive ar, unsigned) override;
};
int main()
{
std::stringstream ss;
{
// serialize:
boost::archive::polymorphic_text_oarchive output(ss);
MyClass object;
output << object;
}
// Debug dump;
std::cout << "Serialized: " << ss.str();
{
// read back:
boost::archive::polymorphic_text_iarchive input(ss);
MyClass cloned;
input >> cloned;
std::cout << "Roundtripped: ";
boost::archive::polymorphic_text_oarchive pta(std::cout);
pta << cloned;
}
}
////////////////////////////////
// implementation:
namespace /*detail*/ {
template <typename F> struct wrap_visitor : boost::static_visitor<> {
wrap_visitor(F const& f) : f_(f) { }
wrap_visitor(F&& f) : f_(std::move(f)) { }
template<typename... T> void operator()(T&&... t) const {
f_(std::forward<T>(t)...);
}
private:
F f_;
};
template <typename F>
wrap_visitor<F> make_visitor(F&& f) {
return std::forward<F>(f);
}
}
void MyClass::serialize(PolyArchive ar, unsigned) {
boost::apply_visitor(make_visitor([=](auto& ar) {
ar & data_member;
}), ar);
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…