Boost препроцессор не расширяется

У меня есть следующий код:

#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 или g ++ 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 не раскрыт?

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

РЕДАКТИРОВАТЬ: После долгих поисков я прочитал, что макрос не будет расширяться, если он вызывается дважды, я думаю, поэтому.

РЕДАКТИРОВАТЬ: я должен был использовать PP_SEQ_FOR_EACH_I, R не предназначен для использования в качестве нижнего индекса.

3

Решение

BOOST_PP_SEQ_FOR_EACH не является входящий угол. В 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) ())
)
4

Другие решения

#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) ())
)
1