|
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