Как разделить результат раскрытия макроса на разные аргументы? - PullRequest
3 голосов
/ 15 апреля 2011

Я пишу метапрограмму Boost.Preprocessor, и у меня возникла следующая проблема. Рассмотрим следующие макросы (это упрощение для иллюстрации проблемы):

#define ITERATION_IMPL(p1, p2, p3, p4) ((p1),(p2),(p3),(p4))
#define ITERATION(args) ITERATION_IMPL(hello, args(), world)

#define ARGS() a, b
ITERATION(ARGS)

Предварительно обработанный вывод такой:

((hello),(a, b),(world),())

Это показывает, что args() не разделен на несколько аргументов. Согласно моему пониманию стандарта, аргументы макроса полностью раскрываются перед вставкой в ​​список замены. Поэтому я ожидал бы следующую последовательность расширения:

ITERATION(ARGS)
ITERATION_IMPL(hello, ARGS(), world)
ITERATION_IMPL(hello, a, b, world)
((hello),(a),(b),(world))

Это мой желаемый результат. Как мне достичь этого, не изменяя ITERATION_IMPL и сам вызов?

Редактировать: Если это невозможно (и я предполагаю, что это так), пожалуйста, объясните это на основе любого стандарта C или C ++.

1 Ответ

3 голосов
/ 15 апреля 2011

Я думаю, что если встречается ITERATION(ARGS), он принимает ITERATION_IMPL(hello, args(), world), заменяет args на ARGS, а затем выполняет повторное сканирование.ITERATION_IMPL(hello, ARGS(), world) является вызовом ITERATION_IMPL.Для этого он принимает ((p1),(p2),(p3),(p4)) и заменяет p2 на ARGS() (вместе с другими параметрами).Затем он сканирует и разрешает ((hello),(a, b),(world),()).Я не знаю, почему это работает, что он вызывает макрос с 4 параметрами с 3 аргументами в вашем случае.

Вы могли бы сделать

#define EVAL(X) X
#define ITERATION(args) ITERATION_IMPL EVAL((hello, args(), world))

Это заняло бы X, подставило бы (hello, ARGS(), world), а затем повторило бы сканирование, в результате чего ARGS() был бы заменен на a, b.Получившаяся строка токена ITERATION_IMPL (hello, a, b, world) сделает то, что вы ожидали

РЕДАКТИРОВАТЬ: протестировано с GCC:)

РЕДАКТИРОВАТЬ: я заметил, что вы хотите строку ((hello),(a),(b),(world)), но мой ответ дает строку ITERATION_IMPL (hello, a, b, world).Я думаю, это потому, что когда он повторно просматривает после вызова ITERATION, он заменяет IERATION_IMPL EVAL((hello, ARGS(), world)) на ITERATION_IMPL (hello, a, b, wold).Затем потребуется еще одно сканирование, чтобы заметить, что теперь он может вызывать ITERATION_IMPL с этими аргументами.Таким образом, ITERATION должно быть

#define ITERATION(args) EVAL(ITERATION_IMPL EVAL((hello, args(), world)))

Когда X для внешнего EVAL заменяется на ITERATION_IMPL EVAL((hello, args(), world)), оно повторно просматривает и выдает ITERATION_IMPL (hello, a, b, world) для вызова EVAL.Затем он снова пересматривается для вызова ITERATION и выдает последовательность, которую вы действительно хотели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...