4

次の問題があります-可変数のマクロ引数argXを指定して、文字列化された引数#argXのリストを作成します

例:

LIST(A, B) -> "A", "B"
LIST(A, B, C) -> "A", "B", "C"

私は Boost を使用しているので、上記のマクロは、引数の数ごとにヘルパー マクロを使用して実装し、LIST(...) を適切な LIST_n(arg1, ... argn) にディスパッチするのはそれほど難しくありません。

問題は、LIST への入力自体がマクロである場合に始まります。その場合 (... と __VA_ARGS__ を使用すると)、マクロは文字列化される前に展開され、次のようになります。

#define A 10
LIST(A, B) -> "10", "B"

Windowsヘッダーで定義されたマクロでこれを機能させたいのですが、そこにある値のほとんどはマクロ(MB_OK、AF_INETなど)であるため、取得するのは文字列化された数値のリストだけです。

__VA_ARGS__ を使用しない場合、すべて正常に動作します。

#define A 10
#define LIST_1(arg0) #arg0
LIST_1(A) -> "A"

__VA_ARGS__ の展開を後で延期するいくつかのマクロを試しました (たとえば、可変引数のない LIST_1 まで) が、何も機能しませんでした。

これは、C プリプロセッサを使用して実装することも可能ですか?

4

1 に答える 1

1

申し訳ありませんが、msvc でこれを行う方法があります。プリプロセッサの古典的なバグ (ここここ__VA_ARGS__を参照) のため、単一の引数として扱います。個別の引数に分割するには、別のスキャンを適用する必要があります。これにより、マクロも展開されます。C99 プリプロセッサでは__VA_ARGS__、空のプレースホルダーを使用して展開を禁止できます。

/* This counts the number of args */
#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N
#define NARGS(...) NARGS_SEQ(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)

/* This will let macros expand before concating them */
#define PRIMITIVE_CAT(x, y) x ## y
#define CAT(x, y) PRIMITIVE_CAT(x, y)

/* p is an empty placeholder used to inhibit the expansion of __VA_ARGS__ */
#define STRINGIZE_ALL(p, ...) FIRST(NARGS(__VA_ARGS__), PRIMITIVE_STRINGIZE_ALL(p ## __VA_ARGS__,~,~,~,~,~,~,~,~))
#define PRIMITIVE_STRINGIZE_ALL(x1, x2, x3, x4, x5, x6, x7, x8, ...)  #x1, #x2, #x3, #x4, #x5, #x6, #x7, #x8

/* Retrieve the first n arguments from __VA_ARGS__ */
#define FIRST(n, ...) CAT(FIRST_, n)(__VA_ARGS__,~,~,~,~,~,~,~,~)
#define FIRST_1(x1, ...) x1
#define FIRST_2(x1, x2, ...) x1, x2
#define FIRST_3(x1, x2, x3, ...) x1, x2, x3
#define FIRST_4(x1, x2, x3, x4, ...) x1, x2, x3, x4
#define FIRST_5(x1, x2, x3, x4, x5, ...) x1, x2, x3, x4, x5
#define FIRST_6(x1, x2, x3, x4, x5, x6, ...) x1, x2, x3, x4, x5, x6
#define FIRST_7(x1, x2, x3, x4, x5, x6, x7, ...) x1, x2, x3, x4, x5, x6, x7
#define FIRST_8(x1, x2, x3, x4, x5, x6, x7, x8, ...) x1, x2, x3, x4, x5, x6, x7, x8

#define A 10
STRINGIZE_ALL(, A, B)

これは、gcc および clang 3.4 以降で最大 8 つの引数に対して機能します。

于 2014-01-03T07:35:56.893 に答える