Почему этот макрос с переменным числом аргументов не работает с VC ++? - PullRequest
17 голосов
/ 03 апреля 2011

Я получил следующую реализацию, чтобы получить число аргументов в макросе с переменным числом аргументов (в настоящее время ограничено 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;
}

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

Ответы [ 3 ]

23 голосов
/ 03 апреля 2011

Помогает ли следующее обходное решение?

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

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

1 голос
/ 05 июля 2016

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

В вашем случае PP_NARGS(A,V,C,X,Y,Z) связывает *От 1007 * до __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, как вы, вероятно, ожидаете.


Возможное решение, как уже предлагалось Ise Wisteria, заключается в форсировании расширения с помощью:

#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))
0 голосов
/ 03 апреля 2011

__VA_ARGS__ является языковой функцией C99.
VC ++ не является компилятором C99.
Посчитай.

Это все равно, что пытаться скомпилировать Pascal с помощью компилятора Scheme и найти его странным, что он не работает для пар «начало / конец».

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

...