Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:10

0001 // Boost Lambda Library -- if.hpp ------------------------------------------
0002 
0003 // Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
0004 // Copyright (C) 2000 Gary Powell (powellg@amazon.com)
0005 // Copyright (C) 2001-2002 Joel de Guzman
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See
0008 // accompanying file LICENSE_1_0.txt or copy at
0009 // http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 // For more information, see www.boost.org
0012 
0013 // --------------------------------------------------------------------------
0014 
0015 #if !defined(BOOST_LAMBDA_IF_HPP)
0016 #define BOOST_LAMBDA_IF_HPP
0017 
0018 #include "boost/lambda/core.hpp"
0019 
0020 // Arithmetic type promotion needed for if_then_else_return
0021 #include "boost/lambda/detail/operator_actions.hpp"
0022 #include "boost/lambda/detail/operator_return_type_traits.hpp"
0023 
0024 namespace boost { 
0025 namespace lambda {
0026 
0027 // -- if control construct actions ----------------------
0028 
0029 class ifthen_action {};
0030 class ifthenelse_action {};
0031 class ifthenelsereturn_action {};
0032 
0033 // Specialization for if_then.
0034 template<class Args>
0035 class 
0036 lambda_functor_base<ifthen_action, Args> {
0037 public:
0038   Args args;
0039   template <class T> struct sig { typedef void type; };
0040 public:
0041   explicit lambda_functor_base(const Args& a) : args(a) {}
0042 
0043   template<class RET, CALL_TEMPLATE_ARGS>
0044   RET call(CALL_FORMAL_ARGS) const {
0045     if (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) 
0046       detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); 
0047   }
0048 };
0049 
0050 // If Then
0051 template <class Arg1, class Arg2>
0052 inline const 
0053 lambda_functor<
0054   lambda_functor_base<
0055     ifthen_action, 
0056     tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
0057   > 
0058 >
0059 if_then(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {
0060   return 
0061     lambda_functor_base<
0062       ifthen_action, 
0063       tuple<lambda_functor<Arg1>, lambda_functor<Arg2> > 
0064     > 
0065     ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2) );
0066 }
0067 
0068 
0069 // Specialization for if_then_else.
0070 template<class Args>
0071 class 
0072 lambda_functor_base<ifthenelse_action, Args> {
0073 public:
0074   Args args;
0075   template <class T> struct sig { typedef void type; };
0076 public:
0077   explicit lambda_functor_base(const Args& a) : args(a) {}
0078 
0079   template<class RET, CALL_TEMPLATE_ARGS>
0080   RET call(CALL_FORMAL_ARGS) const {
0081     if (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) 
0082       detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); 
0083     else 
0084       detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS);
0085   }
0086 };
0087 
0088 
0089 
0090 // If then else
0091 
0092 template <class Arg1, class Arg2, class Arg3>
0093 inline const 
0094 lambda_functor<
0095   lambda_functor_base<
0096     ifthenelse_action, 
0097     tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
0098   > 
0099 >
0100 if_then_else(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2, 
0101              const lambda_functor<Arg3>& a3) {
0102   return 
0103     lambda_functor_base<
0104       ifthenelse_action, 
0105       tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
0106     > 
0107     (tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
0108        (a1, a2, a3) );
0109 }
0110 
0111 // Our version of operator?:()
0112 
0113 template <class Arg1, class Arg2, class Arg3>
0114 inline const 
0115   lambda_functor<
0116     lambda_functor_base<
0117       other_action<ifthenelsereturn_action>, 
0118       tuple<lambda_functor<Arg1>,
0119           typename const_copy_argument<Arg2>::type,
0120           typename const_copy_argument<Arg3>::type>
0121   > 
0122 >
0123 if_then_else_return(const lambda_functor<Arg1>& a1, 
0124                     const Arg2 & a2, 
0125                     const Arg3 & a3) {
0126   return 
0127       lambda_functor_base<
0128         other_action<ifthenelsereturn_action>, 
0129         tuple<lambda_functor<Arg1>,
0130               typename const_copy_argument<Arg2>::type,
0131               typename const_copy_argument<Arg3>::type>
0132       > ( tuple<lambda_functor<Arg1>,
0133               typename const_copy_argument<Arg2>::type,
0134               typename const_copy_argument<Arg3>::type> (a1, a2, a3) );
0135 }
0136 
0137 namespace detail {
0138 
0139 // return type specialization for conditional expression begins -----------
0140 // start reading below and move upwards
0141 
0142 // PHASE 6:1 
0143 // check if A is conbertible to B and B to A
0144 template<int Phase, bool AtoB, bool BtoA, bool SameType, class A, class B>
0145 struct return_type_2_ifthenelsereturn;
0146 
0147 // if A can be converted to B and vice versa -> ambiguous
0148 template<int Phase, class A, class B>
0149 struct return_type_2_ifthenelsereturn<Phase, true, true, false, A, B> {
0150   typedef 
0151     detail::return_type_deduction_failure<return_type_2_ifthenelsereturn> type;
0152   // ambiguous type in conditional expression
0153 };
0154 // if A can be converted to B and vice versa and are of same type
0155 template<int Phase, class A, class B>
0156 struct return_type_2_ifthenelsereturn<Phase, true, true, true, A, B> {
0157   typedef A type;
0158 };
0159 
0160 
0161 // A can be converted to B
0162 template<int Phase, class A, class B>
0163 struct return_type_2_ifthenelsereturn<Phase, true, false, false, A, B> {
0164   typedef B type;
0165 };
0166 
0167 // B can be converted to A
0168 template<int Phase, class A, class B>
0169 struct return_type_2_ifthenelsereturn<Phase, false, true, false, A, B> {
0170   typedef A type;
0171 };
0172 
0173 // neither can be converted. Then we drop the potential references, and
0174 // try again
0175 template<class A, class B>
0176 struct return_type_2_ifthenelsereturn<1, false, false, false, A, B> {
0177   // it is safe to add const, since the result will be an rvalue and thus
0178   // const anyway. The const are needed eg. if the types 
0179   // are 'const int*' and 'void *'. The remaining type should be 'const void*'
0180   typedef const typename boost::remove_reference<A>::type plainA; 
0181   typedef const typename boost::remove_reference<B>::type plainB; 
0182   // TODO: Add support for volatile ?
0183 
0184   typedef typename
0185        return_type_2_ifthenelsereturn<
0186          2,
0187          boost::is_convertible<plainA,plainB>::value, 
0188          boost::is_convertible<plainB,plainA>::value,
0189          boost::is_same<plainA,plainB>::value,
0190          plainA, 
0191          plainB>::type type;
0192 };
0193 
0194 // PHASE 6:2
0195 template<class A, class B>
0196 struct return_type_2_ifthenelsereturn<2, false, false, false, A, B> {
0197   typedef 
0198     detail::return_type_deduction_failure<return_type_2_ifthenelsereturn> type;
0199   // types_do_not_match_in_conditional_expression 
0200 };
0201 
0202 
0203 
0204 // PHASE 5: now we know that types are not arithmetic.
0205 template<class A, class B>
0206 struct non_numeric_types {
0207   typedef typename 
0208     return_type_2_ifthenelsereturn<
0209       1, // phase 1 
0210       is_convertible<A,B>::value, 
0211       is_convertible<B,A>::value, 
0212       is_same<A,B>::value,
0213       A, 
0214       B>::type type;
0215 };
0216 
0217 // PHASE 4 : 
0218 // the base case covers arithmetic types with differing promote codes
0219 // use the type deduction of arithmetic_actions
0220 template<int CodeA, int CodeB, class A, class B>
0221 struct arithmetic_or_not {
0222   typedef typename
0223     return_type_2<arithmetic_action<plus_action>, A, B>::type type; 
0224   // plus_action is just a random pick, has to be a concrete instance
0225 };
0226 
0227 // this case covers the case of artihmetic types with the same promote codes. 
0228 // non numeric deduction is used since e.g. integral promotion is not 
0229 // performed with operator ?: 
0230 template<int CodeA, class A, class B>
0231 struct arithmetic_or_not<CodeA, CodeA, A, B> {
0232   typedef typename non_numeric_types<A, B>::type type; 
0233 };
0234 
0235 // if either A or B has promote code -1 it is not an arithmetic type
0236 template<class A, class B>
0237 struct arithmetic_or_not <-1, -1, A, B> {
0238   typedef typename non_numeric_types<A, B>::type type;
0239 };
0240 template<int CodeB, class A, class B>
0241 struct arithmetic_or_not <-1, CodeB, A, B> {
0242   typedef typename non_numeric_types<A, B>::type type;
0243 };
0244 template<int CodeA, class A, class B>
0245 struct arithmetic_or_not <CodeA, -1, A, B> {
0246   typedef typename non_numeric_types<A, B>::type type;
0247 };
0248 
0249 
0250 
0251 
0252 // PHASE 3 : Are the types same?
0253 // No, check if they are arithmetic or not
0254 template <class A, class B>
0255 struct same_or_not {
0256   typedef typename detail::remove_reference_and_cv<A>::type plainA;
0257   typedef typename detail::remove_reference_and_cv<B>::type plainB;
0258 
0259   typedef typename 
0260     arithmetic_or_not<
0261       detail::promote_code<plainA>::value, 
0262       detail::promote_code<plainB>::value, 
0263       A, 
0264       B>::type type;
0265 };
0266 // Yes, clear.
0267 template <class A> struct same_or_not<A, A> {
0268   typedef A type;
0269 };
0270 
0271 } // detail
0272 
0273 // PHASE 2 : Perform first the potential array_to_pointer conversion 
0274 template<class A, class B>
0275 struct return_type_2<other_action<ifthenelsereturn_action>, A, B> { 
0276 
0277   typedef typename detail::array_to_pointer<A>::type A1;
0278   typedef typename detail::array_to_pointer<B>::type B1;
0279 
0280   typedef typename 
0281     boost::add_const<typename detail::same_or_not<A1, B1>::type>::type type;
0282 };
0283 
0284 // PHASE 1 : Deduction is based on the second and third operand
0285 
0286 
0287 // return type specialization for conditional expression ends -----------
0288 
0289 
0290 // Specialization of lambda_functor_base for if_then_else_return.
0291 template<class Args>
0292 class 
0293 lambda_functor_base<other_action<ifthenelsereturn_action>, Args> {
0294 public:
0295   Args args;
0296 
0297   template <class SigArgs> struct sig {
0298   private:
0299     typedef typename detail::nth_return_type_sig<1, Args, SigArgs>::type ret1;
0300     typedef typename detail::nth_return_type_sig<2, Args, SigArgs>::type ret2;
0301   public:
0302     typedef typename return_type_2<
0303       other_action<ifthenelsereturn_action>, ret1, ret2
0304     >::type type;
0305   };
0306 
0307 public:
0308   explicit lambda_functor_base(const Args& a) : args(a) {}
0309 
0310   template<class RET, CALL_TEMPLATE_ARGS>
0311   RET call(CALL_FORMAL_ARGS) const {
0312     return (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) ?
0313        detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS) 
0314     : 
0315        detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS);
0316   }
0317 };
0318 
0319   // The code below is from Joel de Guzman, some name changes etc. 
0320   // has been made.
0321 
0322 ///////////////////////////////////////////////////////////////////////////////
0323 //
0324 //  if_then_else_composite
0325 //
0326 //      This composite has two (2) forms:
0327 //
0328 //          if_(condition)
0329 //          [
0330 //              statement
0331 //          ]
0332 //
0333 //      and
0334 //
0335 //          if_(condition)
0336 //          [
0337 //              true_statement
0338 //          ]
0339 //          .else_
0340 //          [
0341 //              false_statement
0342 //          ]
0343 //
0344 //      where condition is an lambda_functor that evaluates to bool. If condition
0345 //      is true, the true_statement (again an lambda_functor) is executed
0346 //      otherwise, the false_statement (another lambda_functor) is executed. The
0347 //      result type of this is void. Note the trailing underscore after
0348 //      if_ and the leading dot and the trailing underscore before
0349 //      and after .else_.
0350 //
0351 ///////////////////////////////////////////////////////////////////////////////
0352 template <typename CondT, typename ThenT, typename ElseT>
0353 struct if_then_else_composite {
0354 
0355     typedef if_then_else_composite<CondT, ThenT, ElseT> self_t;
0356 
0357     template <class SigArgs>
0358     struct sig { typedef void type; };
0359 
0360     if_then_else_composite(
0361         CondT const& cond_,
0362         ThenT const& then_,
0363         ElseT const& else__)
0364     :   cond(cond_), then(then_), else_(else__) {}
0365 
0366     template <class Ret, CALL_TEMPLATE_ARGS>
0367     Ret call(CALL_FORMAL_ARGS) const
0368     {
0369         if (cond.internal_call(CALL_ACTUAL_ARGS))
0370             then.internal_call(CALL_ACTUAL_ARGS);
0371         else
0372             else_.internal_call(CALL_ACTUAL_ARGS);
0373     }
0374 
0375     CondT cond; ThenT then; ElseT else_; //  lambda_functors
0376 };
0377 
0378 //////////////////////////////////
0379 template <typename CondT, typename ThenT>
0380 struct else_gen {
0381 
0382     else_gen(CondT const& cond_, ThenT const& then_)
0383     :   cond(cond_), then(then_) {}
0384 
0385     template <typename ElseT>
0386     lambda_functor<if_then_else_composite<CondT, ThenT,
0387         typename as_lambda_functor<ElseT>::type> >
0388     operator[](ElseT const& else_)
0389     {
0390         typedef if_then_else_composite<CondT, ThenT,
0391             typename as_lambda_functor<ElseT>::type>
0392         result;
0393 
0394         return result(cond, then, to_lambda_functor(else_));
0395     }
0396 
0397     CondT cond; ThenT then;
0398 };
0399 
0400 //////////////////////////////////
0401 template <typename CondT, typename ThenT>
0402 struct if_then_composite {
0403 
0404     template <class SigArgs>
0405     struct sig { typedef void type; };
0406 
0407     if_then_composite(CondT const& cond_, ThenT const& then_)
0408     :   cond(cond_), then(then_), else_(cond, then) {}
0409 
0410     template <class Ret, CALL_TEMPLATE_ARGS>
0411     Ret call(CALL_FORMAL_ARGS) const
0412     {
0413       if (cond.internal_call(CALL_ACTUAL_ARGS))
0414             then.internal_call(CALL_ACTUAL_ARGS);
0415     }
0416 
0417     CondT cond; ThenT then; //  lambda_functors
0418     else_gen<CondT, ThenT> else_;
0419 };
0420 
0421 //////////////////////////////////
0422 template <typename CondT>
0423 struct if_gen {
0424 
0425     if_gen(CondT const& cond_)
0426     :   cond(cond_) {}
0427 
0428     template <typename ThenT>
0429     lambda_functor<if_then_composite<
0430         typename as_lambda_functor<CondT>::type,
0431         typename as_lambda_functor<ThenT>::type> >
0432     operator[](ThenT const& then) const
0433     {
0434         typedef if_then_composite<
0435             typename as_lambda_functor<CondT>::type,
0436             typename as_lambda_functor<ThenT>::type>
0437         result;
0438 
0439         return result(
0440             to_lambda_functor(cond),
0441             to_lambda_functor(then));
0442     }
0443 
0444     CondT cond;
0445 };
0446 
0447 //////////////////////////////////
0448 template <typename CondT>
0449 inline if_gen<CondT>
0450 if_(CondT const& cond)
0451 {
0452     return if_gen<CondT>(cond);
0453 }
0454 
0455 
0456 
0457 } // lambda
0458 } // boost
0459 
0460 #endif // BOOST_LAMBDA_IF_HPP
0461 
0462