1 | // Boost Lambda Library -- loops.hpp ---------------------------------------- |
2 | |
3 | // Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) |
4 | // Copyright (C) 2000 Gary Powell (powellg@amazon.com) |
5 | // Copyright (c) 2001-2002 Joel de Guzman |
6 | // |
7 | // Distributed under the Boost Software License, Version 1.0. (See |
8 | // accompanying file LICENSE_1_0.txt or copy at |
9 | // http://www.boost.org/LICENSE_1_0.txt) |
10 | // |
11 | // For more information, see www.boost.org |
12 | |
13 | // -------------------------------------------------------------------------- |
14 | |
15 | #if !defined(BOOST_LAMBDA_LOOPS_HPP) |
16 | #define BOOST_LAMBDA_LOOPS_HPP |
17 | |
18 | #include "boost/lambda/core.hpp" |
19 | |
20 | namespace boost { |
21 | namespace lambda { |
22 | |
23 | // -- loop control structure actions ---------------------- |
24 | |
25 | class forloop_action {}; |
26 | class forloop_no_body_action {}; |
27 | class whileloop_action {}; |
28 | class whileloop_no_body_action {}; |
29 | class dowhileloop_action {}; |
30 | class dowhileloop_no_body_action {}; |
31 | |
32 | |
33 | // For loop |
34 | template <class Arg1, class Arg2, class Arg3, class Arg4> |
35 | inline const |
36 | lambda_functor< |
37 | lambda_functor_base< |
38 | forloop_action, |
39 | tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, |
40 | lambda_functor<Arg3>, lambda_functor<Arg4> > |
41 | > |
42 | > |
43 | for_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2, |
44 | const lambda_functor<Arg3>& a3, const lambda_functor<Arg4>& a4) { |
45 | return |
46 | lambda_functor_base< |
47 | forloop_action, |
48 | tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, |
49 | lambda_functor<Arg3>, lambda_functor<Arg4> > |
50 | > |
51 | ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, |
52 | lambda_functor<Arg3>, lambda_functor<Arg4> >(a1, a2, a3, a4) |
53 | ); |
54 | } |
55 | |
56 | // No body case. |
57 | template <class Arg1, class Arg2, class Arg3> |
58 | inline const |
59 | lambda_functor< |
60 | lambda_functor_base< |
61 | forloop_no_body_action, |
62 | tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> > |
63 | > |
64 | > |
65 | for_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2, |
66 | const lambda_functor<Arg3>& a3) { |
67 | return |
68 | lambda_functor_base< |
69 | forloop_no_body_action, |
70 | tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, |
71 | lambda_functor<Arg3> > |
72 | > |
73 | ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, |
74 | lambda_functor<Arg3> >(a1, a2, a3) ); |
75 | } |
76 | |
77 | // While loop |
78 | template <class Arg1, class Arg2> |
79 | inline const |
80 | lambda_functor< |
81 | lambda_functor_base< |
82 | whileloop_action, |
83 | tuple<lambda_functor<Arg1>, lambda_functor<Arg2> > |
84 | > |
85 | > |
86 | while_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) { |
87 | return |
88 | lambda_functor_base< |
89 | whileloop_action, |
90 | tuple<lambda_functor<Arg1>, lambda_functor<Arg2> > |
91 | > |
92 | ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2)); |
93 | } |
94 | |
95 | // No body case. |
96 | template <class Arg1> |
97 | inline const |
98 | lambda_functor< |
99 | lambda_functor_base< |
100 | whileloop_no_body_action, |
101 | tuple<lambda_functor<Arg1> > |
102 | > |
103 | > |
104 | while_loop(const lambda_functor<Arg1>& a1) { |
105 | return |
106 | lambda_functor_base< |
107 | whileloop_no_body_action, |
108 | tuple<lambda_functor<Arg1> > |
109 | > |
110 | ( tuple<lambda_functor<Arg1> >(a1) ); |
111 | } |
112 | |
113 | |
114 | // Do While loop |
115 | template <class Arg1, class Arg2> |
116 | inline const |
117 | lambda_functor< |
118 | lambda_functor_base< |
119 | dowhileloop_action, |
120 | tuple<lambda_functor<Arg1>, lambda_functor<Arg2> > |
121 | > |
122 | > |
123 | do_while_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) { |
124 | return |
125 | lambda_functor_base< |
126 | dowhileloop_action, |
127 | tuple<lambda_functor<Arg1>, lambda_functor<Arg2> > |
128 | > |
129 | ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2)); |
130 | } |
131 | |
132 | // No body case. |
133 | template <class Arg1> |
134 | inline const |
135 | lambda_functor< |
136 | lambda_functor_base< |
137 | dowhileloop_no_body_action, |
138 | tuple<lambda_functor<Arg1> > |
139 | > |
140 | > |
141 | do_while_loop(const lambda_functor<Arg1>& a1) { |
142 | return |
143 | lambda_functor_base< |
144 | dowhileloop_no_body_action, |
145 | tuple<lambda_functor<Arg1> > |
146 | > |
147 | ( tuple<lambda_functor<Arg1> >(a1)); |
148 | } |
149 | |
150 | |
151 | // Control loop lambda_functor_base specializations. |
152 | |
153 | // Specialization for for_loop. |
154 | template<class Args> |
155 | class |
156 | lambda_functor_base<forloop_action, Args> { |
157 | public: |
158 | Args args; |
159 | template <class T> struct sig { typedef void type; }; |
160 | public: |
161 | explicit lambda_functor_base(const Args& a) : args(a) {} |
162 | |
163 | template<class RET, CALL_TEMPLATE_ARGS> |
164 | RET call(CALL_FORMAL_ARGS) const { |
165 | for(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS); |
166 | detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); |
167 | detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS)) |
168 | |
169 | detail::select(boost::tuples::get<3>(args), CALL_ACTUAL_ARGS); |
170 | } |
171 | }; |
172 | |
173 | // No body case |
174 | template<class Args> |
175 | class |
176 | lambda_functor_base<forloop_no_body_action, Args> { |
177 | public: |
178 | Args args; |
179 | template <class T> struct sig { typedef void type; }; |
180 | public: |
181 | explicit lambda_functor_base(const Args& a) : args(a) {} |
182 | |
183 | template<class RET, CALL_TEMPLATE_ARGS> |
184 | RET call(CALL_FORMAL_ARGS) const { |
185 | for(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS); |
186 | detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); |
187 | detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS)) {} |
188 | } |
189 | }; |
190 | |
191 | |
192 | // Specialization for while_loop. |
193 | template<class Args> |
194 | class |
195 | lambda_functor_base<whileloop_action, Args> { |
196 | public: |
197 | Args args; |
198 | template <class T> struct sig { typedef void type; }; |
199 | public: |
200 | explicit lambda_functor_base(const Args& a) : args(a) {} |
201 | |
202 | template<class RET, CALL_TEMPLATE_ARGS> |
203 | RET call(CALL_FORMAL_ARGS) const { |
204 | while(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) |
205 | |
206 | detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); |
207 | } |
208 | }; |
209 | |
210 | // No body case |
211 | template<class Args> |
212 | class |
213 | lambda_functor_base<whileloop_no_body_action, Args> { |
214 | public: |
215 | Args args; |
216 | template <class T> struct sig { typedef void type; }; |
217 | public: |
218 | explicit lambda_functor_base(const Args& a) : args(a) {} |
219 | |
220 | template<class RET, CALL_TEMPLATE_ARGS> |
221 | RET call(CALL_FORMAL_ARGS) const { |
222 | while(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) {} |
223 | } |
224 | }; |
225 | |
226 | // Specialization for do_while_loop. |
227 | // Note that the first argument is the condition. |
228 | template<class Args> |
229 | class |
230 | lambda_functor_base<dowhileloop_action, Args> { |
231 | public: |
232 | Args args; |
233 | template <class T> struct sig { typedef void type; }; |
234 | public: |
235 | explicit lambda_functor_base(const Args& a) : args(a) {} |
236 | |
237 | template<class RET, CALL_TEMPLATE_ARGS> |
238 | RET call(CALL_FORMAL_ARGS) const { |
239 | do { |
240 | detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); |
241 | } while (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) ); |
242 | } |
243 | }; |
244 | |
245 | // No body case |
246 | template<class Args> |
247 | class |
248 | lambda_functor_base<dowhileloop_no_body_action, Args> { |
249 | public: |
250 | Args args; |
251 | template <class T> struct sig { typedef void type; }; |
252 | public: |
253 | explicit lambda_functor_base(const Args& a) : args(a) {} |
254 | |
255 | template<class RET, CALL_TEMPLATE_ARGS> |
256 | RET call(CALL_FORMAL_ARGS) const { |
257 | do {} while (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) ); |
258 | } |
259 | }; |
260 | |
261 | // The code below is from Joel de Guzman, some name changes etc. |
262 | // has been made. |
263 | |
264 | /////////////////////////////////////////////////////////////////////////////// |
265 | // |
266 | // while_composite |
267 | // |
268 | // This composite has the form: |
269 | // |
270 | // while_(condition) |
271 | // [ |
272 | // statement |
273 | // ] |
274 | // |
275 | // While the condition (an lambda_functor) evaluates to true, statement |
276 | // (another lambda_functor) is executed. The result type of this is void. |
277 | // Note the trailing underscore after while_. |
278 | // |
279 | /////////////////////////////////////////////////////////////////////////////// |
280 | template <typename CondT, typename DoT> |
281 | struct while_composite { |
282 | |
283 | typedef while_composite<CondT, DoT> self_t; |
284 | |
285 | template <class SigArgs> |
286 | struct sig { typedef void type; }; |
287 | |
288 | while_composite(CondT const& cond_, DoT const& do__) |
289 | : cond(cond_), do_(do__) {} |
290 | |
291 | template <class Ret, CALL_TEMPLATE_ARGS> |
292 | Ret call(CALL_FORMAL_ARGS) const |
293 | { |
294 | while (cond.internal_call(CALL_ACTUAL_ARGS)) |
295 | do_.internal_call(CALL_ACTUAL_ARGS); |
296 | } |
297 | |
298 | CondT cond; |
299 | DoT do_; |
300 | }; |
301 | |
302 | ////////////////////////////////// |
303 | template <typename CondT> |
304 | struct while_gen { |
305 | |
306 | while_gen(CondT const& cond_) |
307 | : cond(cond_) {} |
308 | |
309 | template <typename DoT> |
310 | lambda_functor<while_composite< |
311 | typename as_lambda_functor<CondT>::type, |
312 | typename as_lambda_functor<DoT>::type> > |
313 | operator[](DoT const& do_) const |
314 | { |
315 | typedef while_composite< |
316 | typename as_lambda_functor<CondT>::type, |
317 | typename as_lambda_functor<DoT>::type> |
318 | result; |
319 | |
320 | return result( |
321 | to_lambda_functor(cond), |
322 | to_lambda_functor(do_)); |
323 | } |
324 | |
325 | CondT cond; |
326 | }; |
327 | |
328 | ////////////////////////////////// |
329 | template <typename CondT> |
330 | inline while_gen<CondT> |
331 | while_(CondT const& cond) |
332 | { |
333 | return while_gen<CondT>(cond); |
334 | } |
335 | |
336 | /////////////////////////////////////////////////////////////////////////////// |
337 | // |
338 | // do_composite |
339 | // |
340 | // This composite has the form: |
341 | // |
342 | // do_ |
343 | // [ |
344 | // statement |
345 | // ] |
346 | // .while_(condition) |
347 | // |
348 | // While the condition (an lambda_functor) evaluates to true, statement |
349 | // (another lambda_functor) is executed. The statement is executed at least |
350 | // once. The result type of this is void. Note the trailing |
351 | // underscore after do_ and the leading dot and the trailing |
352 | // underscore before and after .while_. |
353 | // |
354 | /////////////////////////////////////////////////////////////////////////////// |
355 | template <typename DoT, typename CondT> |
356 | struct do_composite { |
357 | |
358 | typedef do_composite<DoT, CondT> self_t; |
359 | |
360 | template <class SigArgs> |
361 | struct sig { typedef void type; }; |
362 | |
363 | do_composite(DoT const& do__, CondT const& cond_) |
364 | : do_(do__), cond(cond_) {} |
365 | |
366 | template <class Ret, CALL_TEMPLATE_ARGS> |
367 | Ret call(CALL_FORMAL_ARGS) const |
368 | { |
369 | do |
370 | do_.internal_call(CALL_ACTUAL_ARGS); |
371 | while (cond.internal_call(CALL_ACTUAL_ARGS)); |
372 | } |
373 | |
374 | DoT do_; |
375 | CondT cond; |
376 | }; |
377 | |
378 | //////////////////////////////////// |
379 | template <typename DoT> |
380 | struct do_gen2 { |
381 | |
382 | do_gen2(DoT const& do__) |
383 | : do_(do__) {} |
384 | |
385 | template <typename CondT> |
386 | lambda_functor<do_composite< |
387 | typename as_lambda_functor<DoT>::type, |
388 | typename as_lambda_functor<CondT>::type> > |
389 | while_(CondT const& cond) const |
390 | { |
391 | typedef do_composite< |
392 | typename as_lambda_functor<DoT>::type, |
393 | typename as_lambda_functor<CondT>::type> |
394 | result; |
395 | |
396 | return result( |
397 | to_lambda_functor(do_), |
398 | to_lambda_functor(cond)); |
399 | } |
400 | |
401 | DoT do_; |
402 | }; |
403 | |
404 | //////////////////////////////////// |
405 | struct do_gen { |
406 | |
407 | template <typename DoT> |
408 | do_gen2<DoT> |
409 | operator[](DoT const& do_) const |
410 | { |
411 | return do_gen2<DoT>(do_); |
412 | } |
413 | }; |
414 | |
415 | do_gen const do_ = do_gen(); |
416 | |
417 | /////////////////////////////////////////////////////////////////////////////// |
418 | // |
419 | // for_composite |
420 | // |
421 | // This statement has the form: |
422 | // |
423 | // for_(init, condition, step) |
424 | // [ |
425 | // statement |
426 | // ] |
427 | // |
428 | // Where init, condition, step and statement are all lambda_functors. init |
429 | // is executed once before entering the for-loop. The for-loop |
430 | // exits once condition evaluates to false. At each loop iteration, |
431 | // step and statement is called. The result of this statement is |
432 | // void. Note the trailing underscore after for_. |
433 | // |
434 | /////////////////////////////////////////////////////////////////////////////// |
435 | template <typename InitT, typename CondT, typename StepT, typename DoT> |
436 | struct for_composite { |
437 | |
438 | template <class SigArgs> |
439 | struct sig { typedef void type; }; |
440 | |
441 | for_composite( |
442 | InitT const& init_, |
443 | CondT const& cond_, |
444 | StepT const& step_, |
445 | DoT const& do__) |
446 | : init(init_), cond(cond_), step(step_), do_(do__) {} |
447 | |
448 | template <class Ret, CALL_TEMPLATE_ARGS> |
449 | Ret |
450 | call(CALL_FORMAL_ARGS) const |
451 | { |
452 | for (init.internal_call(CALL_ACTUAL_ARGS); cond.internal_call(CALL_ACTUAL_ARGS); step.internal_call(CALL_ACTUAL_ARGS)) |
453 | do_.internal_call(CALL_ACTUAL_ARGS); |
454 | } |
455 | |
456 | InitT init; CondT cond; StepT step; DoT do_; // lambda_functors |
457 | }; |
458 | |
459 | ////////////////////////////////// |
460 | template <typename InitT, typename CondT, typename StepT> |
461 | struct for_gen { |
462 | |
463 | for_gen( |
464 | InitT const& init_, |
465 | CondT const& cond_, |
466 | StepT const& step_) |
467 | : init(init_), cond(cond_), step(step_) {} |
468 | |
469 | template <typename DoT> |
470 | lambda_functor<for_composite< |
471 | typename as_lambda_functor<InitT>::type, |
472 | typename as_lambda_functor<CondT>::type, |
473 | typename as_lambda_functor<StepT>::type, |
474 | typename as_lambda_functor<DoT>::type> > |
475 | operator[](DoT const& do_) const |
476 | { |
477 | typedef for_composite< |
478 | typename as_lambda_functor<InitT>::type, |
479 | typename as_lambda_functor<CondT>::type, |
480 | typename as_lambda_functor<StepT>::type, |
481 | typename as_lambda_functor<DoT>::type> |
482 | result; |
483 | |
484 | return result( |
485 | to_lambda_functor(init), |
486 | to_lambda_functor(cond), |
487 | to_lambda_functor(step), |
488 | to_lambda_functor(do_)); |
489 | } |
490 | |
491 | InitT init; CondT cond; StepT step; |
492 | }; |
493 | |
494 | ////////////////////////////////// |
495 | template <typename InitT, typename CondT, typename StepT> |
496 | inline for_gen<InitT, CondT, StepT> |
497 | for_(InitT const& init, CondT const& cond, StepT const& step) |
498 | { |
499 | return for_gen<InitT, CondT, StepT>(init, cond, step); |
500 | } |
501 | |
502 | } // lambda |
503 | } // boost |
504 | |
505 | #endif // BOOST_LAMBDA_LOOPS_HPP |
506 | |