开发者

Multi-statement Macros in C++

In C++, is it possible to make a multi-statement macro with nested if statements inside of it like the one below? I've been attempting it fo开发者_高级运维r a while now and I'm getting a scope issue for the second if statement not being able to see 'symbol'. Maybe I need to understand macros further.

#define MATCH_SYMBOL( symbol, token)
     if(something == symbol){
          if( symbol == '-'){
          }else if (symbol != '-'){
          }
     other steps;
     }


For a multi-line macro you need to add a \ character to the end of all but the last line to tell the macro processor to continue parsing the macro on the next line, like so:

#define MATCH_SYMBOL( symbol, token) \
     if(something == symbol){        \
          if( symbol == '-'){        \
          }else if (symbol != '-'){  \
          }                          \
     other steps;                    \
     }

Right now, it's trying to interpret it as a 1-line macro and then some actual code at the top of your file, which isn't what you want:

#define MATCH_SYMBOL( symbol, token)

// and then... wrongly thinking this is separate...

 if(something == symbol){ // symbol was never defined, because the macro was never used here!
      if( symbol == '-'){
      }else if (symbol != '-'){
      }
 other steps;
 }


If you're using C++ you should avoid using macros altogether. They are not type-safe, they're not namespace-aware, they're hard to debug and just they're plain messy.

If you need a type-independent function, use templates:

template <typename T>
bool match_symbol(T symbol, T token) {
    if(something == symbol){
        if( symbol == '-'){
        }else if (symbol != '-'){
        }
    ...

or if the parameters can be different types:

template <typename T, typename V>
bool match_symbol(T symbol, V token) {
    if(something == symbol){
        if( symbol == '-'){
        }else if (symbol != '-'){
        }
    ...


Note that some of the answers here have a problem.

For example, for a normal statement you can do this:

if (foo)
   function();
else
   otherstuff();

If you followed some of the suggestions here, but if replace function with a macro, it might expand to:

if (foo)
   if (something) { /* ... */ }
   else           { /* ... */ }; // <-- note evil semicolon!
else
   otherstuff();

So a common (ugly) hack that people do to avoid this is:

#define MATCH_SYMBOL(symbol, token)    \
    do                                 \
    {                                  \
       if(something == symbol)         \
       {                               \
          if( symbol == '-')           \
          {                            \
          }                            \
          else if (symbol != '-')      \
          {                            \
          }                            \
          other steps;                 \
       }                               \
    }                                  \
    while (0) // no semicolon here

This is so that the "statement" MATCH_SYMBOL(a, b) can end with a semicolon just like a normal statement. You also have braces around the multiple statements.

If you think nobody's crazy enough to use this technique, think again. It's very common in the Linux kernel, for example.


You need to have a backslash (\) at the end of all the lines in the macro but the last one.


The way of the C++:

inline void MATCH_SYMBOL(const Symbol& symbol, const Token& token) {
    /* ... */
    if (something == symbol) {

        if ('-' == symbol) {
        /* ... */
        }
        else if ('-' != symbol) {
        /* ... */
        }
    }
    /* ...other steps... */
}


also, see if you can replace the macro with a function.

?
MATCH_SYMBOL(Sym const & symbol, Tok const & token)
{
    ...
}


One can also define macro function and implement the function than

#define MATCH_SYMBOL( symbol, token) match_symbol(symbol,token)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜