2016-04-07 2 views
1

Я работаю над рекурсивным макросом. Однако, похоже, он не рекурсивно расширяется. Вот минимальный рабочий пример, чтобы показать, что я имею в виду:Рекурсивный макрос C не расширен

// ignore input, do nothing 
#define ignore(...) 
// choose between 6 names, depending on arity 
#define choose(_1,_2,_3,_4,_5,_6,NAME,...) NAME 
// if more than one parameter is given to this macro, then execute f, otherwise ignore 
#define ifMore(f,...) choose(__VA_ARGS__,f,f,f,f,f,ignore)(__VA_ARGS__) 
// call recursively if there are more parameters 
#define recursive(first,args...) first:ifMore(recursive,args) 

recursive(a,b,c,d) 
// should print: a:b:c:d 
// prints: a:recursive(b,c,d) 

recursive макрос должен расширять себя рекурсивно и всегда сцепить результат, отделенный двоеточием. Однако это не работает. Рекурсивный макрос генерируется правильно (как видно из результата a:recursive(b,c,d), который включает в себя хорошо сформированный вызов макроса снова), но сгенерированный рекурсивный вызов is not exansed.

Почему это так и как я могу получить поведение, которое я хочу?

+1

«Я работаю на рекурсивной макрокоманды» - ну, это трудно понять, что сказать :(Нерекурсивные макросы - это PITA. –

ответ

4

Вы не можете получить нужное поведение. Препроцессор C, по своему усмотрению, не завершен.

Вы можете использовать несколько макросов для получения нескольких замен, но вы не достигнете истинной рекурсии с произвольным количеством замен.

+0

какое правило запрещает мой макрос снова расширяться здесь? Какое правило? – gexicide

+0

Вы можете найти правило здесь: http://stackoverflow.com/a/12447739/464136 –

1

Препроцессор компилятора не будет расшифровывать макрос, который вы определяете. То есть он будет слепо заменять любую строку, найденную в макрооператоре, с помощью строки, которую он находит в определении. Например, Can we have recursive macros? или Macro recursive expansion to a sequence и C preprocessor, recursive macros

То есть, recursive(a,b,c,d) будет расширен до a:recursive(b,c,d) и предварительно процессор будет затем перейти к следующей строке в базовом коде. Он не будет зацикливаться, чтобы попытаться продолжить расширение строки (см. Ссылки, которые я привел).

+1

«он будет слепо заменять любую строку, найденную в макрооператоре, строкой, которую он находит в определении». Ну, это именно то, что я хочу, но это не делает это здесь! явно является строкой 'рекурсивный (b, c, d)' в результате, но не заменяется строкой в ​​определении 'recursive'. – gexicide

+0

Нет смысла в том, чтобы ваше определение включало строку «рекурсивная (b, c, d)». В результате она слепо копирует эту строку в код, который нужно скомпилировать. Следуйте ссылкам, которые я показываю. – sabbahillel

+1

@sabbahillel: Но если тело содержит другой макрос, оно расширит его. Таким образом, это не имеет никакого отношения к «слепому копированию». Фактически, препроцессор имеет открытые глаза, как он получает; он ищет макросы для расширения, но тщательно игнорирует макросы, которые уже расширяются. – rici

1

Как уже упоминалось, чистая рекурсия невозможна с макросами C. Тем не менее, можно моделировать рекурсивные эффекты.

подпиточного инструменты препроцессор сделать это хорошо как для C и C++ и автономные библиотеки:

http://www.boost.org/doc/libs/1_60_0/libs/preprocessor/doc/index.html

Смежные вопросы