Подтвердить что ты не робот

Почему этот макрокоманда с переменным аргументом терпит неудачу с VС++?

Я получил следующую реализацию, чтобы получить количество аргументов в переменном макросе (в настоящее время ограничено 16 аргументами). Однако для VS2010 вывод всегда 1, независимо от того, сколько аргументов передано. С GCC, вывод верен, и я пришел к выводу, что я, должно быть, пропустил что-то конкретное для MSVC (10).

#define PP_NARGS(...) \
    _xPP_NARGS_IMPL(__VA_ARGS__,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)

#define _xPP_NARGS_IMPL(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,N,...) N

int main(){
    int i = PP_NARGS(A,V,C,X,Y,Z);

    std::cout << i;

    std::cin.get();
    return 0;
}

Итак, вопрос заключается в том, что состояние заголовка, любая помощь будет оценена.

4b9b3361

Ответ 1

Помогает ли следующая помощь?

#define EXPAND(x) x
#define PP_NARGS(...) \
    EXPAND(_xPP_NARGS_IMPL(__VA_ARGS__,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))

Я думаю, что ваш макрос не ошибается, в частности, но Похоже, что расширение MSVC __VA_ARGS__ ведет себя иначе, чем C99.

Ответ 2

Проблема заключается в том, что Visual Studio расширяет __VA_ARGS__ после передачи ее в последующий макрос, а gcc расширяет ее до передачи.

В вашем случае PP_NARGS(A,V,C,X,Y,Z) связывает A,V,C,X,Y,Z с __VA_ARGS__, а затем передает его как целое на _xPP_NARGS_IMPL.

В качестве теста запустите:

#define PP_NARGS(...) \
    _xPP_NARGS_IMPL(__VA_ARGS__,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)

#define _xPP_NARGS_IMPL(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,N,...) \
  (std::cout << #x1 << std::endl, N) 

int main() {
  int i = PP_NARGS(A, V, C, X, Y, Z);
  std::cout << i;
  return 0;
}

Вы увидите A, V, C, X, Y, Z, напечатанный на экране, а не только A, как вы, вероятно, ожидаете.


Возможное решение, как уже было предложено Исе Вистерия, заключается в том, чтобы заставить расширение с помощью:

#define EXPAND(x) x
#define PP_NARGS(...) \
    EXPAND(_xPP_NARGS_IMPL(__VA_ARGS__,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))

Ответ 3

__VA_ARGS__ - функция языка C99.
VС++ не является компилятором C99.
Сделайте математику.

Это похоже на попытку скомпилировать Pascal с компилятором Scheme и найти его нечетным, он не работает для пар "начало/конец".

Я понятия не имею, как С++ и Visual Studio ведут себя во всем этом.