1 /////////////////////////////////////////////////////////////////////////////// 2 /// \file fold.hpp 3 /// Contains definition of the fold<> and reverse_fold<> transforms. 4 // 5 // Copyright 2008 Eric Niebler. Distributed under the Boost 6 // Software License, Version 1.0. (See accompanying file 7 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 9 #ifndef BOOST_PROTO_TRANSFORM_FOLD_HPP_EAN_11_04_2007 10 #define BOOST_PROTO_TRANSFORM_FOLD_HPP_EAN_11_04_2007 11 12 #include <boost/preprocessor/cat.hpp> 13 #include <boost/preprocessor/iteration/iterate.hpp> 14 #include <boost/preprocessor/arithmetic/inc.hpp> 15 #include <boost/preprocessor/arithmetic/sub.hpp> 16 #include <boost/preprocessor/repetition/repeat.hpp> 17 #include <boost/fusion/include/fold.hpp> 18 #include <boost/fusion/include/reverse_fold.hpp> 19 #include <boost/proto/proto_fwd.hpp> 20 #include <boost/proto/traits.hpp> 21 #include <boost/proto/transform/impl.hpp> 22 #include <boost/proto/transform/when.hpp> 23 24 namespace boost { namespace proto 25 { 26 namespace detail 27 { 28 template<typename Transform, typename Data> 29 struct as_callable 30 { as_callableboost::proto::detail::as_callable31 as_callable(Data d) 32 : d_(d) 33 {} 34 35 template<typename Sig> 36 struct result; 37 38 template<typename This, typename State, typename Expr> 39 struct result<This(State, Expr)> 40 { 41 typedef 42 typename when<_, Transform>::template impl<Expr, State, Data>::result_type 43 type; 44 }; 45 46 template<typename State, typename Expr> 47 typename when<_, Transform>::template impl<Expr &, State const &, Data>::result_type operator ()boost::proto::detail::as_callable48 operator ()(State const &s, Expr &e) const 49 { 50 return typename when<_, Transform>::template impl<Expr &, State const &, Data>()(e, s, this->d_); 51 } 52 53 private: 54 Data d_; 55 }; 56 57 template< 58 typename State0 59 , typename Fun 60 , typename Expr 61 , typename State 62 , typename Data 63 , long Arity = arity_of<Expr>::value 64 > 65 struct fold_impl 66 {}; 67 68 template< 69 typename State0 70 , typename Fun 71 , typename Expr 72 , typename State 73 , typename Data 74 , long Arity = arity_of<Expr>::value 75 > 76 struct reverse_fold_impl 77 {}; 78 79 #include <boost/proto/transform/detail/fold_impl.hpp> 80 81 } // namespace detail 82 83 /// \brief A PrimitiveTransform that invokes the <tt>fusion::fold\<\></tt> 84 /// algorithm to accumulate 85 template<typename Sequence, typename State0, typename Fun> 86 struct fold : transform<fold<Sequence, State0, Fun> > 87 { 88 template<typename Expr, typename State, typename Data> 89 struct impl : transform_impl<Expr, State, Data> 90 { 91 /// \brief A Fusion sequence. 92 typedef 93 typename remove_reference< 94 typename when<_, Sequence>::template impl<Expr, State, Data>::result_type 95 >::type 96 sequence; 97 98 /// \brief An initial state for the fold. 99 typedef 100 typename remove_reference< 101 typename when<_, State0>::template impl<Expr, State, Data>::result_type 102 >::type 103 state0; 104 105 /// \brief <tt>fun(d)(e,s) == when\<_,Fun\>()(e,s,d)</tt> 106 typedef 107 detail::as_callable<Fun, Data> 108 fun; 109 110 typedef 111 typename fusion::result_of::fold< 112 sequence 113 , state0 114 , fun 115 >::type 116 result_type; 117 118 /// Let \c seq be <tt>when\<_, Sequence\>()(e, s, d)</tt>, let 119 /// \c state0 be <tt>when\<_, State0\>()(e, s, d)</tt>, and 120 /// let \c fun(d) be an object such that <tt>fun(d)(e, s)</tt> 121 /// is equivalent to <tt>when\<_, Fun\>()(e, s, d)</tt>. Then, this 122 /// function returns <tt>fusion::fold(seq, state0, fun(d))</tt>. 123 /// 124 /// \param e The current expression 125 /// \param s The current state 126 /// \param d An arbitrary data operator ()boost::proto::fold::impl127 result_type operator ()( 128 typename impl::expr_param e 129 , typename impl::state_param s 130 , typename impl::data_param d 131 ) const 132 { 133 typename when<_, Sequence>::template impl<Expr, State, Data> seq; 134 detail::as_callable<Fun, Data> f(d); 135 return fusion::fold( 136 seq(e, s, d) 137 , typename when<_, State0>::template impl<Expr, State, Data>()(e, s, d) 138 , f 139 ); 140 } 141 }; 142 }; 143 144 /// \brief A PrimitiveTransform that is the same as the 145 /// <tt>fold\<\></tt> transform, except that it folds 146 /// back-to-front instead of front-to-back. 147 template<typename Sequence, typename State0, typename Fun> 148 struct reverse_fold : transform<reverse_fold<Sequence, State0, Fun> > 149 { 150 template<typename Expr, typename State, typename Data> 151 struct impl : transform_impl<Expr, State, Data> 152 { 153 /// \brief A Fusion sequence. 154 typedef 155 typename remove_reference< 156 typename when<_, Sequence>::template impl<Expr, State, Data>::result_type 157 >::type 158 sequence; 159 160 /// \brief An initial state for the fold. 161 typedef 162 typename remove_reference< 163 typename when<_, State0>::template impl<Expr, State, Data>::result_type 164 >::type 165 state0; 166 167 /// \brief <tt>fun(d)(e,s) == when\<_,Fun\>()(e,s,d)</tt> 168 typedef 169 detail::as_callable<Fun, Data> 170 fun; 171 172 typedef 173 typename fusion::result_of::reverse_fold< 174 sequence 175 , state0 176 , fun 177 >::type 178 result_type; 179 180 /// Let \c seq be <tt>when\<_, Sequence\>()(e, s, d)</tt>, let 181 /// \c state0 be <tt>when\<_, State0\>()(e, s, d)</tt>, and 182 /// let \c fun(d) be an object such that <tt>fun(d)(e, s)</tt> 183 /// is equivalent to <tt>when\<_, Fun\>()(e, s, d)</tt>. Then, this 184 /// function returns <tt>fusion::fold(seq, state0, fun(d))</tt>. 185 /// 186 /// \param e The current expression 187 /// \param s The current state 188 /// \param d An arbitrary data operator ()boost::proto::reverse_fold::impl189 result_type operator ()( 190 typename impl::expr_param e 191 , typename impl::state_param s 192 , typename impl::data_param d 193 ) const 194 { 195 typename when<_, Sequence>::template impl<Expr, State, Data> seq; 196 detail::as_callable<Fun, Data> f(d); 197 return fusion::reverse_fold( 198 seq(e, s, d) 199 , typename when<_, State0>::template impl<Expr, State, Data>()(e, s, d) 200 , f 201 ); 202 } 203 }; 204 }; 205 206 // This specialization is only for improved compile-time performance 207 // in the commom case when the Sequence transform is \c proto::_. 208 // 209 /// INTERNAL ONLY 210 /// 211 template<typename State0, typename Fun> 212 struct fold<_, State0, Fun> : transform<fold<_, State0, Fun> > 213 { 214 template<typename Expr, typename State, typename Data> 215 struct impl 216 : detail::fold_impl<State0, Fun, Expr, State, Data> 217 {}; 218 }; 219 220 // This specialization is only for improved compile-time performance 221 // in the commom case when the Sequence transform is \c proto::_. 222 // 223 /// INTERNAL ONLY 224 /// 225 template<typename State0, typename Fun> 226 struct reverse_fold<_, State0, Fun> : transform<reverse_fold<_, State0, Fun> > 227 { 228 template<typename Expr, typename State, typename Data> 229 struct impl 230 : detail::reverse_fold_impl<State0, Fun, Expr, State, Data> 231 {}; 232 }; 233 234 /// INTERNAL ONLY 235 /// 236 template<typename Sequence, typename State, typename Fun> 237 struct is_callable<fold<Sequence, State, Fun> > 238 : mpl::true_ 239 {}; 240 241 /// INTERNAL ONLY 242 /// 243 template<typename Sequence, typename State, typename Fun> 244 struct is_callable<reverse_fold<Sequence, State, Fun> > 245 : mpl::true_ 246 {}; 247 248 }} 249 250 #endif 251