4e9b60b7b9500b439ed8bf77f8afc8270954cbc3
[platform/upstream/boost.git] / boost / lambda / loops.hpp
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 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