我想为
生成序列化/反序列化代码class Object
{
string a;
int b;
long c;
char d;
};
通过查看mpl序列,但我需要能够识别对象并将其检索回来,我无法弄清楚如何获取其成员的名称,我是否必须知道它
代码应该看起来像
void SerializeObject(ostream os)
{
serialize(object.a, os);
serialize(object.b, os);
//serialize(object.member, os);
}
我想用户生成上面的代码只定义一个对应于对象布局的mpl序列,是否可行,你能给我一些提示吗?
我的目标是:
用户为上述对象定义mpl::vector<String, int, long, char>
,我的metaprogram
可以生成所需的编码。
答案 0 :(得分:10)
考虑boost::fusion
,并使用宏BOOST_FUSION_ADAPT_STRUCT()
将您的结构提升为融合序列(随机访问),例如一旦定义了上述结构,就可以执行类似
BOOST_FUSION_ADAPT_STRUCT(
Object,
(std::string, a)
(int, b)
(long, c)
(char, d)
)
现在它已被提升,您可以简单地使用for_each
来迭代成员,例如:
template<typename archive>
struct serializer {
serializer(archive& ar):ar(ar) {}
template<typename T>
void operator()(const T& o) const {
ar & o; // assuming binary for example...
}
archive& ar;
};
template<typename archive, typename sequence>
void serialize(archive& ar, sequence const& v) {
boost::fusion::for_each(v, serializer<archive>(ar));
}
要使用,它应该如下:
Object foo; // instance to serialize
serialize(<archive>, foo);
答案 1 :(得分:2)
无法在模板中推断成员名称。您需要明确指定所有内容,如下所示:
template<typename ObjT, typename MemberT, MemberT ObjT::*Ptr>
struct member{};
mpl::vector
<
member<Object, string, &Object::a>,
member<Object, int, &Object::b>,
member<Object, long, &Object::c>,
member<Object, char, &Object::d>
>;
另一种选择是创建函数来帮助生成member
,为operator>>
定义member
,将member_vec
合并为operator>>
,member_vec
为member_vec
auto serializer =
mem(&Object::a) >>
mem(&Object::b) >>
mem(&Object::c) >>
mem(&Object::d);
合并为更大的{{1}}。由于您只使用该类型,编译器可以优化任何实际的函数调用
函数可以使用隐式模板参数,因此它可以使序列化程序使用更少的代码来定义:
{{1}}
我自己使用这两种技术制作了序列化器。第二个是我最满意的。
答案 2 :(得分:0)
您可以使用mpl::string
来表示成员名称。在我的应用程序中,我做了一些代码生成,发出类似以下内容。
typedef mpl::string < 'n', 'a', 'm', 'e' > name;
您可以使用mpl::c_str < name >::value
来获取字符串表示形式。即“名字”。
我存储了一系列这样的成员名称,成员指针的另一个序列,将它们压缩在一起,然后使用boost :: fusion查询算法之一来查找给定成员名称的成员指针。
如果您有兴趣,我会发布代码。目前我无法访问它,因为它在我的家用电脑上。