Use C preprocessor to iterate over structure fields

…衆ロ難τιáo~ 提交于 2019-12-23 20:17:39

问题


I have several different C++ structs and classes with fields of the same name, that I have to copy between frequently. I would like to do something like: (in bashy pseudocode)

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

Whether or not it a good idea, is there a way to abuse either the C++ preprocessor or C++ templates to achieve this? I use g++ and clang++.

I am already aware of templating engines like MAKO, and I'm also aware I could write a program to do code generation. If you must know, one of the things I would like to use this for is filling Google protobufs from C++ structs.


回答1:


If you already have a Boost dependency, you can use BOOST_FUSION_ADAPT_STRUCT and use Fusion to iterate over the members. This also allows you to work with types, which is not possible in a pure preprocessor approach.

You also will need to map member functions to fusion sequences to make that more automatic.

All in all: Just write a constructor.




回答2:


See this answer, which shows how to iterate over the members of a class. Then using those macros, the two classes can be reflectable like this:

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); 
};

Then to create a generic assignment, based on the name of the member variable:

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));
}

Finally, it can be called like this:

S s; C c;
assign(c, s);


来源:https://stackoverflow.com/questions/13314422/use-c-preprocessor-to-iterate-over-structure-fields

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!