Reputation: 16317
How would you write a variadic macro that can take either 1 or 0 arguments. I.e. something like this:
GREET() // returns @"Hello World"
GREET(@"John") // returns @"Hello John"
Upvotes: 3
Views: 1172
Reputation: 78923
I don't know if this would work for objective C, but for C99 and C11 you can use P99 that has a meta macro P99_IF_EMPTY
#define GREET(...) P99_IF_EMPTY(__VA_ARGS__)("Hello World")("Hello " __VA_ARGS__)
Upvotes: 4
Reputation: 55573
It's quite simple, you have something like this:
#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"));
}
Output:
2012-09-30 11:56:48.478 TestProj[51823:303] Hello World! 2012-09-30 11:56:48.480 TestProj[51823:303] Hello, John
Now, this is quite complex, but assuming you understand at a basic level how the preprocessor works, you should be in a good position to understand what is happening.
Upvotes: 8
Reputation: 9305
A good way to do this is to build a data structure with a repeating element, such as:
union greet_arg {
char *string;
};
struct greet_args {
union greet_arg *arg[2];
};
void greet_function(struct greet_args *x);
Your macro can then be implemented like this:
#define GREET(x...) greet_function(&(struct greet_args){0, x})
Now the reason this works is that if you call GREET("foo")
then you get:
greet_function(&(struct greet_args){0, "foo"});
whereas if you call GREET()
you get:
greet_function(&(struct greet_args){0, });
which is still valid; the "0" simply null-fills the rest of the array.
Your greet_function()
then simply check x->arg[1]
.
Upvotes: 2
Reputation: 164291
Either a macro has variadic arguments, or it has a fixed number of arguments. To get the desired result, declare 2 macros, one with 0 parameters and one with 1 parameter.
Upvotes: 1