source: NonGTP/Boost/boost/lambda/detail/control_structures_impl.hpp @ 857

Revision 857, 16.1 KB checked in by igarcia, 18 years ago (diff)
Line 
1// Boost Lambda Library -- control_structures_impl.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//
6// Distributed under the Boost Software License, Version 1.0. (See
7// accompanying file LICENSE_1_0.txt or copy at
8// http://www.boost.org/LICENSE_1_0.txt)
9//
10// For more information, see www.boost.org
11
12// --------------------------------------------------------------------------
13
14#if !defined(BOOST_LAMBDA_CONTROL_CONSTRUCTS_HPP)
15#define BOOST_LAMBDA_CONTROL_CONSTRUCTS_HPP
16
17namespace boost {
18namespace lambda {
19
20// -- void return control actions ----------------------
21
22class forloop_action {};
23class forloop_no_body_action {};
24class ifthen_action {};
25class ifthenelse_action {};
26class whileloop_action {};
27class whileloop_no_body_action {};
28class dowhileloop_action {};
29class dowhileloop_no_body_action {};
30// -- nonvoid return control actions ----------------------
31
32class ifthenelsereturn_action {};
33
34// For loop
35template <class Arg1, class Arg2, class Arg3, class Arg4>
36inline const
37lambda_functor<
38  lambda_functor_base<
39    forloop_action,
40    tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
41          lambda_functor<Arg3>, lambda_functor<Arg4> >
42  >
43>
44for_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2,
45         const lambda_functor<Arg3>& a3, const lambda_functor<Arg4>& a4) {
46  return
47      lambda_functor_base<
48        forloop_action,
49        tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
50              lambda_functor<Arg3>, lambda_functor<Arg4> >
51      >
52    ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
53            lambda_functor<Arg3>, lambda_functor<Arg4> >(a1, a2, a3, a4)
54    );
55}
56
57// No body case.
58template <class Arg1, class Arg2, class Arg3>
59inline const
60lambda_functor<
61  lambda_functor_base<
62    forloop_no_body_action,
63    tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
64  >
65>
66for_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2,
67         const lambda_functor<Arg3>& a3) {
68  return
69      lambda_functor_base<
70        forloop_no_body_action,
71        tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
72              lambda_functor<Arg3> >
73      >
74      ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2>,
75               lambda_functor<Arg3> >(a1, a2, a3) );
76}
77
78// While loop
79template <class Arg1, class Arg2>
80inline const
81lambda_functor<
82  lambda_functor_base<
83    whileloop_action,
84    tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
85  >
86>
87while_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {
88  return
89      lambda_functor_base<
90        whileloop_action,
91        tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
92      >
93      ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2));
94}
95
96// No body case.
97template <class Arg1>
98inline const
99lambda_functor<
100  lambda_functor_base<
101    whileloop_no_body_action,
102    tuple<lambda_functor<Arg1> >
103  >
104>
105while_loop(const lambda_functor<Arg1>& a1) {
106  return
107      lambda_functor_base<
108        whileloop_no_body_action,
109        tuple<lambda_functor<Arg1> >
110      >
111      ( tuple<lambda_functor<Arg1> >(a1) );
112}
113
114
115// Do While loop
116template <class Arg1, class Arg2>
117inline const
118lambda_functor<
119  lambda_functor_base<
120    dowhileloop_action,
121    tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
122  >
123>
124do_while_loop(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {
125  return
126      lambda_functor_base<
127        dowhileloop_action,
128        tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
129      >
130      ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2));
131}
132
133// No body case.
134template <class Arg1>
135inline const
136lambda_functor<
137  lambda_functor_base<
138    dowhileloop_no_body_action,
139    tuple<lambda_functor<Arg1> >
140  >
141>
142do_while_loop(const lambda_functor<Arg1>& a1) {
143  return
144      lambda_functor_base<
145        dowhileloop_no_body_action,
146        tuple<lambda_functor<Arg1> >
147      >
148      ( tuple<lambda_functor<Arg1> >(a1));
149}
150
151
152// If Then
153template <class Arg1, class Arg2>
154inline const
155lambda_functor<
156  lambda_functor_base<
157    ifthen_action,
158    tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
159  >
160>
161if_then(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {
162  return
163    lambda_functor_base<
164      ifthen_action,
165      tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
166    >
167    ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2) );
168}
169
170// If then else
171
172template <class Arg1, class Arg2, class Arg3>
173inline const
174lambda_functor<
175  lambda_functor_base<
176    ifthenelse_action,
177    tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
178  >
179>
180if_then_else(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2,
181             const lambda_functor<Arg3>& a3) {
182  return
183    lambda_functor_base<
184      ifthenelse_action,
185      tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
186    >
187    (tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
188       (a1, a2, a3) );
189}
190
191// Our version of operator?:()
192
193template <class Arg1, class Arg2, class Arg3>
194inline const
195  lambda_functor<
196    lambda_functor_base<
197      other_action<ifthenelsereturn_action>,
198      tuple<lambda_functor<Arg1>,
199          typename const_copy_argument<Arg2>::type,
200          typename const_copy_argument<Arg3>::type>
201  >
202>
203if_then_else_return(const lambda_functor<Arg1>& a1,
204                    const Arg2 & a2,
205                    const Arg3 & a3) {
206  return
207      lambda_functor_base<
208        other_action<ifthenelsereturn_action>,
209        tuple<lambda_functor<Arg1>,
210              typename const_copy_argument<Arg2>::type,
211              typename const_copy_argument<Arg3>::type>
212      > ( tuple<lambda_functor<Arg1>,
213              typename const_copy_argument<Arg2>::type,
214              typename const_copy_argument<Arg3>::type> (a1, a2, a3) );
215}
216
217namespace detail {
218
219// return type specialization for conditional expression begins -----------
220// start reading below and move upwards
221
222// PHASE 6:1
223// check if A is conbertible to B and B to A
224template<int Phase, bool AtoB, bool BtoA, bool SameType, class A, class B>
225struct return_type_2_ifthenelsereturn;
226
227// if A can be converted to B and vice versa -> ambiguous
228template<int Phase, class A, class B>
229struct return_type_2_ifthenelsereturn<Phase, true, true, false, A, B> {
230  typedef
231    detail::return_type_deduction_failure<return_type_2_ifthenelsereturn> type;
232  // ambiguous type in conditional expression
233};
234// if A can be converted to B and vice versa and are of same type
235template<int Phase, class A, class B>
236struct return_type_2_ifthenelsereturn<Phase, true, true, true, A, B> {
237  typedef A type;
238};
239
240
241// A can be converted to B
242template<int Phase, class A, class B>
243struct return_type_2_ifthenelsereturn<Phase, true, false, false, A, B> {
244  typedef B type;
245};
246
247// B can be converted to A
248template<int Phase, class A, class B>
249struct return_type_2_ifthenelsereturn<Phase, false, true, false, A, B> {
250  typedef A type;
251};
252
253// neither can be converted. Then we drop the potential references, and
254// try again
255template<class A, class B>
256struct return_type_2_ifthenelsereturn<1, false, false, false, A, B> {
257  // it is safe to add const, since the result will be an rvalue and thus
258  // const anyway. The const are needed eg. if the types
259  // are 'const int*' and 'void *'. The remaining type should be 'const void*'
260  typedef const typename boost::remove_reference<A>::type plainA;
261  typedef const typename boost::remove_reference<B>::type plainB;
262  // TODO: Add support for volatile ?
263
264  typedef typename
265       return_type_2_ifthenelsereturn<
266         2,
267         boost::is_convertible<plainA,plainB>::value,
268         boost::is_convertible<plainB,plainA>::value,
269         boost::is_same<plainA,plainB>::value,
270         plainA,
271         plainB>::type type;
272};
273
274// PHASE 6:2
275template<class A, class B>
276struct return_type_2_ifthenelsereturn<2, false, false, false, A, B> {
277  typedef
278    detail::return_type_deduction_failure<return_type_2_ifthenelsereturn> type;
279  // types_do_not_match_in_conditional_expression
280};
281
282
283
284// PHASE 5: now we know that types are not arithmetic.
285template<class A, class B>
286struct non_numeric_types {
287  typedef typename
288    return_type_2_ifthenelsereturn<
289      1, // phase 1
290      is_convertible<A,B>::value,
291      is_convertible<B,A>::value,
292      is_same<A,B>::value,
293      A,
294      B>::type type;
295};
296
297// PHASE 4 :
298// the base case covers arithmetic types with differing promote codes
299// use the type deduction of arithmetic_actions
300template<int CodeA, int CodeB, class A, class B>
301struct arithmetic_or_not {
302  typedef typename
303    return_type_2<arithmetic_action<plus_action>, A, B>::type type;
304  // plus_action is just a random pick, has to be a concrete instance
305};
306
307// this case covers the case of artihmetic types with the same promote codes.
308// non numeric deduction is used since e.g. integral promotion is not
309// performed with operator ?:
310template<int CodeA, class A, class B>
311struct arithmetic_or_not<CodeA, CodeA, A, B> {
312  typedef typename non_numeric_types<A, B>::type type;
313};
314
315// if either A or B has promote code -1 it is not an arithmetic type
316template<class A, class B>
317struct arithmetic_or_not <-1, -1, A, B> {
318  typedef typename non_numeric_types<A, B>::type type;
319};
320template<int CodeB, class A, class B>
321struct arithmetic_or_not <-1, CodeB, A, B> {
322  typedef typename non_numeric_types<A, B>::type type;
323};
324template<int CodeA, class A, class B>
325struct arithmetic_or_not <CodeA, -1, A, B> {
326  typedef typename non_numeric_types<A, B>::type type;
327};
328
329
330
331
332// PHASE 3 : Are the types same?
333// No, check if they are arithmetic or not
334template <class A, class B>
335struct same_or_not {
336  typedef typename detail::remove_reference_and_cv<A>::type plainA;
337  typedef typename detail::remove_reference_and_cv<B>::type plainB;
338
339  typedef typename
340    arithmetic_or_not<
341      detail::promote_code<plainA>::value,
342      detail::promote_code<plainB>::value,
343      A,
344      B>::type type;
345};
346// Yes, clear.
347template <class A> struct same_or_not<A, A> {
348  typedef A type;
349};
350
351} // detail
352
353// PHASE 2 : Perform first the potential array_to_pointer conversion
354template<class A, class B>
355struct return_type_2<other_action<ifthenelsereturn_action>, A, B> {
356
357  typedef typename detail::array_to_pointer<A>::type A1;
358  typedef typename detail::array_to_pointer<B>::type B1;
359
360  typedef typename
361    boost::add_const<typename detail::same_or_not<A1, B1>::type>::type type;
362};
363
364// PHASE 1 : Deduction is based on the second and third operand
365
366
367// return type specialization for conditional expression ends -----------
368
369
370
371
372// Control loop lambda_functor_base specializations.
373
374// Specialization for for_loop.
375template<class Args>
376class
377lambda_functor_base<forloop_action, Args> {
378public:
379  Args args;
380  template <class T> struct sig { typedef void type; };
381public:
382  explicit lambda_functor_base(const Args& a) : args(a) {}
383
384  template<class RET, CALL_TEMPLATE_ARGS>
385  RET call(CALL_FORMAL_ARGS) const {
386    for(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS);
387        detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
388        detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS))
389     
390      detail::select(boost::tuples::get<3>(args), CALL_ACTUAL_ARGS);
391  }
392};
393
394// No body case
395template<class Args>
396class
397lambda_functor_base<forloop_no_body_action, Args> {
398public:
399  Args args;
400  template <class T> struct sig { typedef void type; };
401public:
402  explicit lambda_functor_base(const Args& a) : args(a) {}
403
404  template<class RET, CALL_TEMPLATE_ARGS>
405  RET call(CALL_FORMAL_ARGS) const {
406    for(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS);
407        detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
408        detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS)) {}
409   }
410};
411
412
413// Specialization for while_loop.
414template<class Args>
415class
416lambda_functor_base<whileloop_action, Args> {
417public:
418  Args args;
419  template <class T> struct sig { typedef void type; };
420public:
421  explicit lambda_functor_base(const Args& a) : args(a) {}
422
423  template<class RET, CALL_TEMPLATE_ARGS>
424  RET call(CALL_FORMAL_ARGS) const {
425    while(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS))
426     
427      detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
428  }
429};
430
431// No body case
432template<class Args>
433class
434lambda_functor_base<whileloop_no_body_action, Args> {
435public:
436  Args args;
437  template <class T> struct sig { typedef void type; };
438public:
439  explicit lambda_functor_base(const Args& a) : args(a) {}
440
441  template<class RET, CALL_TEMPLATE_ARGS>
442  RET call(CALL_FORMAL_ARGS) const {
443          while(detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) {}
444  }
445};
446
447// Specialization for do_while_loop.
448// Note that the first argument is the condition.
449template<class Args>
450class
451lambda_functor_base<dowhileloop_action, Args> {
452public:
453  Args args;
454  template <class T> struct sig { typedef void type; };
455public:
456  explicit lambda_functor_base(const Args& a) : args(a) {}
457
458  template<class RET, CALL_TEMPLATE_ARGS>
459  RET call(CALL_FORMAL_ARGS) const {
460    do {
461      detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);     
462    } while (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) );
463  }
464};
465
466// No body case
467template<class Args>
468class
469lambda_functor_base<dowhileloop_no_body_action, Args> {
470public:
471  Args args;
472  template <class T> struct sig { typedef void type; };
473public:
474  explicit lambda_functor_base(const Args& a) : args(a) {}
475
476  template<class RET, CALL_TEMPLATE_ARGS>
477  RET call(CALL_FORMAL_ARGS) const {
478          do {} while (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS) );
479  }
480};
481
482
483// Specialization for if_then.
484template<class Args>
485class
486lambda_functor_base<ifthen_action, Args> {
487public:
488  Args args;
489  template <class T> struct sig { typedef void type; };
490public:
491  explicit lambda_functor_base(const Args& a) : args(a) {}
492
493  template<class RET, CALL_TEMPLATE_ARGS>
494  RET call(CALL_FORMAL_ARGS) const {
495    if (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
496  }
497};
498
499// Specialization for if_then_else.
500template<class Args>
501class
502lambda_functor_base<ifthenelse_action, Args> {
503public:
504  Args args;
505  template <class T> struct sig { typedef void type; };
506public:
507  explicit lambda_functor_base(const Args& a) : args(a) {}
508
509  template<class RET, CALL_TEMPLATE_ARGS>
510  RET call(CALL_FORMAL_ARGS) const {
511    if (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS))
512      detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
513    else
514      detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS);
515  }
516};
517
518// Specialization of lambda_functor_base for if_then_else_return.
519template<class Args>
520class
521lambda_functor_base<other_action<ifthenelsereturn_action>, Args> {
522public:
523  Args args;
524
525  template <class SigArgs> struct sig {
526  private:
527    typedef typename detail::nth_return_type_sig<1, Args, SigArgs>::type ret1;
528    typedef typename detail::nth_return_type_sig<2, Args, SigArgs>::type ret2;
529  public:
530    typedef typename return_type_2<
531      other_action<ifthenelsereturn_action>, ret1, ret2
532    >::type type;
533  };
534
535public:
536  explicit lambda_functor_base(const Args& a) : args(a) {}
537
538  template<class RET, CALL_TEMPLATE_ARGS>
539  RET call(CALL_FORMAL_ARGS) const {
540    return (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) ?
541       detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS)
542    :
543       detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS);
544  }
545};
546
547} // lambda
548} // boost
549
550#endif // BOOST_LAMBDA_CONTROL_CONSTRUCTS_HPP
Note: See TracBrowser for help on using the repository browser.