Проблемы с расширением макросов в MSVC
Интересно, почему этот макрос так сильно расширяется.
#define CONCAT_IMPL(A, B) A##B
#define CONCAT(A, B) CONCAT_IMPL(A, B)
#define EAT(...)
#define TEST(ARG) EXPANDED, ARG) EAT(
#define GET_LAST(A, B) B
int result = 0;
result = GET_LAST(CONCAT(TEST, (1)), 2); // result is 2
result = GET_LAST(TEST(1), 2); // result is 2
result = GET_LAST(EXPANDED, 1) EAT(, 2); // result is 1
Я хочу GET_LAST(CONCAT(TEST, (1)), 2); расчетное значение 1.
Буду признателен, если вы скажете мне, возможно ли это на MSVC или что-то не хватает.
1 ответ
Последовательность токенов предварительной обработки, ограниченная внешними совпадающими круглыми скобками, формирует список аргументов для макроса, подобного функции. Отдельные аргументы в списке разделяются запятыми токенами предварительной обработки, но запятые токены предварительной обработки между соответствующими внутренними скобками не разделяют аргументы.
GET_LAST(CONCAT(TEST, (1)), 2)
это вызов макроса GET_LAST
со списком из двух аргументов. ОдинCONCAT(TEST, (1))
а другой 2
.
После того, как аргументы для вызова функционально-подобного макроса определены, происходит подстановка аргументов. Параметр в списке замены, если ему не предшествует токен предварительной обработки # или ## или не следует токен предварительной обработки ## (см. Ниже), заменяется соответствующим аргументом после того, как все содержащиеся в нем макросы были развернуты. Перед заменой токены предварительной обработки каждого аргумента полностью заменяются макросом, как если бы они сформировали остальную часть файла предварительной обработки; других токенов предварительной обработки нет.
Первый параметр A
не встречается в списке замен макроса, поэтому с соответствующим аргументом ничего не делается. Второй параметрB
происходит, поэтому соответствующий аргумент макроса расширяется до 2
, и появление B
в списке замены заменяется расширением.