3

我有几个不同的 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。

4

2 回答 2

3

如果您已经有 Boost 依赖项,则可以使用BOOST_FUSION_ADAPT_STRUCT并使用 Fusion 迭代成员。这也允许您使用类型,这在纯预处理器方法中是不可能的。

您还需要将成员函数映射到融合序列以使其更加自动化。

总而言之:只需编写一个构造函数。

于 2012-11-09T19:14:57.813 回答
2

请参阅此答案,它显示了如何迭代类的成员。然后使用这些宏,这两个类可以像这样反映:

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);
于 2012-11-14T06:09:16.613 回答