Reputation: 2442
I have the following code:
#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) ())
)
When I preprocess this with Clang 3.2 or g++ 4.6.3, I get:
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,,));
(I added line-breaks for clarity)
The question is, why is the inner BOOST_PP_SEQ_FOR_EACH not expanded?
Passing this output again expands the expected result.
EDIT: After a lot of searching I read that a macro wont expand if it's called twice, I think that's why.
EDIT: I should've used PP_SEQ_FOR_EACH_I, the R is not meant to be used as a subscript.
Upvotes: 3
Views: 2251
Reputation: 18218
BOOST_PP_SEQ_FOR_EACH
is not reentrant. There are only a few macros in Boost.PP that are reentrant(BOOST_PP_FOR
, BOOST_PP_WHILE
, and BOOST_PP_REPEAT
). However, you can workaround it by using deferred expressions, like this:
#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) ())
)
Upvotes: 4
Reputation: 11
#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) ())
)
Upvotes: 1