我有几个不同的C ++结构和具有相同名称字段的类,我必须经常复制。我想做类似的事情:(在bashy伪代码中)
struct S{double a;
double b;
double c;};
class C{public: void set_a(double a);
void set_b(double b);
void set_c(double c); };
S s; C c;
#FOR F in FIELDSOF(S)
c.set_${F}(${F});
#ENDFOR
是否一个好主意,有没有办法滥用C ++预处理器或C ++模板来实现这一目标?我用g ++和clang ++。
我已经知道像MAKO这样的模板引擎,而且我也知道我可以编写一个程序来进行代码生成。如果你必须知道,我想用它做的一件事就是从C ++结构中填充Google protobufs。
答案 0 :(得分:3)
如果您已经拥有Boost依赖关系,则可以使用BOOST_FUSION_ADAPT_STRUCT并使用Fusion迭代成员。这也允许您使用类型,这在纯预处理器方法中是不可能的。
您还需要将成员函数映射到融合序列,以使其更加自动化。
总而言之:只需编写一个构造函数。
答案 1 :(得分:2)
参见this answer,其中显示了如何迭代类的成员。然后使用这些宏,这两个类可以反映如下:
struct S
{
REFLECTABLE
(
(double) a,
(double) b,
(double) c
)
};
class C
{
private:
REFLECTABLE
(
(double) a,
(double) b,
(double) c
)
public:
void set_a(double a);
void set_b(double b);
void set_c(double c);
};
然后根据成员变量的名称创建一个通用赋值:
struct assign_fields_visitor
{
template<class FieldData1, class FieldData2>
void operator()(FieldData1 fd1, FieldData2 fd2)
{
if (strcmp(fd1.name(), fd2.name()) == 0)
{
fd1.get() = fd2.get();
}
}
};
struct assign_fields
{
template<class X, class FieldData>
void operator()(X & x, FieldData f)
{
visit_each(x, boost::bind(assign_fields_visitor(), f, _1));
}
};
template<class L, class R>
void assign(L & lhs, const R& rhs)
{
visit_each(rhs, boost::bind(assign_fields(), boost::ref(lhs), _1));
}
最后,它可以像这样调用:
S s; C c;
assign(c, s);