почему этому макросу PP_ARG_COUNT нужен PP_EXPAND?

#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 не работает?


person Hikari    schedule 31.03.2014    source источник


Ответы (1)


Это обходной путь для ошибки в препроцессоре Visual C++. В некоторых контекстах неправильно расширяются последовательности токенов, разделенные запятыми.

В вашем PP_ARG_COUNT2 __VA_ARGS__ рассматривается как один аргумент при использовании в вызове PP_ARG_POPER, что приводит к неправильному результату.

Наиболее распространенным обходным путем для этой проблемы является введение дополнительного уровня косвенности, который заставляет компилятор повторно оценивать последовательность токенов с разделителями-запятыми. Используемая здесь техника с вызовом PP_ARG_COUNT через EXPAND является одним из способов сделать это; Я представил вариант этой техники в ответе на другой вопрос.

person James McNellis    schedule 31.03.2014