3

同じ名前のフィールドを持ついくつかの異なる C++ 構造体とクラスがあり、頻繁にコピーする必要があります。私は次のようなことをしたいと思います:(basy疑似コードで)

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 のようなテンプレート エンジンについては既に認識しており、コード生成を行うプログラムを作成できることも認識しています。知っておく必要がある場合、私がこれを使用したいことの 1 つは、C++ 構造体から Google の protobuf を埋めることです。

4

2 に答える 2

3

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.

于 2012-11-09T19:14:57.813 に答える
2

クラスのメンバーを反復処理する方法を示すこの回答を参照してください。次に、これらのマクロを使用して、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 に答える