最近同様の問題に遭遇しましたが、解決策はあると思います。
重要なアイデアはNUM_ARGS
、可変個のマクロが与えられる引数の数を数えるマクロを書く方法があるということです。あなたはのバリエーションを使用することができますNUM_ARGS
ビルドにNUM_ARGS_CEILING2
可変引数マクロは1つの引数または2 -または-複数の引数を与えているかどうかを伝えることができ、。次に、Bar
マクロを記述して、その引数を使用NUM_ARGS_CEILING2
しCONCAT
て2つのヘルパーマクロの1つに送信することができます。
UNIMPLEMENTED
これは、このトリックを使用してマクロを記述する例です。これは、に非常に似ていBAR
ます。
ステップ1:
/**
* A variadic macro which counts the number of arguments which it is
* passed. Or, more precisely, it counts the number of commas which it is
* passed, plus one.
*
* Danger: It can't count higher than 20. If it's given 0 arguments, then it
* will evaluate to 1, rather than to 0.
*/
#define NUM_ARGS(...) \
NUM_ARGS_COUNTER(__VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, \
12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define NUM_ARGS_COUNTER(a1, a2, a3, a4, a5, a6, a7, \
a8, a9, a10, a11, a12, a13, \
a14, a15, a16, a17, a18, a19, a20, \
N, ...) \
N
ステップ1.5:
/*
* A variant of NUM_ARGS that evaluates to 1 if given 1 or 0 args, or
* evaluates to 2 if given more than 1 arg. Behavior is nasty and undefined if
* it's given more than 20 args.
*/
#define NUM_ARGS_CEIL2(...) \
NUM_ARGS_COUNTER(__VA_ARGS__, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, \
2, 2, 2, 2, 2, 2, 2, 1)
ステップ2:
#define _UNIMPLEMENTED1(msg) \
log("My creator has forsaken me. %s:%s:%d." msg, __FILE__, \
__func__, __LINE__)
#define _UNIMPLEMENTED2(msg, ...) \
log("My creator has forsaken me. %s:%s:%d." msg, __FILE__, \
__func__, __LINE__, __VA_ARGS__)
ステップ3:
#define UNIMPLEMENTED(...) \
CONCAT(_UNIMPLEMENTED, NUM_ARGS_CEIL2(__VA_ARGS__))(__VA_ARGS__)
CONCATが通常の方法で実装されている場合。簡単なヒントとして、上記が混乱していると思われる場合:CONCATの目的は、別のマクロ「呼び出し」に拡張することです。
NUM_ARGS自体は使用されないことに注意してください。ここでは、基本的なトリックを説明するために含めました。Jens GustedtのP99ブログを参照してください。
2つのメモ:
NUM_ARGSは、処理する引数の数に制限があります。鉱山は20までしか処理できませんが、その数は完全に任意です。
NUM_ARGSは、示されているように、引数が0の場合に1を返すという落とし穴があります。その要点は、NUM_ARGSが技術的に[カンマ+ 1]を数えているのであって、引数を数えていないことです。この特定のケースでは、それは実際に私たちに有利に働きます。_UNIMPLEMENTED1は空のトークンを問題なく処理し、_UNIMPLEMENTED0を記述する必要をなくします。Gustedtにもそれに対する回避策がありますが、私はそれを使用していません。
BAR
代わりに使うのFOO
ですか?