views:

77

answers:

3
+3  Q: 

Token pasting in C

Hi all, After reading about VA_NARG

I tried to implement function overloading depending on number of arguments in C using macros. Now the problem is:

void hello1(char *s) { ... }
void hello2(char *s, char *t) { ... }
// PP_NARG(...)           macro returns number of arguments :ref to link above
 // does not work
#define hello(...)         hello ## PP_NARG(__VA_ARGS__)  

int main(void)
{
   hello("hi");   // call hello1("hi");
   hello("foo","bar"); // call hello2("foo","bar");
   return 0;
}

I've read this from c-faq. But still could not get it to work...

A: 

I don't have a C99 compiler available to check, but this should work:

#define helloN(N, ...) hello ## N (__VA_ARGS__)
#define hello(...) helloN(PP_NARG(__VA_ARGS__), __VA_ARGS__)
Bart van Ingen Schenau
+2  A: 

This is because of the evaluation rules for macros. You would have to define some sort of helper macro that receives the number as a token:

#define HELLO_1(N, ...)         hello ## N
#define HELLO_0(N, ...)         HELLO_1(N, __VARGS__)
#define HELLO(...)         HELLO_0(PP_NARG(__VA_ARGS__), __VARGS__)  

or so. You could also have a glance into the prerelease of the documentation of P99. This will provide you more comfortable macro tools to do that directly.

Jens Gustedt
"or so" indeed. It needs one more level of indirection to make it work.
John Marshall
@John: yeah, thanks. I always use my own version of a paste macro for that, so I have a hard time to remember how much levels of indirection you need if you just have `##`. I adapted my answer accordingly.
Jens Gustedt
Thanks that works. but HELLO("foo") give hello1; not hello1("foo"). But i get the idea...
Nyan
@bstpierre: thanks for the edit
Jens Gustedt
+4  A: 

That PP_NARG is a rather impressive piece of craziness!

Following the glue example in the C99 standard (6.10.3.5, example 4), the following produces the desired results:

#define glue(a, b)   a ## b
#define xglue(a, b)  glue(a, b)

#define hello(...)   xglue(hello, PP_NARG(__VA_ARGS__))(__VA_ARGS__)
John Marshall