12

私の推測では、この質問への答えはノーですが、方法があれば素晴らしいでしょう。明確にするために、私が次のマクロを持っていると仮定します。

#define MY_VARIADIC_MACRO(X...) // Does some stuff here in the macro definition

私がやりたいのは、可変個引数関数に渡す前に、Xのすべての変数に対して何らかの方法で文字列化を実行することです。ここでのキーワードは前です。マクロ定義内から個々の引数に実際にアクセスする方法はないことに気付きましたが、次のようなものを使用して、すべての引数を文字列化する方法はありますか?

#define MY_VARIADIC_MACRO(X...) some_variadic_function("some string", #X)
4

3 に答える 3

21

さまざまな再帰マクロ手法を使用して、可変個引数マクロで処理を実行できます。たとえばNUM_ARGS、可変個引数マクロへの引数の数をカウントするマクロを定義できます。

#define _NUM_ARGS(X100, X99, X98, X97, X96, X95, X94, X93, X92, X91, X90, X89, X88, X87, X86, X85, X84, X83, X82, X81, X80, X79, X78, X77, X76, X75, X74, X73, X72, X71, X70, X69, X68, X67, X66, X65, X64, X63, X62, X61, X60, X59, X58, X57, X56, X55, X54, X53, X52, X51, X50, X49, X48, X47, X46, X45, X44, X43, X42, X41, X40, X39, X38, X37, X36, X35, X34, X33, X32, X31, X30, X29, X28, X27, X26, X25, X24, X23, X22, X21, X20, X19, X18, X17, X16, X15, X14, X13, X12, X11, X10, X9, X8, X7, X6, X5, X4, X3, X2, X1, N, ...)   N

#define NUM_ARGS(...) _NUM_ARGS(__VA_ARGS__, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)

次にFOREACH、リストの要素ごとに別のマクロを展開するマクロを作成できます。

#define EXPAND(X)       X
#define FIRSTARG(X, ...)    (X)
#define RESTARGS(X, ...)    (__VA_ARGS__)
#define FOREACH(MACRO, LIST)    FOREACH_(NUM_ARGS LIST, MACRO, LIST)
#define FOREACH_(N, M, LIST)    FOREACH__(N, M, LIST)
#define FOREACH__(N, M, LIST)   FOREACH_##N(M, LIST)
#define FOREACH_1(M, LIST)  M LIST
#define FOREACH_2(M, LIST)  EXPAND(M FIRSTARG LIST) FOREACH_1(M, RESTARGS LIST)
#define FOREACH_3(M, LIST)  EXPAND(M FIRSTARG LIST) FOREACH_2(M, RESTARGS LIST)
        :

これにより、各引数を文字列化するマクロを定義できるようになります。

#define STRINGIFY(X)    #X
#define MY_VARIADIC_MACRO(...)    FOREACH(STRINGIFY, (__VA_ARGS__))
于 2011-05-11T01:39:12.887 に答える
11

さて、ここで自分の質問に答えるつもりはありませんでしたが、マーク・ウィルキンスの答えと質問で示した例を組み合わせた、まともな解決策を思いつきました。

セットの可変個引数セット全体を文字列化することができます。これにより、文字列に区切りコンマが含まれます。簡単な例を次に示します。

#define MY_VARIADIC_MACRO(X...) printf(#X)

上記のマクロを使用すると、マクロに渡される引数のセット全体が文字列化されることがわかります。

次に、区切りコンマを使用してこれらの引数をトークン化する関数を定義し、可変個引数マクロを使用してトークン化された文字列のセットを取得できます。

#define MY_VARIADIC_MACRO(X...) tokenize_my_arguments(#X)

そうすれば、実際には、可変個引数マクロに可変個引数関数を呼び出させるという依存関係はなくなり、va_argを反復処理するのではなく、定数C文字列の配列を適切に反復処理できます。

*編集からの新しいものが続きます*

ティムのコメントによると、ソリューションの詳細は次のとおりです。急いで行われ、作業中のものから移植する必要があったため、エラーはご容赦ください。また、POCを示すために引数の文字列化を出力するだけなので、コピー/貼り付けソリューションを意味するものではありませんが、機能を示すには十分である必要があります。

このソリューションには実行時の計算が必要ですが、可変個引数マクロは可変個引数関数を呼び出すことが多く、va_argsを反復処理する必要があるため、パフォーマンスは多少犠牲になりますが、トークンの検索で反復処理が行われます。ただし、保守性、汎用性、および実装の容易さのために、これは現時点で最良のオプションのようです。

#define VARIADIC_STRINGIFY(_ARGUMENTS_TO_STRINGIFY...) Variadic_Stringification_Without_Variadic_Function(#_ARGUMENTS_TO_STRINGIFY)

void Variadic_Stringification_Without_Variadic_Function (const char* _stringified_arguments)
{
    strcpy(converted_arguments, _stringified_arguments);

    for(char* token = strtok(converted_arguments, ","); token != 0x0; token = strtok(0x0, ","))
        std::cout << token << std::endl;
}
于 2011-05-11T00:02:18.707 に答える
3

これはおそらくあなたが望んでいるものにあまり近くありませんが、次のようなものがあなたをそこに導くかもしれません:

#define MY_VARIADIC_MACRO(X) printf( "%s\n", #X )

次に、次のように使用します。マクロに対して1つのパラメーターとして表示されるように、パラメーターを括弧で囲みます。

MY_VARIADIC_MACRO((var1、var2、 "string"));

次に、マクロに、外側の親を削除するか、場合によっては指定された文字列を解析する関数を呼び出すことができます。

于 2011-05-10T23:48:04.127 に答える