fold.hpp 8.4 KB

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