Boost logo

Boost :

From: Tobias Schwinger (tschwinger_at_[hidden])
Date: 2006-11-05 12:10:20


Daniel Wallin wrote:
> Eric Niebler wrote:
>
>>I'd still be curious what a PP solution looks like, though. The problem
>>stumped me for quite some time.
>
>
> I'll bite. It's a bit of a hack, but it works. :) It basically
> accumulates the closing >'s as it goes, and expands them after the last
> item. It keeps a looping counter that keeps track of when to split into
> another mpl::and_<>.
>

Here is an alternative implementation with a similar approach, using a sequence to "escape" the commas and SEQ_ENUM for "unescaping".

Next fun challenge: build a tree instead:

  mpl::and_< pred0, pred1, pred2, pred3 >
  // ...
  mpl::and_< pred0, pred1, pred2, mpl::and_< pred3, pred4, pred5, pred6> >
  mpl::and_< pred0, pred1, mpl::and_< pred2, pred3>, mpl::and_< pred4, pred5, pred6, pred7 > >
  mpl::and_< pred0, pred1, mpl::and_< pred2, pred3, pred4>, mpl::and_< pred5, pred6, pred7, pred8 > >
  mpl::and_< pred0, pred1, mpl::and_< pred2, pred3, pred4, pred5>, mpl::and_< pred6, pred7, pred8, pred9 > >
  // ...

;-P

Regards,

Tobias


#include <boost/preprocessor/facilities/expand.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/facilities/identity.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/arithmetic/mod.hpp>
#include <boost/preprocessor/comparison/not_equal.hpp>
#include <boost/preprocessor/logical/not.hpp>
#include <boost/preprocessor/logical/or.hpp>
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/control/while.hpp>
#include <boost/preprocessor/seq/enum.hpp>

// state is a tuple (prev-seq,next-seq,n,stop)

// "unescape" the state into output

#define FINALIZE_STATE(head_seq, tail_elem, n, stop) \
    BOOST_PP_SEQ_ENUM(head_seq()) tail_elem()

// state modifiers

#define NEXT_PRED(head_seq, tail_elem, n, stop) \
    ( BOOST_PP_IDENTITY(head_seq() (pred ## n)) \
    , tail_elem \
    , BOOST_PP_INC(n), stop \
    )

#define NEXT_OP(head_seq, tail_elem, n, stop) \
    ( BOOST_PP_IDENTITY(head_seq() (mpl::and_< pred ## n)) \
    , > tail_elem \
    , BOOST_PP_INC(n), stop \
    )

// select either NEXT_PRED or NEXT_OP

#define NEXT_PRED_COND(head_seq, tail_elem, n, stop) \
    BOOST_PP_OR( BOOST_PP_MOD(n,3) \
               , BOOST_PP_NOT( \
                   WHILE_PRED_IMPL (~,~,BOOST_PP_INC(n),stop) ) )

#define WHILE_OP(d,state) \
    BOOST_PP_IF(NEXT_PRED_COND state, NEXT_PRED \
        , NEXT_OP) state

// predicate to terminate the while loop

#define WHILE_PRED_IMPL(head_seq, tail_elem, n, stop) \
    BOOST_PP_NOT_EQUAL(n,stop)

#define WHILE_PRED(d,state) WHILE_PRED_IMPL state

//

#define ALL(n) BOOST_PP_EXPAND( FINALIZE_STATE \
    BOOST_PP_WHILE(WHILE_PRED, WHILE_OP \
        , (BOOST_PP_EMPTY,BOOST_PP_EMPTY,0,n)) )

ALL(1)
ALL(2)
ALL(3)
ALL(4)
ALL(5)
ALL(6)
ALL(7)
ALL(8)
ALL(9)


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk