Макросы с несколькими утверждениями в C ++ - PullRequest
3 голосов
/ 02 декабря 2009

В C ++ возможно ли сделать макрос с несколькими операторами с вложенным , если внутри него есть операторы , как показано ниже? Я уже некоторое время пытаюсь это сделать, и у меня возникает проблема с областью действия, если второе утверждение if не может увидеть ' symbol '. Может быть, мне нужно понять макросы дальше.

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

Ответы [ 7 ]

11 голосов
/ 02 декабря 2009

Для многострочного макроса необходимо добавить символ \ в конец всех строк, кроме последней, чтобы сообщить макропроцессору о продолжении анализа макроса на следующей строке, например:

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

Сейчас он пытается интерпретировать его как макрос, состоящий из одной строки, а затем какой-то реальный код в верхней части файла, а это не то, что вам нужно:

#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;
 }
8 голосов
/ 02 декабря 2009

Если вы используете C ++, вам следует вообще избегать использования макросов. Они не безопасны по типу, они не учитывают пространство имен, их сложно отлаживать, и они просто беспорядочные.

Если вам нужна независимая от типа функция, используйте шаблоны:

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

или если параметры могут быть разных типов:

template <typename T, typename V>
bool match_symbol(T symbol, V token) {
    if(something == symbol){
        if( symbol == '-'){
        }else if (symbol != '-'){
        }
    ...
4 голосов
/ 02 декабря 2009

Обратите внимание, что у некоторых из ответов здесь есть проблема.

Например, для нормального утверждения вы можете сделать это:

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

Если вы следовали здесь некоторым советам, но если заменить function макросом, он может расшириться до:

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

Итак, обычный (безобразный) взлом, который люди делают, чтобы избежать этого:

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

Это так, что «оператор» MATCH_SYMBOL(a, b) может заканчиваться точкой с запятой, как обычный оператор. У вас также есть скобки вокруг нескольких операторов.

Если вы думаете, что никто не сошел с ума, чтобы использовать эту технику, подумайте еще раз. Например, это очень распространено в ядре Linux.

1 голос
/ 02 декабря 2009

Путь С ++:

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

        if ('-' == symbol) {
        /* ... */
        }
        else if ('-' != symbol) {
        /* ... */
        }
    }
    /* ...other steps... */
}
1 голос
/ 02 декабря 2009

Вы должны иметь обратную косую черту (\) в конце всех строк в макросе, кроме последней.

0 голосов
/ 02 декабря 2009

Можно также определить макрофункцию и реализовать функцию, чем

#define MATCH_SYMBOL( symbol, token) match_symbol(symbol,token)
0 голосов
/ 02 декабря 2009

также, посмотрите, можете ли вы заменить макрос на функцию.

?
MATCH_SYMBOL(Sym const & symbol, Tok const & token)
{
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...