Как исправить проблемы, связанные с переменными макросами при перегрузке макросов в MSVC ++ (Microsoft Visual Studio)?

Вдохновленный такого рода решения, я написал ниже код, который имитирует «перегрузку макросов» .

#include<iostream>

#define CONCATE_(X,Y) X##Y
#define CONCATE(X,Y) CONCATE_(X,Y)
#define UNIQUE(NAME) CONCATE(NAME, __LINE__)

#define NUM_ARGS_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, TOTAL, ...) TOTAL
#define NUM_ARGS(...) NUM_ARGS_(__VA_ARGS__, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define VA_MACRO(MACRO, ...) CONCATE(MACRO, NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)

#define COUT(...) VA_MACRO(_COUT, __VA_ARGS__)
#define _COUT1(X) std::cout << "1 argument\n"
#define _COUT2(X, Y) std::cout << "2 arguments\n"
#define _COUT3(X, Y, Z) std::cout << "3 arguments\n"

int main ()
{
  COUT("A");
  COUT("A", 1);
  COUT("A", 1, 'a');
  return 0;
}

Это отлично работает в компиляторах g ++ / clang ++, что дает следующий результат:

1 argument
2 arguments
3 arguments

Однако он не дает ожидаемого результата для последней версии MSVC (2017) из-за известной ошибки компилятора, связанной с __VA_ARGS__:

1 argument
1 argument
1 argument

Я пробовал различные комбинации «косвенных расширений» на основе сообщения ниже, но безуспешно:
Visual studio __VA_ARGS__ issue

Как исправить эту проблему в MSVC?


person iammilind    schedule 09.02.2018    source источник
comment
Решение: Не используйте макросы.!   -  person Jesper Juhl    schedule 09.02.2018
comment
@Jesper, приведенный выше код предназначен только для демонстрационных целей. Реальный код более сложен, и макросы используются по-другому, где они незаменимы. В любом случае рассмотрите этот Qn из любопытства или в учебных целях.   -  person iammilind    schedule 09.02.2018


Ответы (1)


Я не очень разбираюсь в ошибке MSVC, кроме того, что знаю, что она существует, но я смог применить обходной путь в другом ответе следующим образом:

#define MSVC_BUG(MACRO, ARGS) MACRO ARGS  // name to remind that bug fix is due to MSVC :-)

#define NUM_ARGS_2(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, TOTAL, ...) TOTAL
#define NUM_ARGS_1(...) MSVC_BUG(NUM_ARGS_2, (__VA_ARGS__))
#define NUM_ARGS(...) NUM_ARGS_1(__VA_ARGS__, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define VA_MACRO(MACRO, ...) MSVC_BUG(CONCATE, (MACRO, NUM_ARGS(__VA_ARGS__)))(__VA_ARGS__)

Это также дает соответствующий вывод препроцессора в последних версиях GCC и Clang. Я не удивлюсь, если узнаю, что есть способ обойти это, не вызывая дважды макрос MSVC_BUG для «косвенного расширения», но я его не нашел.

person chris    schedule 09.02.2018