3

I'd like to do something like this:

#define NUM_ARGS() 2
#define MYMACRO0(...) "no args"
#define MYMACRO1(...) "one arg"
#define MYMACRO2(...) "two args"
#define MYMACRO(num,...) MYMACRO##num(__VA_ARGS__)
#define GENERATE(...) MYMACRO(NUM_ARGS(),__VA_ARGS__)

And I expected it to evaluate to "two args". But instead I have

MYMACRONUM_ARGS()(1,1)

Is there a way to do what I want (using visual c++) ?

P.S. Eventually I want to implement logger that dumps all of variables. The next code

int myInt = 7;
string myStr("Hello Galaxy!");
DUMP_VARS(myInt, myStr);

will produce log record "myInt = 7; myStr = Hello Galaxy!"

AstroCB
  • 12,337
  • 20
  • 57
  • 73
sergeyz
  • 1,308
  • 2
  • 14
  • 23
  • Check out this answer: http://stackoverflow.com/questions/2124339/c-preprocessor-va-args-number-of-arguments/2124433#2124433 – qrdl Dec 20 '12 at 11:08
  • Are you doing this as a thought experiment? You say you are compiling with Visual C++. Macros are evil and very, very hard to debug and trace (especially when you start writing stuff like this). Why not use templates instead. I work on a product that has a bunch of these and it is painful when I am trying to trace back into what function is actually being called. – pstrjds Dec 20 '12 at 11:08
  • @pstrjds Chainsaw is evil because you can hurt yourself with it, you are absolutely right. And there are no templates in C. – qrdl Dec 20 '12 at 11:10
  • @qrdl - I know that there are no templates in C. I was merely asking if OP had to do this. If they are compiling with Visual C++, maybe they actually have c++ code and could use templates instead which are much cleaner. I am not saying "don't", I am saying "don't if you don't absolutely have to". In the product I work on, someone made a mistake with the value they passed to a MACRO. There was no type checking because it was a MACRO and a bug was released to the field that took days to track down (subtle difference between calling foo(&val) and foo(val) that visually is hard to spot). – pstrjds Dec 20 '12 at 11:18
  • @pstrjds I understand you position, but the mere fact that somebody used macro incorrectly doesn't make macros evil. Preprocessor is a power tool so one needs to use it with caution, that's it – qrdl Dec 20 '12 at 11:50
  • 1
    @qrdl - I suppose it is more a religious debate. I am a big fan of strong typing, which you don't get with macros. That being said, if you are stuck in C, then you don't have templates and other nice things so you use the tools you have. – pstrjds Dec 20 '12 at 11:53

1 Answers1

6

You need another macro because macro expansion does not take place near # or ##:

#define NUM_ARGS() 2
#define MYMACRO0(...) "no args"
#define MYMACRO1(...) "one arg"
#define MYMACRO2(...) "two args"
#define MYMACRO_AUX(num,...) MYMACRO##num(__VA_ARGS__)
#define MYMACRO(num,...) MYMACRO_AUX(num, __VA_ARGS__)
#define GENERATE(...) MYMACRO(NUM_ARGS(),__VA_ARGS__)

#include <stdio.h>

int main(void)
{
    puts(GENERATE(0, 1));

    return 0;
}

If this is what you're trying to do, but complicated preprocessor tricks are not really safe, as others already said, don't do it unless you really have to.

effeffe
  • 2,821
  • 3
  • 21
  • 44