]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | { | |
31 | 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 | |
48 | 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 | |
127 | 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 | |
189 | 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 |