1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
| #include <iostream>
#include <sstream>
#include <string>
#include <memory>
#include <stdexcept>
#include <unordered_map>
#include <boost/any.hpp>
//template<class... Ts>
class Archive
{
struct SerializerBase
{
std::string name;
SerializerBase(std::string name)
: name(std::move(name))
{}
virtual ~SerializerBase()
{}
virtual boost::any extract(std::istream & is) = 0;
};
template<class T>
struct Serializer : SerializerBase
{
Serializer()
: SerializerBase(typeid(T).name())
{}
boost::any extract(std::istream & is)
{
T x;
is >> x;
return boost::any(x);
}
};
std::unordered_map<std::string, std::unique_ptr<SerializerBase>> serializer;
template<class T>
static std::string get_name()
{
return typeid(T).name();
}
public:
template<class T>
void push()
{
serializer.insert(decltype(serializer)::value_type(
get_name<T>(), decltype(serializer)::mapped_type(new Serializer<T>)));
}
template<class T>
void serialize(std::ostream & os, T const & x) const
{
os << get_name<T>() << ' ' << x << '\n';
}
boost::any deserialize(std::istream & is) const
{
std::string s;
is >> s;
auto it = serializer.find(s);
if (it == serializer.end()) {
throw std::runtime_error("deserializer not found");
}
return it->second->extract(is);
}
};
int main()
{
int n = 1;
std::string s = "plop";
Archive a;
a.push<int>();
a.push<std::string>();
std::stringstream io;
a.serialize(io, n);
a.serialize(io, s);
std::cout << "serialize:\n" << io.rdbuf() << "\n";
io.seekg(0);
int n2 = 0;
std::string s2;
while (std::istream::sentry(io)) {
boost::any any = a.deserialize(io);
if (int * pi = boost::any_cast<int>(&any)) {
n2 = *pi;
}
else if(std::string * ps = boost::any_cast<std::string>(&any)) {
s2 = std::move(*ps);
}
else {
std::cerr << "no matching: " << any.type().name() << '\n';
}
}
std::cout << "deserialize:\n"
<< "n1: " << n2 << '\n'
<< "s1: " << s2 << '\n';
} |