4

ある種のマクロ「オーバーロード」を実行しようとしているので、MACRO(何か)はMACRO(何か、その他)とは異なる方法で展開されます。

ここから取得したスニペット(100%移植可能かどうかはわかりません)とBoost PPライブラリのいくつかの関数を使用して、それを機能させることができました:D

//THESE TWO COUNT THE NUMBER OF ARGUMENTS
#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N
#define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1)

//THIS ONE RETURNS THE PARAMETER AT POSITION _i FROM A LIST OF __VA_ARGS__
#define VA_ARG(_i, ...) BOOST_PP_ARRAY_ELEM(_i, (VA_NARGS(__VA_ARGS__), (__VA_ARGS__)))

//AND THIS ONE IS THE 'OVERLOADED' MACRO ;)
#define TEST(...) BOOST_PP_IF(BOOST_PP_EQUAL(1, VA_NARGS(__VA_ARGS__)), function_A(VA_ARG(0, __VA_ARGS__)), \ //1 parameter
                  BOOST_PP_IF(BOOST_PP_EQUAL(2, VA_NARGS(__VA_ARGS__)), function_B(VA_ARG(0, __VA_ARGS__) + VA_ARG(1, __VA_ARGS__)), \ //2 parameters
                  BOOST_PP_IF(BOOST_PP_EQUAL(3, VA_NARGS(__VA_ARGS__)), function_C(VA_ARG(1, __VA_ARGS__) + VA_ARG(2, __VA_ARGS__)), BOOST_PP_EMPTY())) // 3 parameters and so on ...

So       TEST(a) = function_A(a)
      TEST(a, b) = function_B(a + b)
   TEST(a, b, c) = function_C(b + c)

今、私がやりたい他の2つのことがまだ欠けています。

  1. (これは、解決しなくてもかまいません)「バリアント」とそれに対応する「出力」の数を取得すると、上記のようなコードが生成されるマクロを記述できると思います。上記の例を生成するには、TEMPLATE(3、function_A(...)、function_B(...)、function_C(...))のようなものを使用します。

  2. TEST()が引数なしで呼び出されるとどうなりますか?さて、VA_NARGSは1に展開されます。しかし、最初の引数は ""(何もありません)です。__VA_ARGS__この状況に対応するために「オーバーロード」関数を拡張するために、「ゼロ」引数を検出するか、「ヌル」引数と実際の引数を区別する方法を見つけようとしています。何か案は?

4

1 に答える 1

5

最初に質問2に答えます。はい、可変個引数マクロを使用すると、空の引数リストを検出することもできます。説明は少し長いです、私はそれをここに書きました。このアプローチを、使用しているブーストマクロと組み合わせるのは比較的簡単です。

あなたの質問1については、はい、これも可能です。Boostには、これに近いイテレータマクロがいくつかあると思いますが、使用するのは少し怖いようです。私が正しく理解していれば、ネストされたリストのようなものを使用する必要がありますが(a, (b, (c,d)))、あまり便利ではありません。

(これをより直接的に実現できる一連のマクロを作成しましたが、残念ながらパッケージはまだリリースの準備ができていません。本当に興味がある場合は、非公開で私に連絡してください。)

編集: P99パッケージはその間に公開され、マクロの「オーバーロード」とタイプジェネリックマクロに関する多くのものが含まれています。

于 2010-08-06T06:31:30.240 に答える