次のようなつもりじゃない:
#define COMMA ,
#if defined(DOXYGEN_PROCESSING)
# define DOCUMENTED_TYPEDEF(x, y) class y : public x {};
#else
# define DOCUMENTED_TYPEDEF(x, y) typedef x y;
#endif
DOCUMENTED_TYPEDEF(Foo<R COMMA S>,Bar)
テスト:任意の置換が行われる前に
$ gcc -E comma-macro.c
# 1 "comma-macro.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "comma-macro.c"
# 9 "comma-macro.c"
typedef Foo<R , S> Bar;
マクロ引数リストは括弧とカンマのために解析されます。 x
引数でCOMMA
が置換され、マクロ本体にx
が代入されます。その時、議論が破られました。 COMMA
がカンマ区切り記号トークンに置き換えられていることは関係ありません。しかし、そのコンマは、そのマクロによって生成されたマクロ呼び出しで発生する別々の引数なので、それらを保護する必要がある場合は、もっと狂ったことが必要です。
あなたは関数のようなマクロの後ろCOMMA
を隠すことができ、PAIR
を言う:一見
#define COMMA ,
#define PAIR(A, B) A COMMA B
#if defined(DOXYGEN_PROCESSING)
# define DOCUMENTED_TYPEDEF(x, y) class y : public x {};
#else
# define DOCUMENTED_TYPEDEF(x, y) typedef x y;
#endif
DOCUMENTED_TYPEDEF(PAIR(Foo<R, S>), Bar)
それがより魅力的ですが、欠点は、おそらくあります。それはもっと難解です。読者は、PAIR
の後ろにセマンティクスがあるのだろうか? COMMA
はあまりにも曖昧すぎてセマンティクスを持っていませんが、その目的は戦闘傷跡がプリプロセッサと戦っている人にはすぐに明らかです。
についてPAIR
については、私たちはそれを隠すことができ、Zwolの答えのような構文で終わることがあります。しかし、我々はDOCUMENTED_TYPEDEF
の複数の変種が必要です。
また、ところで、のは、マクロの右側に必要とされていない無用COMMA
を落としてみましょう:それはC99スタイル可変引数マクロでなんとかかもしれよう
#define PAIR(A, B) A, B
#if defined(DOXYGEN_PROCESSING)
# define DOCUMENTED_TYPEDEF_2(x2, y) class y : public PAIR x2 {};
#else
# define DOCUMENTED_TYPEDEF_2(x2, y) typedef PAIR x2 y;
#endif
DOCUMENTED_TYPEDEF_2((<R, S>), Bar)
$ gcc -std=c90 -E -Wall -pedantic comma-macro.c
# 1 "comma-macro.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "comma-macro.c"
# 11 "comma-macro.c"
typedef <R, S> Bar;
これが見えます。しかし、これはC++であることは言うまでもなく、コメントで説明されている移植性の要件に違反する可能性があります。将来の訪問者のために:
#define PNEUMATIC_COMMA_GUN(A, ...) A, ## __VA_ARGS__
#if defined(DOXYGEN_PROCESSING)
# define DOCUMENTED_TYPEDEF(xv, y) class y : public PNEUMATIC_COMMA_GUN xv {};
#else
# define DOCUMENTED_TYPEDEF(xv, y) typedef PNEUMATIC_COMMA_GUN xv y;
#endif
DOCUMENTED_TYPEDEF((<R, S, T, L, N, E>), Bar)
$ gcc -std=c99 -E -Wall -pedantic comma-macro.c
# 1 "comma-macro.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "comma-macro.c"
# 9 "comma-macro.c"
typedef <R, S, T, L, N, E> Bar;
私は左の引数Xは、宣言指定の位置に置かれているので、それは、問題が発生します疑います。 CおよびC++スタイル宣言では、宣言指定子はオプションのかっこを使用しません。しかしながら、宣言子は: 'int x;'と 'int(x);'は同じことです。 '(int)x;'はキャスト式のように見えます。 – Kaz
@ Kaz C99可変マクロを実装するコンパイラのみをサポートするテンプレートパラメータ、*と*を含むかもしれない引数の周りに*常に*カッコを入れることができますか?もしそうなら、機能するハックがあります。 – zwol