Boost logo

Boost Users :

Subject: Re: [Boost-users] [preprocessor] having trouble using reentrant macros
From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2012-03-29 11:29:39


On Thu, 29 Mar 2012 14:39:20 +0100, Rob Desbois wrote:

> I'm unable to use the reentrant macros for iteration currently..I think
> I'm probably misunderstanding their usage, and a push in the right
> direction would be much appreciated.
>
> My need is to iterate through a sequence, then iterate through a
> sequence nested within each element.
> As I understand, I should be able to call (e.g.): *
> BOOST_PP_SEQ_FOR_EACH(OP, data, seq) to iterate through the outer
> sequence * then in OP(r, data, elem) call BOOST_PP_SEQ_FOR_EACH_R(r,
> OP2, data, elem)

Neither BOOST_PP_SEQ_FOR_EACH nor BOOST_PP_SEQ_TRANSFORM are reentrant
algorithms. In fact, only a relative few of the core algorithms in the pp-
lib are reentrant. In the cases of SEQ_FOR_EACH and SEQ_TRANSFORM, the
SEQ_FOR_EACH_R and SEQ_TRANSFORM_S variants of those macros reenter
BOOST_PP_FOR and BOOST_PP_SEQ_FOLD_LEFT efficiently. They do not reenter
SEQ_FOR_EACH and SEQ_TRANSFORM.

Unfortunately, it isn't realistic to implement everything in a reentrant
way (i.e. explosion of # of macros).

With Chaos--which requires a really good preprocessor (such as gcc)--
rather than the Boost.Preprocessor), all higher-order algorithms are
reentrant. E.g.

// 1.cpp
#include <chaos/preprocessor/recursion/expr.h>
#include <chaos/preprocessor/seq/transform.h>

#define I(s, e) <e>
#define M(s, is) CHAOS_PP_EXPR(CHAOS_PP_SEQ_TRANSFORM(I, is))
#define O(os) CHAOS_PP_EXPR(CHAOS_PP_SEQ_TRANSFORM(M, os))

O( ((a) (b) (c)) ((i) (j) (k)) ((x) (y) (z)) )

// w/gcc 4.7
$ g++ -std=c++11 -E -P -I $CHAOS_ROOT 1.cpp
((<a>)(<b>)(<c>))((<i>)(<j>)(<k>))((<x>)(<y>)(<z>))

With gcc earlier than 4.7 (e.g. 4.6.x), you'd use:

g++ -std=c++0x -E -P -I $CHAOS_ROOT -D CHAOS_PP_VARIADICS 1.cpp

Of course, if you want to get fancy:

// 2.cpp
#include <chaos/preprocessor/control/iif.h>
#include <chaos/preprocessor/detection/is_variadic.h>
#include <chaos/preprocessor/recursion/basic.h>
#include <chaos/preprocessor/recursion/expr.h>
#include <chaos/preprocessor/seq/for_each.h>

#define MACRO(s, ...) \
    CHAOS_PP_IIF(CHAOS_PP_IS_VARIADIC(__VA_ARGS__))( \
        MACRO_A, MACRO_B \
    )(CHAOS_PP_OBSTRUCT(), CHAOS_PP_NEXT(s), __VA_ARGS__) \
    /**/
#define MACRO_ID() MACRO
#define MACRO_A(_, s, ...) \
    CHAOS_PP_EXPR_S _(s)(CHAOS_PP_SEQ_FOR_EACH_S _( \
        s, MACRO_ID _(), __VA_ARGS__ \
    )) \
    /**/
#define MACRO_B(_, s, ...) (__VA_ARGS__)

#define FLATTEN(seq) \
    CHAOS_PP_EXPR(CHAOS_PP_SEQ_FOR_EACH( \
        MACRO, seq \
    )) \
    /**/

FLATTEN( ((a) (b) (c)) ((i) (j) (k)) ((x) (y) (z)) (1) ((2)) (((3))) )

$ g++ -std=c++11 -E -P -I $CHAOS_ROOT 2.cpp
(a)(b)(c)(i)(j)(k)(x)(y)(z)(1)(2)(3)

Here we have a recursive SEQ_FOR_EACH and a recursive target MACRO.

Regards,
Paul Mensonides


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net