1つまたは0つの引数を取ることができる可変個引数マクロをどのように記述しますか。つまり、次のようなものです。
GREET() // returns @"Hello World"
GREET(@"John") // returns @"Hello John"
1つまたは0つの引数を取ることができる可変個引数マクロをどのように記述しますか。つまり、次のようなものです。
GREET() // returns @"Hello World"
GREET(@"John") // returns @"Hello John"
それは非常に簡単です、あなたはこのようなものを持っています:
#define __NARGS(unused, _1, _2, _3, _4, _5, VAL, ...) VAL
#define NARGS(...) __NARGS(unused, ## __VA_ARGS__, 5, 4, 3, 2, 1, 0)
#define __GREET(ARGC, ARGS...) GREET_ ## ARGC (ARGS)
#define _GREET(ARGC, ARGS...) __GREET(ARGC, ARGS)
#define GREET(...) _GREET(NARGS(__VA_ARGS__), __VA_ARGS__)
#define GREET_0(...) @"Hello World!"
#define GREET_1(ARG, ...) @"Hello, " ARG // strings are auto-concatenated in objc
int main()
{
NSLog(@"%@", GREET());
NSLog(@"%@", GREET(@"John"));
}
出力:
2012-09-30 11:56:48.478 TestProj [51823:303] Hello World! 2012-09-30 11:56:48.480 TestProj [51823:303]こんにちは、ジョン
さて、これは非常に複雑ですが、プリプロセッサがどのように機能するかを基本的なレベルで理解していると仮定すると、何が起こっているのかを理解するのに適した立場にいるはずです。
これがObjective Cで機能するかどうかはわかりませんが、C99およびC11では、メタマクロを持つP99を使用できますP99_IF_EMPTY
#define GREET(...) P99_IF_EMPTY(__VA_ARGS__)("Hello World")("Hello " __VA_ARGS__)
これを行う良い方法は、次のような繰り返し要素を持つデータ構造を構築することです。
union greet_arg {
char *string;
};
struct greet_args {
union greet_arg *arg[2];
};
void greet_function(struct greet_args *x);
マクロは次のように実装できます。
#define GREET(x...) greet_function(&(struct greet_args){0, x})
これが機能する理由は、電話をかけると次のGREET("foo")
ようになるためです。
greet_function(&(struct greet_args){0, "foo"});
一方、電話をかけるとGREET()
次のようになります。
greet_function(&(struct greet_args){0, });
これはまだ有効です。「0」は、配列の残りの部分を単にnullで埋めます。
次にgreet_function()
、単にチェックしx->arg[1]
ます。
マクロに可変引数があるか、固定数の引数があるかのいずれかです。目的の結果を得るには、2 つのマクロを宣言します。1 つはパラメーターが 0 で、もう 1 つはパラメーターが 1 です。