Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading a macro

I'm trying to overload a macro by the number of parameter.
Of course I can't actually overload the macro.

I've tried using variadic macros to choose the right macro (using the fact that if __VA_ARGS__ doesn't exist it's supposed to delete the last coma before it - GCC Reference):

#define TEST1() printf("TEST1");
#define TEST2() printf("TEST2");

#define CHOOSER(x, y,FUNC,...) FUNC()

#define MANIMACRO(...) CHOOSER(,__VA_ARGS__,TEST1,TEST2)

int main(void)
{
    MANIMACRO(1);
    MANIMACRO();
}

The idea was that if __VA_ARGS__ exists it should pass 4 arguments to CHOOSER, where the third one should have been "disappeared" with the unused args. so TEST1 would be chosen.

If there is no parameter the __VA_ARGS__ would be null, and should have removed the coma, so TEST2 would be chosen and used.

So, i guess that doesn't work because the __VA_ARGS__ probably gets removed only at the end of the preprocessing stage, after the whole thing was already expanded.

So, how can I do such a thing? (in vs2010)

like image 391
Yochai Timmer Avatar asked Apr 14 '26 03:04

Yochai Timmer


2 Answers

Based on this answer:

#define TEST1(expr)           printf("test1")
#define TEST2(expr, explain)  printf("test2")

#define N_ARGS_IMPL2(_1, _2, count, ...) \
   count
#define N_ARGS_IMPL(args) \
   N_ARGS_IMPL2 args
#define N_ARGS(...) N_ARGS_IMPL((__VA_ARGS__, 2, 1, 0))
 /* Pick the right helper macro to invoke. */
#define CHOOSER2(count) TEST##count
#define CHOOSER1(count) CHOOSER2(count)
#define CHOOSER(count)  CHOOSER1(count)
 /* The actual macro. */
#define TEST_GLUE(x, y) x y
#define TEST(...) \
   TEST_GLUE(CHOOSER(N_ARGS(__VA_ARGS__)), \
               (__VA_ARGS__))

int main() {
  TEST(one); // singleArgumentExpansion(one)
  TEST(two, "foopy"); // twoArgumentExpansion(two, "foopy")
  return 0;
}
like image 159
perreal Avatar answered Apr 15 '26 17:04

perreal


First, the page you link explains it is a GCC extension. If you are using visual studio 2010 as your tag implies, I'm not surprised it doesn't work.

Then you aren't using it correctly: you need ## between the coma and __VA_ARGS__. If I do this and fix the typo which makes both TESTx macros print TEST1, I get the behaviour you expect with gcc 4.4

#include <stdio.h>

#define TEST1() printf("TEST1\n");
#define TEST2() printf("TEST2\n");

#define CHOOSER(x, y, FUNC,...) FUNC()

#define MANIMACRO(...) CHOOSER(,##__VA_ARGS__,TEST1,TEST2)

int main(void)
{
    MANIMACRO(1);
    MANIMACRO();
}
like image 28
AProgrammer Avatar answered Apr 15 '26 15:04

AProgrammer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!