lmirosevic
lmirosevic

Reputation: 16317

Variadic macro that takes 0 or 1 arguments?

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

Answers (4)

Jens Gustedt
Jens Gustedt

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

Richard J. Ross III
Richard J. Ross III

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

geocar
geocar

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

driis
driis

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

Related Questions