#include <type_traits>
#include <iostream>
using namespace std;
// Expand
#define PP_EXPAND(X) X
// Counter Arguments count
#define PP_ARG_COUNT(...) PP_EXPAND( PP_ARG_POPER(__VA_ARGS__, 5, 4, 3, 2, 1, 0) )
#define PP_ARG_COUNT2(...) PP_ARG_POPER(__VA_ARGS__, 5, 4, 3, 2, 1, 0)
#define PP_ARG_POPER(_1, _2, _3, _4, _5, N, ...) N
int main()
{
cout << PP_ARG_COUNT(1, 2, int) << endl;
cout << PP_ARG_COUNT2(1, 2, int) << endl;
cout << PP_ARG_POPER(1, 2, int, 5, 4, 3, 2, 1 0) << endl;
return 0;
}
Я скомпилировал этот код в Visual Studio 2013, он выводит:
3
1
3
зачем этому макросу нужен PP_EXPAND, а PP_ARG_COUNT2 это не работает?
Это обходной путь для ошибки в препроцессоре Visual C ++. В некоторых контекстах он неправильно не раскрывает последовательности токенов, разделенных запятыми.
В вашем PP_ARG_COUNT2
, __VA_ARGS__
рассматривается как один аргумент при использовании в вызове PP_ARG_POPER
, вызывая неверный результат.
Наиболее распространенным способом решения этой проблемы является введение дополнительного уровня косвенности, который заставляет компилятор переоценивать последовательность токенов, разделенных запятыми. Техника, используемая здесь, с PP_ARG_COUNT
вызывая через EXPAND
это один из способов сделать это; Я представил вариант этой техники в ответ на другой вопрос.
Других решений пока нет …