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