2

これをCPPマクロへの追加に関する私の質問から切り離します:

ここで誰かがBoost.Preprocessorライブラリのデータ型を使用してXマクロのようなものを実装したことがありますか?

4

1 に答える 1

3

X-Macroがどうあるべきかを調べたところ、あなたが求めているようなことをしたと思います。

私がやりたかったのは、一連のかなり類似したクラスのシリアル化を簡単かつ迅速にサポートすることです。私が抱えていた問題は、シリアル化を実行できるようにするために、いくつかのランタイム情報(int)をコンパイル時の型(クラス)に変換する必要があったことです。その仕事をするためにいくつかのcaseステートメントを書くこともできましたが、それはクラスを追加するたびにいくつかの関数を更新する必要があることを意味します。

この問題を回避するために、最初にマッピングを含むタプルのシーケンスを定義しました。

#define WIN_MESSAGE_TYPE_SEQ \
    ((EM_REPLACESEL, em_replacesel))((WM_CHAR, wm_char)) //...

大文字の名前はintを保持する定義であり、小文字の名前は私が別の場所で定義したクラスです。

次に、このシーケンスをいくつかのBoostプリプロセッサと組み合わせて使用​​して、あらゆる種類のコードを生成できます。たとえば、クラスの前方宣言を取得するには、次のようにします。

#define WIN_MESSAGE_TYPE_BUILD_MACRO(r, _data_, _elem_) \
    class BOOST_PP_TUPLE_ELEM(2,1,_elem_);

BOOST_PP_SEQ_FOR_EACH(WIN_MESSAGE_TYPE_BUILD_MACRO, BOOST_PP_NIL, WIN_MESSAGE_TYPE_SEQ)

#undef WIN_MESSAGE_TYPE_BUILD_MACRO

ランタイムマッピングをコンパイルするために、次のような一連のcaseステートメントを生成します。

#define WIN_MESSAGE_TYPE_BUILD_MACRO(r, _data_, _elem_) \
    case BOOST_PP_TUPLE_ELEM(2,0,_elem_): return win_message_serializer<BOOST_PP_TUPLE_ELEM(2,1,_elem_)>::serialize(msg, o_arch);

template <typename Archive>
void serialize_win_message (p_win_message_base msg, Archive& o_arch) {
    message_type_t message_type = msg->type();

    switch (message_type) {

    // This will generate a series of case statement for each message type that will invoke
    // the serializer for the correct types.
    BOOST_PP_SEQ_FOR_EACH(WIN_MESSAGE_TYPE_BUILD_MACRO, BOOST_PP_NIL, WIN_MESSAGE_TYPE_SEQ)

    default: //...
    };
}

#undef WIN_MESSAGE_TYPE_BUILD_MACRO

コード全体にはこれよりもかなり多くのことが含まれますが、これでもBoostプリプロセッサを使用してコードを生成する方法についてのアイデアが得られるはずです。私の例では、シーケンスを更新するだけで、クラスのシリアル化サポートをすばやく簡単に追加できます。

Boostプリプロセッサを使用しても、非常に読みやすいコードが生成されないことに注意してください。そのため、各マクロで使用されるマクロをできるだけ単純に保つようにしています。また、誰かがこの問題に対してよりエレガントな解決策を持っていても、私は驚かないでしょう。これは、私が余分な複雑さを気にしない個人的なプロジェクトのために思いついたものです。

于 2010-12-29T06:04:17.833 に答える