У меня возникли проблемы с расширением макроса записи ACE. Это элементарная проблема, но я не могу обернуться вокруг нее.
Я пытаюсь сформулировать свой собственный макрос записи ACE со списком переменных аргументов. Мой компилятор (gcc версии 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)) поддерживает __VA_ARGS__
стандарт. Мое текущее определение таково:
#define ERROR_PREFIX ACE_TEXT("ERROR (%T)%?%I")
#define ERROR(FMT,...) ACE_DEBUG((LM_ERROR, ACE_TEXT(FMT) __VA_ARGS__))
Который я хотел бы вызвать через эту последовательность вызова:
ERROR( "This is an example error in file %s\n", errorString.c_str() )
Но я получаю следующую ошибку компиляции:
error: expected ‘)’ before ‘errorString’
Как лучше всего изменить определение макроса для борьбы с этой проблемой?
Я не знаком с ACE, но это появляется что вы ищете расширение для удаления запятой:
#define ERROR(FMT, ...) ACE_DEBUG((LM_ERROR, ACE_TEXT(FMT), ##__VA_ARGS__))
Как описано в раздел Variadic Macros в руководстве по GNU CPP, сдачи ##
между запятой и __VA_ARGS__
имеет особый эффект удаления запятой тогда и только тогда, когда макрос был вызван с нулевыми переменными аргументами. Таким образом,
ERROR("This is an example error");
ERROR("This is an example error %s", string);
соответственно расширится до
ACE_DEBUG((LM_ERROR, ACE_TEXT("This is an example error")));
ACE_DEBUG((LM_ERROR, ACE_TEXT("This is an example error %s"), string));
который наверное что вы хотите (опять же, я не знаю, ACE). Интервал между последовательностью из трех токенов и вокруг нее , ## __VA_ARGS__
не имеет значения, если вы не заботитесь о переносимости очень старый GCC, как в пре-EGCS.
Эта функция является расширением GNU, также поддерживаемым clang и всем, что использует внешний интерфейс EDG с включенным режимом совместимости GNU. Важно, что это не поддерживается компиляторами Microsoft, насколько я знаю.
(Так как это почти Рождество, я должен также упомянуть, что вставка пробелов внутри ваших скобок заставляет младенца Иисуса плакать.)
Других решений пока нет …