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