MSVC не расширяет __VA_ARGS__ правильно

Рассмотрим этот код:

#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__ #define G(...) F(__VA_ARGS__) F(1, 2, 3) G(1, 2, 3) 

Ожидаемый результат: X = 1 and VA_ARGS = 2, 3 для обоих макросов, и это то, что я получаю с GCC, однако MSVC расширяет его следующим образом:

 X = 1 and VA_ARGS = 2, 3 X = 1, 2, 3 and VA_ARGS = 

То есть __VA_ARGS__ расширяется как один аргумент, а не разбивается на несколько.

Как это обойти?

Препроцессор MSVC, похоже, ведет себя совсем не так, как стандартная спецификация.
Возможно, следующее обходное решение поможет:

 #define EXPAND( x ) x #define F(x, ...) X = x and VA_ARGS = __VA_ARGS__ #define G(...) EXPAND( F(__VA_ARGS__) ) 

Я опубликовал следующую проблему с поддержкой Microsoft :

Следующая программа дает ошибку компиляции, потому что прекомпилятор неправильно расширяет __VA_ARGS__ :

 #include  #define A2(a1, a2) ((a1)+(a2)) #define A_VA(...) A2(__VA_ARGS__) int main(int argc, char *argv[]) { printf("%d\n", A_VA(1, 2)); return 0; } 

Препроцессор расширяет printf до: printf (“% d \ n”, ((1, 2) + ()));

вместо printf (“% d \ n”, ((1) + (2)));

Я получил следующий неудовлетворительный ответ от разработчика команды компилятора Microsoft:

Привет. В этом случае компилятор Visual C ++ ведет себя корректно. Если вы комбинируете правило, что токены, которые соответствуют «…» при вызове inital macro, объединяются, чтобы сформировать единый объект (16.3 / p12) с правилом, что подmacros расширяются до замены аргумента (16.3.1 / p1 ), то в этом случае компилятор считает, что A2 вызывается с одним аргументом: отсюда сообщение об ошибке.

Какую версию MSVC вы используете? Вам понадобится Visual C ++ 2010.

__VA_ARGS__ был впервые представлен C99. MSVC никогда не пытался поддерживать C99, поэтому поддержка не была добавлена.

Теперь, однако, __VA_ARGS__ включен в новый стандарт C ++, C ++ 2011 (ранее известный как C ++ 0x), который Microsoft, по-видимому, планирует поддерживать, поэтому он был поддержан в последних версиях MSVC.

BTW, вам нужно будет использовать суффикс .cpp в исходный файл, чтобы получить эту поддержку. MSVC долгое время не обновлял свой интерфейс C.

  • Нужно ли защищать доступ для чтения к контейнеру STL в многопоточной среде?
  • В C ++ / CLI, что делает символ шляпы?
  • Функция OpenSV SURF не реализована
  • постоянные переменные, не работающие в заголовке
  • Ошибка компилятора C ++ C2280 «попытка ссылки на удаленную функцию» в Visual Studio 2013 и 2015
  • В Visual Studio C ++, каковы представления распределения памяти?
  • оператор присваивания '=' атомный?
  • Нельзя передать временный объект в качестве ссылки
  • Что происходит с тем, что происходит с памятью с памятью std :: deque?
  • Ссылки DLL в Visual C ++
  • ошибка LNK2038: обнаружено несоответствие для «_MSC_VER»: значение «1600» не соответствует значению «1700» в CppFile1.obj
  • Давайте будем гением компьютера.