2013-03-27 3 views
3

У меня есть следующий код:Повышение препроцессор не расширяется

#include <boost/preprocessor.hpp> 

#define ARGS(r, data, elem) \ 
    BOOST_PP_COMMA_IF(BOOST_PP_SUB(r, 2)) \ 
    BOOST_PP_SEQ_ELEM(0, elem) BOOST_PP_SEQ_ELEM(1, elem) 

#define DEF_FUN(name, args) void name(BOOST_PP_SEQ_FOR_EACH(ARGS,,args)); 

#define DEF_FUNCTIONS_ELEM(r, data, elem) DEF_FUN(BOOST_PP_SEQ_ELEM(0, elem), BOOST_PP_SEQ_ELEM(1, elem)) 

#define DEF_FUNCTIONS(funSeqs) \ 
    BOOST_PP_SEQ_FOR_EACH(DEF_FUNCTIONS_ELEM,, funSeqs) 


DEF_FUNCTIONS_ELEM(2,, (fun0) (((int)(arg0)) ((char)(arg1)))) 

DEF_FUNCTIONS 
(
    ((fun0) (((int)(arg0)) ((char)(arg1)))) 
    ((fun1) (((char)(arg0)) ((long)(arg1)) ((short)(arg2)))) 
    ((fun3)()) 
) 

Когда я препроцессировать это с Clang 3.2 или г ++ 4.6.3, я получаю:

void fun0(int arg0 , char arg1); 

void fun0(BOOST_PP_SEQ_FOR_EACH(ARGS,,((int)(arg0)) ((char)(arg1)))); 
void fun1(BOOST_PP_SEQ_FOR_EACH(ARGS,,((char)(arg0)) ((long)(arg1)) ((short)(arg2)))); 
void fun3(BOOST_PP_SEQ_FOR_EACH(ARGS,,)); 

(я добавил разрывы строк для ясность)

Вопрос в том, почему внутренний BOOST_PP_SEQ_FOR_EACH не расширен?

Передача этого результата снова увеличивает ожидаемый результат.

EDIT: После многого поиска я прочитал, что макрос не будет расширяться, если его вызывают дважды, я думаю, именно поэтому.

EDIT: Я должен был использовать PP_SEQ_FOR_EACH_I, R не предназначен для использования в качестве индекса.

+0

Теперь я делаю большую часть генерации кода в python и только мелкие вещи в макросах. – chila

ответ

4

BOOST_PP_SEQ_FOR_EACH не reentrant. В Boost.PP есть только несколько макросов, которые являются реентерабельными (BOOST_PP_FOR, BOOST_PP_WHILE и BOOST_PP_REPEAT). Тем не менее, вы можете обходным путем, используя отложенные выражения, например:

#include <boost/preprocessor.hpp> 

#define EXPAND(...) __VA_ARGS__ 
#define EMPTY() 
#define DEFER(x) x EMPTY() 
// An indirection macro to avoid direct recursion 
#define BOOST_PP_SEQ_FOR_EACH_ID() BOOST_PP_SEQ_FOR_EACH 

#define ARGS(r, data, elem) \ 
    BOOST_PP_COMMA_IF(BOOST_PP_SUB(r, 2)) \ 
    BOOST_PP_SEQ_ELEM(0, elem) BOOST_PP_SEQ_ELEM(1, elem) 

// Defer BOOST_PP_SEQ_FOR_EACH_ID here 
#define DEF_FUN(name, args) void name(DEFER(BOOST_PP_SEQ_FOR_EACH_ID)()(ARGS,,args)); 

#define DEF_FUNCTIONS_ELEM(r, data, elem) DEF_FUN(BOOST_PP_SEQ_ELEM(0, elem), BOOST_PP_SEQ_ELEM(1, elem)) 

// Add EXPAND here to apply another scan to expand the deferred expression 
#define DEF_FUNCTIONS(funSeqs) \ 
    EXPAND(BOOST_PP_SEQ_FOR_EACH(DEF_FUNCTIONS_ELEM,, funSeqs)) 


DEF_FUNCTIONS 
(
    ((fun0) (((int)(arg0)) ((char)(arg1)))) 
    ((fun1) (((char)(arg0)) ((long)(arg1)) ((short)(arg2)))) 
    ((fun3)()) 
) 
+0

Это работает, слишком плохо, мы должны изменить DEF_FUN, чтобы сделать его SEQ_FOR_EACH-способным. Будет ли способ изменить вызывающего абонента вместо вызываемого? Жаль, что препроцессор не рекурсирует, по крайней мере, в течение ограниченного количества раз. Должен моститься до mpl/fusion, как только сможете. – chila

1
#include <boost/preprocessor.hpp> 

#define ARGS(r, data, index, elem) \ 
    BOOST_PP_SEQ_ELEM(0, elem) BOOST_PP_SEQ_ELEM(1, elem) BOOST_PP_COMMA_IF(BOOST_PP_NOT_EQUAL(index, BOOST_PP_DEC(data))) 

#define DEF_FUN(name, args) void name(BOOST_PP_SEQ_FOR_EACH_I(ARGS,BOOST_PP_SEQ_SIZE(args),args)); 

#define DEF_FUNCTIONS_ELEM(r, data, elem) DEF_FUN(BOOST_PP_SEQ_ELEM(0, elem), BOOST_PP_SEQ_ELEM(1, elem)) 

#define DEF_FUNCTIONS(funSeqs) \ 
    BOOST_PP_SEQ_FOR_EACH(DEF_FUNCTIONS_ELEM,, funSeqs) 


DEF_FUNCTIONS_ELEM(2,, (fun0) (((int)(arg0)) ((char)(arg1)))) 

DEF_FUNCTIONS 
(
    ((fun0) (((int)(arg0)) ((char)(arg1)))) 
    ((fun1) (((char)(arg0)) ((long)(arg1)) ((short)(arg2)))) 
    ((fun3)()) 
) 
+0

Да, это возможность, я работал, преобразовывая основную последовательность в PP_LIST, а затем вызывал PP_LIST_FOR_EACH. Но учитывая тот факт, что на самом деле нужно использовать PP_SEQ_FOR_EACH_I (см. Мое редактирование), следует использовать более общий обходной путь, я думаю. – chila

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