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 >
for_loop(const lambda_functor<Arg1> & a1,const lambda_functor<Arg2> & a2,const lambda_functor<Arg3> & a3,const lambda_functor<Arg4> & a4)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 >
for_loop(const lambda_functor<Arg1> & a1,const lambda_functor<Arg2> & a2,const lambda_functor<Arg3> & a3)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 >
while_loop(const lambda_functor<Arg1> & a1,const lambda_functor<Arg2> & a2)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 >
while_loop(const lambda_functor<Arg1> & a1)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 >
do_while_loop(const lambda_functor<Arg1> & a1,const lambda_functor<Arg2> & a2)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 >
do_while_loop(const lambda_functor<Arg1> & a1)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:
lambda_functor_base(const Args & a)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:
lambda_functor_base(const Args & a)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:
lambda_functor_base(const Args & a)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:
lambda_functor_base(const Args & a)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:
lambda_functor_base(const Args & a)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:
lambda_functor_base(const Args & a)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 
while_compositeboost::lambda::while_composite288     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 
while_genboost::lambda::while_gen306     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> >
operator []boost::lambda::while_gen313     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>
while_(CondT const & cond)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 
do_compositeboost::lambda::do_composite363     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 
do_gen2boost::lambda::do_gen2382     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> >
while_boost::lambda::do_gen2389     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>
operator []boost::lambda::do_gen409     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 
for_compositeboost::lambda::for_composite441     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 
for_genboost::lambda::for_gen463     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> >
operator []boost::lambda::for_gen475     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>
for_(InitT const & init,CondT const & cond,StepT const & step)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