
On Wed, 31 Aug 2011 16:09:30 -0400, Edward Diener wrote:
instead. Although this change still produces compiler errors with gcc and Boost 1.47 and below ( Paul Mensonsides is looking into that since he knows how iteration works with Boost PP ), it solves the problem compiling with gcc and the latest Boost PP on the trunk.
Okay, here's what's going on... 1) GCC performs macro expansion and parsing on the expressions of all #if/ #elif/#endif blocks that it encounters when not already skipping because of an outer #if/#endif. It is questionable whether this is what was intended, but it is arguable either way. Thus, code like this #if !BOOST_PP_IS_ITERATING // ... #elif BOOST_PP_ITERATION_FLAGS() == 1 // ... #elif BOOST_PP_ITERATION_FLAGS() == 2 // ... #endif should be altered to #if !BOOST_PP_IS_ITERATING #else #if BOOST_PP_ITERATION_FLAGS() == 1 // ... #else // ... #endif #endif The second problem is that the iteration flags are not "evaluated" in the way that the iteration bounds are evaluated but are instead defined to be the whatever was put in the iteration parameters. The error occurs in the during the nested iteration (that includes the SUB, etc.). The ultimate problem is in the way that BOOST_PP_ITERATION_FLAGS() is defined in the <= 1.47 codebase which is essentially: CAT(ITERATION_FLAGS_, ITERATION_DEPTH()) This concatenation forms ITERATION_FLAGS_2, in this case, which, in turn tries to extract the flags via ARRAY_ELEM(3, ITERATION_PARAMS_2). The ITERATION_PARAMS_2 value, however, uses SUB, which uses one of the parentheses detection macros to check for zero. However, those detection macros require CAT--which doesn't expand because we're already "inside" CAT--which prevents the intermediate from expanding from a single "argument" to two "arguments", and then you get the diagnostic. The fix, which has already been in the trunk for a while is to alter the headers as follows: boost/preprocessor/iteration/iterate.hpp - alter the definition of ITERATION_FLAGS() from (BOOST_PP_CAT(BOOST_PP_ITERATION_FLAGS_, BOOST_PP_ITERATION_DEPTH())) to (BOOST_PP_CAT(BOOST_PP_ITERATION_FLAGS_, BOOST_PP_ITERATION_DEPTH())()) (i.e. changing ITERATION_FLAGS_n into a function-like macro) boost/preprocessor/iteration/detail/iter/forward1.hpp ... 2.hpp ... 3.hpp ... 4.hpp ... 5.hpp - each of these five headers contain definitions of ITERATION_FLAGS_n in three places near the top. These all need to be changed to nullary function-like macros instead of object-like macros. That will fix the problem. Alternatively, the iteration flags are "supposed" to be used to distinguish between different iterations at the same depth. Here, however, they are being used where they don't need to be. The iteration flags could have been elided and just use ITERATION_DEPTH() instead... #if !IS_ITERATING #else #if ITERATION_DEPTH() == 1 #elif ITERATION_DEPTH() == 2 #endif #endif