2

The following code compiles fine.

#define CMD_MACRO(pp, cmd)  \
{           \
      if (pp)\
      { cmd; }        \
}

template<class T> void operate_on(T &data, char c) {
  data=data+1;
};

int main() {
  int book=4;
  char c;
    CMD_MACRO(book, {
        operate_on<int>(book, c);
    });
};

Note that the actual macro in my code is more complex, I have given a simplified version which may not make much logical sense

Now, if I add another template parameter in the function it gives compilation error (problem explained in code comment):

template<class T, bool b> void operate_on(T &data, char c) {
  data=data+1;
};
int main() {
      int book=4;
      char c;
        CMD_MACRO(book, {
            operate_on<int, false>(book, c); /* here the "," between int and 
                  false is being treated 
                  as separating arguments to CMD_MACRO, 
                  instead being part of 'cmd'. Thats strange 
                  because the comma separating book and c is 
                  treated fine as part of 'cmd'. */
        });
};


test.cpp:18:6: error: macro "CMD_MACRO" passed 3 arguments, but takes just 2
test.cpp: In function 'int main()':
test.cpp:16: error: 'CMD_MACRO' was not declared in this scope

How to fix the problem (I need to add that extra template parameter to existing code and am getting such an error).

jeetu
  • 23
  • 1
  • 3
  • 1
    A newer question has some excellent answers: http://stackoverflow.com/questions/13842468/comma-in-c-c-macro/13842784#13842784 – jjrv Jul 17 '14 at 05:36

1 Answers1

6

Have you tried: (operate_on<int, false>(book, c));? (Notice the extra parentheses around the expression).

I believe the preprocessor knows nothing of C++ templates, and so treats the < and > as just any old token. Without the extra parentheses, it treats operate_on<int as one argument, and false>(book, c) as another.

dappawit
  • 12,182
  • 2
  • 32
  • 26
  • 1
    Right. The preprocessor knows about `()` but not `[]` or `{}` or `<>`. – aschepler Mar 18 '11 at 04:33
  • Quite right, the preprocessor isn't nearly as clever as the language when it comes to parsing. I've often had to add extra parentheses to macro arguments. – Jon Reid Mar 18 '11 at 04:34
  • great.. it works.. never even knew that extra "(" around code act as "{" and is valid syntax. – jeetu Mar 18 '11 at 04:38
  • No problem, I'm glad I could help. But `(` doesn't actually act as `{`. The former works within expressions (well, in this case), while the latter wraps one or more statements. (Notice the `(` in my answer went *before* the semi-colon.) For instance, you couldn't define a function like this: ` int func() ( return 5; )`. – dappawit Mar 18 '11 at 04:42
  • oh okay.. sort of got it.. :).. but still bit confused, because I put two operate_on statements in the macro call, and wrapped each one of them inside a ( and it works... guess I am a bit rusty about definition of expression and macro arguments, but not too difficult and good learnt a new thing today :) – jeetu Mar 18 '11 at 04:49
  • I think a state of confusion is common when working with macros :)... Practice will make it somewhat clearer... emphasis on "somewhat" :) – dappawit Mar 18 '11 at 04:54
  • Note that this solution is a workaround, and in this case because adding parenthesis `()` is possible in a expression, and it is redundant at worst. However not all code can be surrounded by parenthesis, for example multiline code (more than one line of code separated by `;`) or a variable declaration. – alfC Dec 13 '12 at 05:37