
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)