Проблемы с расширением макросов в 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 ответ

Решение

Проект C11:

Последовательность токенов предварительной обработки, ограниченная внешними совпадающими круглыми скобками, формирует список аргументов для макроса, подобного функции. Отдельные аргументы в списке разделяются запятыми токенами предварительной обработки, но запятые токены предварительной обработки между соответствующими внутренними скобками не разделяют аргументы.

GET_LAST(CONCAT(TEST, (1)), 2) это вызов макроса GET_LASTсо списком из двух аргументов. ОдинCONCAT(TEST, (1)) а другой 2.

После того, как аргументы для вызова функционально-подобного макроса определены, происходит подстановка аргументов. Параметр в списке замены, если ему не предшествует токен предварительной обработки # или ## или не следует токен предварительной обработки ## (см. Ниже), заменяется соответствующим аргументом после того, как все содержащиеся в нем макросы были развернуты. Перед заменой токены предварительной обработки каждого аргумента полностью заменяются макросом, как если бы они сформировали остальную часть файла предварительной обработки; других токенов предварительной обработки нет.

Первый параметр Aне встречается в списке замен макроса, поэтому с соответствующим аргументом ничего не делается. Второй параметрB происходит, поэтому соответствующий аргумент макроса расширяется до 2, и появление B в списке замены заменяется расширением.

Другие вопросы по тегам