#ifndef BOOST_MPL_WHILE_HPP_INCLUDED #define BOOST_MPL_WHILE_HPP_INCLUDED // Copyright Larry Evans 2009 // // $Id: while.cpp,v 1.51 2009/06/05 15:55:23 evansl Exp $ // $Date: 2009/06/05 15:55:23 $ // $Revision: 1.51 $ #include #include #include #include #include #include #define USE_WHILE_UNROLL #ifdef USE_WHILE_UNROLL # include # include # include #endif namespace boost { namespace mpl { //Notation: // MFC_or_LE = Metafunction class or Lambda Expression // (See Description on libs/mpl/doc/refmanual/apply.html) // // State = Any type. // (this is term used in libs/mpl/doc/refmanual/fold.html) // template < class StateMeta//nullary metafunction returning current State. , class OpPred=always//unary MFC_or_LE from State to Bool. , class OpThen=identity >//unary MFC_or_LE from State to State, > struct while_recur { typedef typename eval_if < typename apply::type , while_recur < apply , OpPred , OpThen > , StateMeta >::type type ; }; template < class OpPred , class OpThen , class OpElse=identity > > struct while_step /**@brief * metafunction class whose nested apply template * represents one iteration in a while_recur loop with * given OpPred and Opthen. * i.e. one iteration of the "loop": * * while_recur * */ { template < class StateOld > struct apply /**@brief * Calculates new state from old state, StateOld. */ : eval_if < typename ::boost::mpl::apply < OpPred , StateOld >::type , ::boost::mpl::apply < OpThen , StateOld > , ::boost::mpl::apply < OpElse , StateOld > > {}; }; #ifdef USE_WHILE_UNROLL // local macros, #undef-ined at the end of the header // // Acknowledegement: // Thr following macros are modelled after: // AUX_ITER_FOLD_FORWARD_STEP // AUX_LAST_FORWARD_STEP // at: // https://svn.boost.org/trac/boost/browser/trunk/boost/mpl/aux_/iter_fold_if_impl.hpp#L124 // on: // 2009-06-02(revision 29239) // # define AUX_WHILE_UNROLL_STEP(unused, i, unused2) \ typedef \ typename while_unroller::template apply \ < typename BOOST_PP_CAT(while_unroll_step,i)::type \ > \ BOOST_PP_CAT(while_unroll_step, BOOST_PP_INC(i)); \ /**/ # define AUX_LAST_UNROLL_STEP \ BOOST_PP_CAT(while_unroll_step, BOOST_MPL_LIMIT_UNROLLING) \ /**/ template < class StateMeta//nullary metafunction returning current State. , class OpPred=always//unary MFC_or_LE from State to Bool. , class OpThen=identity >//unary MFC_or_LE from State to State, > struct while_unroll_recur /**@brief * Purpose is same as while_recur; however, lessens the template recursion * depth problem. **@references * [1] http://www.mywikinet.com/mpl/paper/mpl_paper.html#sequences.unrolling * (NOTE: there's a typo. The `recursion` typedef should have * `fold_impl` instead of `fold_impl_step` as its template name. * Also, the recursion typedef here uses eval_if *and* while_unroll_recur * instead of just the enclosing while_unroll_recur {fold_impl in [1]} .) */ { private: typedef while_step < OpPred , OpThen > while_unroller ; typedef StateMeta while_unroll_step0 ; //The following BOOST_PP_REPEAT call corresponds to the //1st one inside the `struct iter_fold_if_impl` of //https://svn.boost.org/trac/boost/browser/trunk/boost/mpl/aux_/iter_fold_if_impl.hpp BOOST_PP_REPEAT( BOOST_MPL_LIMIT_UNROLLING , AUX_WHILE_UNROLL_STEP , unused ) typedef AUX_LAST_UNROLL_STEP last_unroll_step ; typedef eval_if < typename apply::type , while_unroll_recur < apply , OpPred , OpThen > , last_unroll_step > recursion ; public: typedef typename recursion::type type ; }; # undef AUX_WHILE_UNROLL_STEP # undef AUX_LAST_UNROLL_STEP #endif //USE_WHILE_UNROLL template < class StateNow , class OpStateState , class OpStatesEqual=is_same,arg<2> > > struct fix_point /**@brief * Finds the fixed point of unary metafunction * class, OpStateState. */ { typedef StateNow state_now ; typedef typename OpStateState::template apply < state_now >::type state_next ; typedef fix_point < state_next , OpStateState , OpStatesEqual > op_recur ; typedef typename apply < OpStatesEqual , state_now , state_next >::type done ; typedef typename eval_if < done , identity , op_recur >::type type ; }; }//exit mpl namespace }//exit boost namespace #endif #ifndef BOOST_MPL_WHILE_RECUR_SEQ_HPP_INCLUDED #define BOOST_MPL_WHILE_RECUR_SEQ_HPP_INCLUDED //#include #include #include #include #include #include #include namespace boost { namespace mpl { namespace aux { namespace while_recur_seq { template < typename State > struct while_state { typedef State state; typedef while_state type; }; template < typename Stack , typename State > struct while_stack_state : while_state { typedef Stack stack; typedef while_stack_state type; }; template < typename State , typename Iter > struct while_state_iter : State //either while_state or while_stack_state { typedef Iter iter; typedef while_state_iter type; }; template < typename State , typename Op > struct forward_step { typedef typename deref::type item; typedef while_state_iter < while_stack_state < typename push_front::type , typename apply::type > , typename next::type > type; }; template < typename State , typename Op > struct backward_step { typedef typename deref::type item; typedef while_state_iter < while_state::type> , typename next::type > type; }; template < typename State , typename Op > struct direction_step ; template < typename State , typename Iter , typename Op > struct direction_step < while_state_iter < while_state , Iter > , Op > : backward_step < while_state_iter , Op > { }; template < typename Stack , typename State , typename Iter , typename Op > struct direction_step < while_state_iter < while_stack_state , Iter > , Op > : forward_step < while_state_iter < while_stack_state , Iter > , Op > { }; template < typename StateNow , typename IterLast > struct not_iter_last : not_ < is_same < typename StateNow::iter , IterLast > > { }; template < typename Op , typename LazyExpr > struct apply_lazy1 { typedef typename apply::type type; }; template < typename StateNow , typename IterLast , typename Predicate=always > struct not_iter_last_pred : and_ < not_iter_last , apply_lazy1 > > { }; }//exit while_recur_seq namespace }//exit aux namespace template < typename Seq , typename State , typename OperStateVal , typename PredicateVal=always , templateclass Step=aux::while_recur_seq::backward_step > struct while_seq_directed { typedef typename begin::type first; typedef typename end::type last; typedef aux::while_recur_seq::while_state_iter state_iter; typedef Step < arg<1> , typename lambda::type > oper_state_ref; typedef aux::while_recur_seq::not_iter_last_pred < arg<1> , last , typename lambda::type > predicate_ref; typedef typename #ifdef USE_WHILE_UNROLL while_unroll_recur #else while_recur #endif < state_iter , predicate_ref , oper_state_ref >::type type; }; template < typename BOOST_MPL_AUX_NA_PARAM(Sequence) , typename BOOST_MPL_AUX_NA_PARAM(State) , typename BOOST_MPL_AUX_NA_PARAM(ForwardOp) , typename BOOST_MPL_AUX_NA_PARAM(ForwardPredicate) , typename BOOST_MPL_AUX_NA_PARAM(BackwardOp) , typename BOOST_MPL_AUX_NA_PARAM(BackwardPredicate) > struct while_recur_seq { #define WHILE_RECUR_SEQ_USE_WHILE_SEQ_DIRECTED struct forward { typedef list<> stack0; typedef Sequence seq; typedef State state_0; #ifndef WHILE_RECUR_SEQ_USE_WHILE_SEQ_DIRECTED typedef typename begin::type first; typedef typename end::type last; typedef typename lambda::type state_op; typedef typename lambda::type pred_op; typedef aux::while_recur_seq::while_state_iter < aux::while_recur_seq::while_stack_state , first > state_aux_0; typedef aux::while_recur_seq::not_iter_last_pred< arg<1>, last, pred_op> pred_aux_op; typedef aux::while_recur_seq::forward_step< arg<1>, state_op> state_aux_op; typedef typename while_recur::type result; #else typedef typename while_seq_directed < seq , aux::while_recur_seq::while_stack_state , ForwardOp , ForwardPredicate , aux::while_recur_seq::forward_step >::type result ; #endif }; struct backward { typedef typename forward::result::stack seq; typedef typename forward::result::state state_0; #ifndef WHILE_RECUR_SEQ_USE_WHILE_SEQ_DIRECTED typedef typename begin::type first; typedef typename end::type last; typedef typename lambda::type state_op; typedef typename lambda::type pred_op; typedef aux::while_recur_seq::while_state_iter < aux::while_recur_seq::while_state , first > state_aux_0; typedef aux::while_recur_seq::not_iter_last_pred< arg<1>, last, pred_op> pred_aux_op; typedef aux::while_recur_seq::backward_step,state_op> state_aux_op; typedef typename while_recur::type result; #else typedef typename while_seq_directed < seq , aux::while_recur_seq::while_state , BackwardOp , BackwardPredicate , aux::while_recur_seq::backward_step >::type result ; #endif }; typedef typename backward::result::state type; }; }//exit mpl namespace }//exit boost namespace #endif //-{--while_recur_seq_test-- #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace mpl { namespace test_while { typedef int int_type ; typedef #if 0 range_c< int_type, 9, 13> #else list_c< int_type, 9, 10, 11, 12> #endif numbers ; namespace palindrome { typedef while_recur_seq < numbers , vector<> , push_front, arg<2> > , always , push_front, arg<2> > , always > while_result ; typedef while_result::type actual_result ; typedef vector_c expected_result ; BOOST_MPL_ASSERT((equal)) ; }//exit palindrome namespace namespace palindrome_pred_fwd { typedef while_recur_seq < numbers , vector<> , push_front, arg<2> > , less,integral_c > , push_front, arg<2> > , always > while_result ; typedef while_result::type actual_result ; typedef vector_c expected_result ; BOOST_MPL_ASSERT((equal)) ; }//exit palindrome_pred_fwd namespace namespace palindrome_pred_both { typedef while_recur_seq < numbers , vector<> , push_front, arg<2> > , less,integral_c > , push_front, arg<2> > , greater,integral_c > > while_result ; typedef while_result::type actual_result ; typedef vector_c expected_result ; BOOST_MPL_ASSERT((equal)) ; }//exit palindrome_pred_both namespace }//exit test_while namespace namespace test_fix_point { typedef int int_type ; namespace int_dec_to_0 { typedef integral_c expected_fix_down_result ; int_type const val0_down=3 ; typedef integral_c state0_down ; typedef greater,expected_fix_down_result> op_pred_down ; typedef apply < op_pred_down , state0_down >::type actual_pred_down_result ; BOOST_MPL_ASSERT((actual_pred_down_result)) ; typedef prior > op_state_down ; #if 1 typedef while_step < op_pred_down , op_state_down > op_step_down ; typedef op_step_down::apply::type actual_step_down_result ; typedef prior::type expected_step_down_result ; BOOST_MPL_ASSERT((equal_to)) ; #endif #if 1 typedef fix_point < state0_down , op_step_down , equal_to,arg<2> > >::type actual_fix_down_result ; BOOST_MPL_ASSERT((equal_to)) ; #endif typedef op_step_down::apply::type state1_down ; typedef op_step_down::apply::type state2_down ; BOOST_MPL_ASSERT_NOT((equal_to)) ; typedef op_step_down::apply::type state3_down ; BOOST_MPL_ASSERT((equal_to)) ; typedef integral_c expected_fix_up_result ; typedef and_ < greater >,expected_fix_down_result> , less >,expected_fix_up_result> > op_pred_up ; typedef next > > op_state_up ; typedef while_step < op_pred_up , op_state_up , second > > op_step_up ; typedef pair state3_pair ; typedef apply < op_pred_up , state3_pair >::type actual_op_pred_state3_up ; BOOST_MPL_ASSERT_NOT((actual_op_pred_state3_up)) ; typedef apply < op_state_up , state3_pair >::type actual_op_state_state3_up ; BOOST_MPL_ASSERT((is_same::type>)) ; typedef op_step_up::apply < state3_pair >::type state3_up ; BOOST_MPL_ASSERT((equal_to)) ; typedef pair state2_pair ; typedef apply < op_pred_up , state2_pair >::type actual_op_pred_state2_up ; BOOST_MPL_ASSERT((actual_op_pred_state2_up)) ; typedef op_step_up::apply < state2_pair >::type state2_up ; BOOST_MPL_ASSERT((equal_to)) ; typedef pair state1_pair ; typedef op_step_up::apply < state1_pair >::type state1_up ; BOOST_MPL_ASSERT((equal_to)) ; typedef pair state0_pair ; typedef op_step_up::apply < state0_pair >::type state0_up ; BOOST_MPL_ASSERT((equal_to)) ; #if 0 #endif }//exit int_dec_to_0 namespace }//exit test_fix_point namespace }//exit mpl namespace }//exit boost namespace //-}--while_recur_seq_test--