ossrv_pub/boost_apis/boost/lambda/if.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // Boost Lambda Library -- if.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 // 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_IF_HPP)
       
    16 #define BOOST_LAMBDA_IF_HPP
       
    17 
       
    18 #include "boost/lambda/core.hpp"
       
    19 
       
    20 // Arithmetic type promotion needed for if_then_else_return
       
    21 #include "boost/lambda/detail/operator_actions.hpp"
       
    22 #include "boost/lambda/detail/operator_return_type_traits.hpp"
       
    23 
       
    24 namespace boost { 
       
    25 namespace lambda {
       
    26 
       
    27 // -- if control construct actions ----------------------
       
    28 
       
    29 class ifthen_action {};
       
    30 class ifthenelse_action {};
       
    31 class ifthenelsereturn_action {};
       
    32 
       
    33 // Specialization for if_then.
       
    34 template<class Args>
       
    35 class 
       
    36 lambda_functor_base<ifthen_action, Args> {
       
    37 public:
       
    38   Args args;
       
    39   template <class T> struct sig { typedef void type; };
       
    40 public:
       
    41   explicit lambda_functor_base(const Args& a) : args(a) {}
       
    42 
       
    43   template<class RET, CALL_TEMPLATE_ARGS>
       
    44   RET call(CALL_FORMAL_ARGS) const {
       
    45     if (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) 
       
    46       detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); 
       
    47   }
       
    48 };
       
    49 
       
    50 // If Then
       
    51 template <class Arg1, class Arg2>
       
    52 inline const 
       
    53 lambda_functor<
       
    54   lambda_functor_base<
       
    55     ifthen_action, 
       
    56     tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
       
    57   > 
       
    58 >
       
    59 if_then(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {
       
    60   return 
       
    61     lambda_functor_base<
       
    62       ifthen_action, 
       
    63       tuple<lambda_functor<Arg1>, lambda_functor<Arg2> > 
       
    64     > 
       
    65     ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2) );
       
    66 }
       
    67 
       
    68 
       
    69 // Specialization for if_then_else.
       
    70 template<class Args>
       
    71 class 
       
    72 lambda_functor_base<ifthenelse_action, Args> {
       
    73 public:
       
    74   Args args;
       
    75   template <class T> struct sig { typedef void type; };
       
    76 public:
       
    77   explicit lambda_functor_base(const Args& a) : args(a) {}
       
    78 
       
    79   template<class RET, CALL_TEMPLATE_ARGS>
       
    80   RET call(CALL_FORMAL_ARGS) const {
       
    81     if (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) 
       
    82       detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS); 
       
    83     else 
       
    84       detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS);
       
    85   }
       
    86 };
       
    87 
       
    88 
       
    89 
       
    90 // If then else
       
    91 
       
    92 template <class Arg1, class Arg2, class Arg3>
       
    93 inline const 
       
    94 lambda_functor<
       
    95   lambda_functor_base<
       
    96     ifthenelse_action, 
       
    97     tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
       
    98   > 
       
    99 >
       
   100 if_then_else(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2, 
       
   101              const lambda_functor<Arg3>& a3) {
       
   102   return 
       
   103     lambda_functor_base<
       
   104       ifthenelse_action, 
       
   105       tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
       
   106     > 
       
   107     (tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
       
   108        (a1, a2, a3) );
       
   109 }
       
   110 
       
   111 // Our version of operator?:()
       
   112 
       
   113 template <class Arg1, class Arg2, class Arg3>
       
   114 inline const 
       
   115   lambda_functor<
       
   116     lambda_functor_base<
       
   117       other_action<ifthenelsereturn_action>, 
       
   118       tuple<lambda_functor<Arg1>,
       
   119           typename const_copy_argument<Arg2>::type,
       
   120           typename const_copy_argument<Arg3>::type>
       
   121   > 
       
   122 >
       
   123 if_then_else_return(const lambda_functor<Arg1>& a1, 
       
   124                     const Arg2 & a2, 
       
   125                     const Arg3 & a3) {
       
   126   return 
       
   127       lambda_functor_base<
       
   128         other_action<ifthenelsereturn_action>, 
       
   129         tuple<lambda_functor<Arg1>,
       
   130               typename const_copy_argument<Arg2>::type,
       
   131               typename const_copy_argument<Arg3>::type>
       
   132       > ( tuple<lambda_functor<Arg1>,
       
   133               typename const_copy_argument<Arg2>::type,
       
   134               typename const_copy_argument<Arg3>::type> (a1, a2, a3) );
       
   135 }
       
   136 
       
   137 namespace detail {
       
   138 
       
   139 // return type specialization for conditional expression begins -----------
       
   140 // start reading below and move upwards
       
   141 
       
   142 // PHASE 6:1 
       
   143 // check if A is conbertible to B and B to A
       
   144 template<int Phase, bool AtoB, bool BtoA, bool SameType, class A, class B>
       
   145 struct return_type_2_ifthenelsereturn;
       
   146 
       
   147 // if A can be converted to B and vice versa -> ambiguous
       
   148 template<int Phase, class A, class B>
       
   149 struct return_type_2_ifthenelsereturn<Phase, true, true, false, A, B> {
       
   150   typedef 
       
   151     detail::return_type_deduction_failure<return_type_2_ifthenelsereturn> type;
       
   152   // ambiguous type in conditional expression
       
   153 };
       
   154 // if A can be converted to B and vice versa and are of same type
       
   155 template<int Phase, class A, class B>
       
   156 struct return_type_2_ifthenelsereturn<Phase, true, true, true, A, B> {
       
   157   typedef A type;
       
   158 };
       
   159 
       
   160 
       
   161 // A can be converted to B
       
   162 template<int Phase, class A, class B>
       
   163 struct return_type_2_ifthenelsereturn<Phase, true, false, false, A, B> {
       
   164   typedef B type;
       
   165 };
       
   166 
       
   167 // B can be converted to A
       
   168 template<int Phase, class A, class B>
       
   169 struct return_type_2_ifthenelsereturn<Phase, false, true, false, A, B> {
       
   170   typedef A type;
       
   171 };
       
   172 
       
   173 // neither can be converted. Then we drop the potential references, and
       
   174 // try again
       
   175 template<class A, class B>
       
   176 struct return_type_2_ifthenelsereturn<1, false, false, false, A, B> {
       
   177   // it is safe to add const, since the result will be an rvalue and thus
       
   178   // const anyway. The const are needed eg. if the types 
       
   179   // are 'const int*' and 'void *'. The remaining type should be 'const void*'
       
   180   typedef const typename boost::remove_reference<A>::type plainA; 
       
   181   typedef const typename boost::remove_reference<B>::type plainB; 
       
   182   // TODO: Add support for volatile ?
       
   183 
       
   184   typedef typename
       
   185        return_type_2_ifthenelsereturn<
       
   186          2,
       
   187          boost::is_convertible<plainA,plainB>::value, 
       
   188          boost::is_convertible<plainB,plainA>::value,
       
   189          boost::is_same<plainA,plainB>::value,
       
   190          plainA, 
       
   191          plainB>::type type;
       
   192 };
       
   193 
       
   194 // PHASE 6:2
       
   195 template<class A, class B>
       
   196 struct return_type_2_ifthenelsereturn<2, false, false, false, A, B> {
       
   197   typedef 
       
   198     detail::return_type_deduction_failure<return_type_2_ifthenelsereturn> type;
       
   199   // types_do_not_match_in_conditional_expression 
       
   200 };
       
   201 
       
   202 
       
   203 
       
   204 // PHASE 5: now we know that types are not arithmetic.
       
   205 template<class A, class B>
       
   206 struct non_numeric_types {
       
   207   typedef typename 
       
   208     return_type_2_ifthenelsereturn<
       
   209       1, // phase 1 
       
   210       is_convertible<A,B>::value, 
       
   211       is_convertible<B,A>::value, 
       
   212       is_same<A,B>::value,
       
   213       A, 
       
   214       B>::type type;
       
   215 };
       
   216 
       
   217 // PHASE 4 : 
       
   218 // the base case covers arithmetic types with differing promote codes
       
   219 // use the type deduction of arithmetic_actions
       
   220 template<int CodeA, int CodeB, class A, class B>
       
   221 struct arithmetic_or_not {
       
   222   typedef typename
       
   223     return_type_2<arithmetic_action<plus_action>, A, B>::type type; 
       
   224   // plus_action is just a random pick, has to be a concrete instance
       
   225 };
       
   226 
       
   227 // this case covers the case of artihmetic types with the same promote codes. 
       
   228 // non numeric deduction is used since e.g. integral promotion is not 
       
   229 // performed with operator ?: 
       
   230 template<int CodeA, class A, class B>
       
   231 struct arithmetic_or_not<CodeA, CodeA, A, B> {
       
   232   typedef typename non_numeric_types<A, B>::type type; 
       
   233 };
       
   234 
       
   235 // if either A or B has promote code -1 it is not an arithmetic type
       
   236 template<class A, class B>
       
   237 struct arithmetic_or_not <-1, -1, A, B> {
       
   238   typedef typename non_numeric_types<A, B>::type type;
       
   239 };
       
   240 template<int CodeB, class A, class B>
       
   241 struct arithmetic_or_not <-1, CodeB, A, B> {
       
   242   typedef typename non_numeric_types<A, B>::type type;
       
   243 };
       
   244 template<int CodeA, class A, class B>
       
   245 struct arithmetic_or_not <CodeA, -1, A, B> {
       
   246   typedef typename non_numeric_types<A, B>::type type;
       
   247 };
       
   248 
       
   249 
       
   250 
       
   251 
       
   252 // PHASE 3 : Are the types same?
       
   253 // No, check if they are arithmetic or not
       
   254 template <class A, class B>
       
   255 struct same_or_not {
       
   256   typedef typename detail::remove_reference_and_cv<A>::type plainA;
       
   257   typedef typename detail::remove_reference_and_cv<B>::type plainB;
       
   258 
       
   259   typedef typename 
       
   260     arithmetic_or_not<
       
   261       detail::promote_code<plainA>::value, 
       
   262       detail::promote_code<plainB>::value, 
       
   263       A, 
       
   264       B>::type type;
       
   265 };
       
   266 // Yes, clear.
       
   267 template <class A> struct same_or_not<A, A> {
       
   268   typedef A type;
       
   269 };
       
   270 
       
   271 } // detail
       
   272 
       
   273 // PHASE 2 : Perform first the potential array_to_pointer conversion 
       
   274 template<class A, class B>
       
   275 struct return_type_2<other_action<ifthenelsereturn_action>, A, B> { 
       
   276 
       
   277   typedef typename detail::array_to_pointer<A>::type A1;
       
   278   typedef typename detail::array_to_pointer<B>::type B1;
       
   279 
       
   280   typedef typename 
       
   281     boost::add_const<typename detail::same_or_not<A1, B1>::type>::type type;
       
   282 };
       
   283 
       
   284 // PHASE 1 : Deduction is based on the second and third operand
       
   285 
       
   286 
       
   287 // return type specialization for conditional expression ends -----------
       
   288 
       
   289 
       
   290 // Specialization of lambda_functor_base for if_then_else_return.
       
   291 template<class Args>
       
   292 class 
       
   293 lambda_functor_base<other_action<ifthenelsereturn_action>, Args> {
       
   294 public:
       
   295   Args args;
       
   296 
       
   297   template <class SigArgs> struct sig {
       
   298   private:
       
   299     typedef typename detail::nth_return_type_sig<1, Args, SigArgs>::type ret1;
       
   300     typedef typename detail::nth_return_type_sig<2, Args, SigArgs>::type ret2;
       
   301   public:
       
   302     typedef typename return_type_2<
       
   303       other_action<ifthenelsereturn_action>, ret1, ret2
       
   304     >::type type;
       
   305   };
       
   306 
       
   307 public:
       
   308   explicit lambda_functor_base(const Args& a) : args(a) {}
       
   309 
       
   310   template<class RET, CALL_TEMPLATE_ARGS>
       
   311   RET call(CALL_FORMAL_ARGS) const {
       
   312     return (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) ?
       
   313        detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS) 
       
   314     : 
       
   315        detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS);
       
   316   }
       
   317 };
       
   318 
       
   319   // The code below is from Joel de Guzman, some name changes etc. 
       
   320   // has been made.
       
   321 
       
   322 ///////////////////////////////////////////////////////////////////////////////
       
   323 //
       
   324 //  if_then_else_composite
       
   325 //
       
   326 //      This composite has two (2) forms:
       
   327 //
       
   328 //          if_(condition)
       
   329 //          [
       
   330 //              statement
       
   331 //          ]
       
   332 //
       
   333 //      and
       
   334 //
       
   335 //          if_(condition)
       
   336 //          [
       
   337 //              true_statement
       
   338 //          ]
       
   339 //          .else_
       
   340 //          [
       
   341 //              false_statement
       
   342 //          ]
       
   343 //
       
   344 //      where condition is an lambda_functor that evaluates to bool. If condition
       
   345 //      is true, the true_statement (again an lambda_functor) is executed
       
   346 //      otherwise, the false_statement (another lambda_functor) is executed. The
       
   347 //      result type of this is void. Note the trailing underscore after
       
   348 //      if_ and the the leading dot and the trailing underscore before
       
   349 //      and after .else_.
       
   350 //
       
   351 ///////////////////////////////////////////////////////////////////////////////
       
   352 template <typename CondT, typename ThenT, typename ElseT>
       
   353 struct if_then_else_composite {
       
   354 
       
   355     typedef if_then_else_composite<CondT, ThenT, ElseT> self_t;
       
   356 
       
   357     template <class SigArgs>
       
   358     struct sig { typedef void type; };
       
   359 
       
   360     if_then_else_composite(
       
   361         CondT const& cond_,
       
   362         ThenT const& then_,
       
   363         ElseT const& else__)
       
   364     :   cond(cond_), then(then_), else_(else__) {}
       
   365 
       
   366     template <class Ret, CALL_TEMPLATE_ARGS>
       
   367     Ret call(CALL_FORMAL_ARGS) const
       
   368     {
       
   369         if (cond.internal_call(CALL_ACTUAL_ARGS))
       
   370             then.internal_call(CALL_ACTUAL_ARGS);
       
   371         else
       
   372             else_.internal_call(CALL_ACTUAL_ARGS);
       
   373     }
       
   374 
       
   375     CondT cond; ThenT then; ElseT else_; //  lambda_functors
       
   376 };
       
   377 
       
   378 //////////////////////////////////
       
   379 template <typename CondT, typename ThenT>
       
   380 struct else_gen {
       
   381 
       
   382     else_gen(CondT const& cond_, ThenT const& then_)
       
   383     :   cond(cond_), then(then_) {}
       
   384 
       
   385     template <typename ElseT>
       
   386     lambda_functor<if_then_else_composite<CondT, ThenT,
       
   387         typename as_lambda_functor<ElseT>::type> >
       
   388     operator[](ElseT const& else_)
       
   389     {
       
   390         typedef if_then_else_composite<CondT, ThenT,
       
   391             typename as_lambda_functor<ElseT>::type>
       
   392         result;
       
   393 
       
   394         return result(cond, then, to_lambda_functor(else_));
       
   395     }
       
   396 
       
   397     CondT cond; ThenT then;
       
   398 };
       
   399 
       
   400 //////////////////////////////////
       
   401 template <typename CondT, typename ThenT>
       
   402 struct if_then_composite {
       
   403 
       
   404     template <class SigArgs>
       
   405     struct sig { typedef void type; };
       
   406 
       
   407     if_then_composite(CondT const& cond_, ThenT const& then_)
       
   408     :   cond(cond_), then(then_), else_(cond, then) {}
       
   409 
       
   410     template <class Ret, CALL_TEMPLATE_ARGS>
       
   411     Ret call(CALL_FORMAL_ARGS) const
       
   412     {
       
   413       if (cond.internal_call(CALL_ACTUAL_ARGS))
       
   414             then.internal_call(CALL_ACTUAL_ARGS);
       
   415     }
       
   416 
       
   417     CondT cond; ThenT then; //  lambda_functors
       
   418     else_gen<CondT, ThenT> else_;
       
   419 };
       
   420 
       
   421 //////////////////////////////////
       
   422 template <typename CondT>
       
   423 struct if_gen {
       
   424 
       
   425     if_gen(CondT const& cond_)
       
   426     :   cond(cond_) {}
       
   427 
       
   428     template <typename ThenT>
       
   429     lambda_functor<if_then_composite<
       
   430         typename as_lambda_functor<CondT>::type,
       
   431         typename as_lambda_functor<ThenT>::type> >
       
   432     operator[](ThenT const& then) const
       
   433     {
       
   434         typedef if_then_composite<
       
   435             typename as_lambda_functor<CondT>::type,
       
   436             typename as_lambda_functor<ThenT>::type>
       
   437         result;
       
   438 
       
   439         return result(
       
   440             to_lambda_functor(cond),
       
   441             to_lambda_functor(then));
       
   442     }
       
   443 
       
   444     CondT cond;
       
   445 };
       
   446 
       
   447 //////////////////////////////////
       
   448 template <typename CondT>
       
   449 inline if_gen<CondT>
       
   450 if_(CondT const& cond)
       
   451 {
       
   452     return if_gen<CondT>(cond);
       
   453 }
       
   454 
       
   455 
       
   456 
       
   457 } // lambda
       
   458 } // boost
       
   459 
       
   460 #endif // BOOST_LAMBDA_IF_HPP
       
   461 
       
   462