我喜欢我的常规继承lambda技巧:
我之前已经写过这个。
我相信我曾看到Sumant Tambe在他最近的cpptruths.com
帖子中使用过它。
演示
这里有一个演示,稍后会添加一些说明。
最重要的技巧是我使用boost::variant
来隐藏类型代码枚举。但是,即使您保留自己的类型判别逻辑(只需要更多的编码),该原则也适用。
立即测试
#include <boost/serialization/variant.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <fstream>
#include <iostream>
using namespace boost;
namespace util {
template<typename T, class...Fs> struct visitor_t;
template<typename T, class F1, class...Fs>
struct visitor_t<T, F1, Fs...> : F1, visitor_t<T, Fs...>::type {
typedef visitor_t type;
visitor_t(F1 head, Fs...tail) : F1(head), visitor_t<T, Fs...>::type(tail...) {}
using F1::operator();
using visitor_t<T, Fs...>::type::operator();
};
template<typename T, class F> struct visitor_t<T, F> : F, boost::static_visitor<T> {
typedef visitor_t type;
visitor_t(F f) : F(f) {}
using F::operator();
};
template<typename T=void, class...Fs>
typename visitor_t<T, Fs...>::type make_visitor(Fs...x) { return {x...}; }
}
using util::make_visitor;
namespace my_types {
struct A1 {
std::string data;
};
struct A2 {
double data;
};
struct A3 {
std::vector<int> data;
};
template <typename A> static inline void serialize(A& ar, A1& a, unsigned) { ar & a.data; }
template <typename A> static inline void serialize(A& ar, A2& a, unsigned) { ar & a.data; }
template <typename A> static inline void serialize(A& ar, A3& a, unsigned) { ar & a.data; }
static inline void display(std::ostream& os, A3 const& a3) { os << "display A3: " << a3.data.size() << " elements\n"; }
template <typename T> static inline void display(std::ostream& os, T const& an) { os << "display A1 or A2: " << an.data << "\n"; }
using AnyA = variant<A1,A2,A3>;
AnyA generate() {
switch (rand()%3) {
case 0: return A1{ "data is a string here" };
case 1: return A2{ 42 };
case 2: return A3{ { 1,2,3,4,5,6,7,8,9,10 } };
default: throw std::invalid_argument("rand");
}
}
}
using my_types::AnyA;
void write_archive(std::string const& fname)
{
std::vector<AnyA> As;
std::generate_n(back_inserter(As), 10, my_types::generate);
std::ofstream ofs(fname, std::ios::binary);
archive::text_oarchive oa(ofs);
oa << As;
}
template <typename F>
void process_archive(std::string const& fname, F process)
{
std::ifstream ifs(fname, std::ios::binary);
archive::text_iarchive ia(ifs);
std::vector<AnyA> As;
ia >> As;
for(auto& a : As)
apply_visitor(process, a);
}
int main() {
srand(time(0));
write_archive("archive.txt");
auto visitor = make_visitor(
[](my_types::A2& a3) {
std::cout << "Skipping A2 items, just because we can\n";
display(std::cout, a3);
},
[](auto& other) {
std::cout << "Processing (other)\n";
display(std::cout, other);
}
);
process_archive("archive.txt", visitor);
}
打印
Processing (other)
display A3: 10 elements
Skipping A2 items, just because we can
display A1 or A2: 42
Processing (other)
display A1 or A2: data is a string here
Processing (other)
display A3: 10 elements
Processing (other)
display A1 or A2: data is a string here
Processing (other)
display A1 or A2: data is a string here
Processing (other)
display A3: 10 elements
Processing (other)
display A1 or A2: data is a string here
Processing (other)
display A3: 10 elements
Processing (other)
display A3: 10 elements
type_index
是否是连续的并从零开始? - Yakk - Adam Nevraumont