Макропроблема С++ (интерпретация запятой,)

Следующий код компилируется нормально.

#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);
    });
};

Обратите внимание, что реальный макрос в моем коде более сложен, я дал упрощенную версию, которая может не иметь большого логического смысла

Теперь, если я добавлю еще один параметр шаблона в функцию, она выдаст ошибку компиляции (проблема объяснена в комментарии к коду):

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

Как решить проблему (мне нужно добавить этот дополнительный параметр шаблона в существующий код, и я получаю такую ​​​​ошибку).


person jeetu    schedule 18.03.2011    source источник
comment
На более новый вопрос есть отличные ответы: stackoverflow.com/ вопросы/13842468/запятая-в-копии-макрос/   -  person jjrv    schedule 17.07.2014


Ответы (1)


Вы пробовали: (operate_on<int, false>(book, c));? (Обратите внимание на дополнительные скобки вокруг выражения).

Я полагаю, что препроцессор ничего не знает о шаблонах C++ и поэтому рассматривает < и > как любой старый токен. Без дополнительных круглых скобок он обрабатывает operate_on<int как один аргумент, а false>(book, c) как другой.

person dappawit    schedule 18.03.2011
comment
Правильно. Препроцессор знает о (), но не знает [], {} или <>. - person aschepler; 18.03.2011
comment
Совершенно верно, препроцессор далеко не так умен, как язык, когда дело доходит до синтаксического анализа. Мне часто приходилось добавлять дополнительные скобки к аргументам макроса. - person Jon Reid; 18.03.2011
comment
отлично .. это работает .. даже не знал, что лишнее (вокруг кода действует как { и является допустимым синтаксисом. - person jeetu; 18.03.2011
comment
Нет проблем, я рад, что смог помочь. Но ( на самом деле не действует как {. Первый работает внутри выражений (ну, в данном случае), а второй оборачивает один или несколько операторов. (Обратите внимание, что ( в моем ответе стоит перед точкой с запятой.) Например, вы не можете определить такую ​​функцию: ` int func() ( return 5; )`. - person dappawit; 18.03.2011
comment
о, ладно.. вроде понял.. :).. но все еще немного запутался, потому что я поместил два оператора opera_on в вызов макроса и обернул каждый из них внутри a ( и это работает... думаю, я немного заржавел об определении выражения и аргументах макроса, но не слишком сложно и хорошо сегодня узнал что-то новое :) - person jeetu; 18.03.2011
comment
Я думаю, что при работе с макросами часто возникает путаница :)... Практика сделает это несколько яснее... акцент на чем-то :) - person dappawit; 18.03.2011
comment
Обратите внимание, что это решение является обходным путем, и в данном случае потому, что добавление скобки () в выражение возможно, и в худшем случае это избыточно. Однако не весь код может быть заключен в круглые скобки, например многострочный код (более одной строки кода, разделенных ;) или объявление переменной. - person alfC; 13.12.2012