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
20namespace boost {
21namespace lambda {
22
23// -- loop control structure actions ----------------------
24
25class forloop_action {};
26class forloop_no_body_action {};
27class whileloop_action {};
28class whileloop_no_body_action {};
29class dowhileloop_action {};
30class dowhileloop_no_body_action {};
31
32
33// For loop
34template <class Arg1, class Arg2, class Arg3, class Arg4>
35inline const
36lambda_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>
43for_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.
57template <class Arg1, class Arg2, class Arg3>
58inline const
59lambda_functor<
60 lambda_functor_base<
61 forloop_no_body_action,
62 tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
63 >
64>
65for_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
78template <class Arg1, class Arg2>
79inline const
80lambda_functor<
81 lambda_functor_base<
82 whileloop_action,
83 tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
84 >
85>
86while_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.
96template <class Arg1>
97inline const
98lambda_functor<
99 lambda_functor_base<
100 whileloop_no_body_action,
101 tuple<lambda_functor<Arg1> >
102 >
103>
104while_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
115template <class Arg1, class Arg2>
116inline const
117lambda_functor<
118 lambda_functor_base<
119 dowhileloop_action,
120 tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
121 >
122>
123do_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.
133template <class Arg1>
134inline const
135lambda_functor<
136 lambda_functor_base<
137 dowhileloop_no_body_action,
138 tuple<lambda_functor<Arg1> >
139 >
140>
141do_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.
154template<class Args>
155class
156lambda_functor_base<forloop_action, Args> {
157public:
158 Args args;
159 template <class T> struct sig { typedef void type; };
160public:
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
174template<class Args>
175class
176lambda_functor_base<forloop_no_body_action, Args> {
177public:
178 Args args;
179 template <class T> struct sig { typedef void type; };
180public:
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.
193template<class Args>
194class
195lambda_functor_base<whileloop_action, Args> {
196public:
197 Args args;
198 template <class T> struct sig { typedef void type; };
199public:
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
211template<class Args>
212class
213lambda_functor_base<whileloop_no_body_action, Args> {
214public:
215 Args args;
216 template <class T> struct sig { typedef void type; };
217public:
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.
228template<class Args>
229class
230lambda_functor_base<dowhileloop_action, Args> {
231public:
232 Args args;
233 template <class T> struct sig { typedef void type; };
234public:
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
246template<class Args>
247class
248lambda_functor_base<dowhileloop_no_body_action, Args> {
249public:
250 Args args;
251 template <class T> struct sig { typedef void type; };
252public:
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///////////////////////////////////////////////////////////////////////////////
280template <typename CondT, typename DoT>
281struct 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//////////////////////////////////
303template <typename CondT>
304struct 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//////////////////////////////////
329template <typename CondT>
330inline while_gen<CondT>
331while_(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///////////////////////////////////////////////////////////////////////////////
355template <typename DoT, typename CondT>
356struct 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////////////////////////////////////
379template <typename DoT>
380struct 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////////////////////////////////////
405struct 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
415do_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///////////////////////////////////////////////////////////////////////////////
435template <typename InitT, typename CondT, typename StepT, typename DoT>
436struct 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//////////////////////////////////
460template <typename InitT, typename CondT, typename StepT>
461struct 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//////////////////////////////////
495template <typename InitT, typename CondT, typename StepT>
496inline for_gen<InitT, CondT, StepT>
497for_(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