【问题标题】:Use C preprocessor to iterate over structure fields使用 C 预处理器迭代结构字段
【发布时间】:2012-10-30 03:32:40
【问题描述】:

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

【问题讨论】:

    标签: c++ templates macros c-preprocessor


    【解决方案1】:

    参见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);
    

    【讨论】:

      【解决方案2】:

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

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

      总而言之:只要写一个构造函数就行了。

      【讨论】:

      • 感谢回复pmr;我们还没有 boost 依赖,但我还是会研究一下。
      猜你喜欢
      • 1970-01-01
      • 2017-06-28
      • 1970-01-01
      • 2012-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多