可能であれば可変的な関数や関数テンプレートを使うべきだと私は全面的に同意しますが、マクロでできることとできないことについて何か誤解を示しているので、この答えでは関数オプションではありません。
FOO(a, ...);
の定義を変更し、存在する場合、残りの中に、b
に(...の略)__VA_ARGS__
変数を分割して。
はい。
だから、関数呼び出しは次のようになります。FOO(5, "4gamma");
とFOO(5, "4");
号はFOO(5, 4, "gamma");
とFOO(5, 4);
として呼び出しを続行します。最初のケースでは、__VA_ARGS__
は4, "gamma"
です。 2番目のケースでは、__VA_ARGS__
は4
です。
前者から, "gamma"
を抽出する必要がある場合は、プリプロセッサで行うことができます。パラメータの量には上限が必要ですが、これを任意の数に増やすことができます。しかし、それは醜いです。
__VA_ARGS__
は何のカンマが含まれていない場合、抽出が簡単です:
#define COMMA_TRAILING_ARGS_0(a)
あなたは__VA_ARGS__
は、少なくとも一つのカンマが入っていることがわかっている場合は、あなたが
#define COMMA_TRAILING_ARGS_1(a, ...) , __VA_ARGS__
を使用することができますそして、あなたはこれらのどれに検出することができますマクロ引数の特定の上限まで:
#define ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) _16
#define HAS_COMMA(...) ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,)
組み合わせ:
#define COMMA_TRAILING_ARGS_0(a)
#define COMMA_TRAILING_ARGS_1(a, ...) , __VA_ARGS__
#define ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) _16
#define HAS_COMMA(...) ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,)
#define CONCAT(a, b) a ## b
#define CONCAT_(a, b) CONCAT(a, b)
#define FOO(a, ...) BAR(a CONCAT_(COMMA_TRAILING_ARGS_, HAS_COMMA(__VA_ARGS__)) (__VA_ARGS__))
FOO(5, 4, x, q); // expands to BAR(5, x, q);
FOO(5, 4, "gamma"); // expands to BAR(5, "gamma");
FOO(5, 4); // expands to BAR(5);
なぜマクロを使用していますか?あなたが解決しようとしている実際の問題は何ですか? –
バリデーショナル関数テンプレートがあなたのソリューションです。 – DeiDei
@DeiDei関数テンプレートを詳しく教えていただけますか? – FigsHigs