2

次のマクロを確認してください。

#define INPUT (char, "microsecond", "us")(int, "millisecond", "ms")(int, "second", "s")(int, "minute", "min")(float, "hour", "h")

目標は、各タプルの前後に二重括弧を追加して、次のようにすることです。

((char, "microsecond", "us"))((int, "millisecond", "ms"))((int, "second", "s"))((int, "minute", "min"))((float, "hour", "h"))

ここで、次のマクロを使用してこの作業を行います。

#define ADD_PAREN_1(A, B, C) ((A, B, C)) ADD_PAREN_2
#define ADD_PAREN_2(A, B, D) ((A, B, C)) ADD_PAREN_1
#define ADD_PAREN_1_END
#define ADD_PAREN_2_END
#define OUTPUT0 ADD_PAREN_1 INPUT
#define OUTPUT1 BOOST_PP_CAT( OUTPUT0, _END )

結果は次のとおりです。

OUTPUT0は問題ありません:

((char, "microsecond", "us")) ((int, "millisecond", C)) ((int, "second", "s")) ((int, "minute", C)) ((float, "hour", "h")) ADD_PAREN_2

ただし、BOOST_PP_CATが呼び出されると、OUTPUT1の結果は次のようになります。

float

私はこの振る舞いを理解していません。ヒントはありますか?

VisualStudio2010を使用していることに注意してください

4

1 に答える 1

2

プリプロセッサは、スキャンと拡張によって機能します。したがって、OUTPUT0マクロを展開すると、次のようになります。

ADD_PAREN_1 INPUT
^

次に、次のトークンをスキャンして、それが括弧であるかどうかを確認します。括弧である場合はADD_PAREN_1、関数マクロとして呼び出されます。ただし、INPUTのみが表示されるため、を呼び出しませんADD_PAREN_1。次に、次のトークンをスキャンして展開します。

ADD_PAREN_1 INPUT
            ^

その結果、次のようになります。

ADD_PAREN_1 (char, "microsecond", "us")(int, "millisecond", "ms")(int, "second", "s")(int, "minute", "min")(float, "hour", "h")
            ^

次に、を使用しようとすると、次OUTPUT1のように展開されます。

BOOST_PP_CAT( OUTPUT0, _END )

これはトークンBOOST_PP_CATを展開OUTPUT0してから連結するので、最終的には次のようになります。

 ADD_PAREN_1 (char, "microsecond", "us")(int, "millisecond", "ms")(int, "second", "s")(int, "minute", "min")(float, "hour", "h") ## _END

ご覧のとおり、括弧をで連結していますが_END、これは許可されておらず、コンパイラエラーが発生します。Visual Studioでは、プリプロセッサが不思議な方法で機能するため、異なる結果が表示される場合があります。

OUTPUT0最終的に、それを機能させるには、マクロに次のような追加のスキャンを適用する必要があります。

#define X(x) x
#define OUTPUT0 X(ADD_PAREN_1 INPUT)

これはCプリプロセッサで動作しますが、Visual Studioで正確に動作するかどうかはわかりません(現在、チェックするためのアクセス権がありません)が、これが動作することはわかっています。

#define ADD_PAREN(x) BOOST_PP_CAT(ADD_PAREN_1 x, _END)
#define ADD_PAREN_1(A, B, C) ((A, B, C)) ADD_PAREN_2
#define ADD_PAREN_2(A, B, D) ((A, B, C)) ADD_PAREN_1
#define ADD_PAREN_1_END
#define ADD_PAREN_2_END
#define OUTPUT1 ADD_PAREN(INPUT)

これは、彼らがブーストでそれを行う方法に似ています。ここで、 BOOST_FUSION_ADAPT_ASSOC_STRUCT_FILLERマクロがどのように使用されているかを確認してください

于 2013-01-22T19:28:18.163 に答える