|
1 // Boost Lambda Library -- loops.hpp ---------------------------------------- |
|
2 |
|
3 // Copyright (C) 1999, 2000 Jaakko Järvi (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 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 |