1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/ossrv_pub/boost_apis/boost/lambda/if.hpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,462 @@
1.4 +// Boost Lambda Library -- if.hpp ------------------------------------------
1.5 +
1.6 +// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
1.7 +// Copyright (C) 2000 Gary Powell (powellg@amazon.com)
1.8 +// Copyright (C) 2001-2002 Joel de Guzman
1.9 +//
1.10 +// Distributed under the Boost Software License, Version 1.0. (See
1.11 +// accompanying file LICENSE_1_0.txt or copy at
1.12 +// http://www.boost.org/LICENSE_1_0.txt)
1.13 +//
1.14 +// For more information, see www.boost.org
1.15 +
1.16 +// --------------------------------------------------------------------------
1.17 +
1.18 +#if !defined(BOOST_LAMBDA_IF_HPP)
1.19 +#define BOOST_LAMBDA_IF_HPP
1.20 +
1.21 +#include "boost/lambda/core.hpp"
1.22 +
1.23 +// Arithmetic type promotion needed for if_then_else_return
1.24 +#include "boost/lambda/detail/operator_actions.hpp"
1.25 +#include "boost/lambda/detail/operator_return_type_traits.hpp"
1.26 +
1.27 +namespace boost {
1.28 +namespace lambda {
1.29 +
1.30 +// -- if control construct actions ----------------------
1.31 +
1.32 +class ifthen_action {};
1.33 +class ifthenelse_action {};
1.34 +class ifthenelsereturn_action {};
1.35 +
1.36 +// Specialization for if_then.
1.37 +template<class Args>
1.38 +class
1.39 +lambda_functor_base<ifthen_action, Args> {
1.40 +public:
1.41 + Args args;
1.42 + template <class T> struct sig { typedef void type; };
1.43 +public:
1.44 + explicit lambda_functor_base(const Args& a) : args(a) {}
1.45 +
1.46 + template<class RET, CALL_TEMPLATE_ARGS>
1.47 + RET call(CALL_FORMAL_ARGS) const {
1.48 + if (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS))
1.49 + detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
1.50 + }
1.51 +};
1.52 +
1.53 +// If Then
1.54 +template <class Arg1, class Arg2>
1.55 +inline const
1.56 +lambda_functor<
1.57 + lambda_functor_base<
1.58 + ifthen_action,
1.59 + tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
1.60 + >
1.61 +>
1.62 +if_then(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2) {
1.63 + return
1.64 + lambda_functor_base<
1.65 + ifthen_action,
1.66 + tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >
1.67 + >
1.68 + ( tuple<lambda_functor<Arg1>, lambda_functor<Arg2> >(a1, a2) );
1.69 +}
1.70 +
1.71 +
1.72 +// Specialization for if_then_else.
1.73 +template<class Args>
1.74 +class
1.75 +lambda_functor_base<ifthenelse_action, Args> {
1.76 +public:
1.77 + Args args;
1.78 + template <class T> struct sig { typedef void type; };
1.79 +public:
1.80 + explicit lambda_functor_base(const Args& a) : args(a) {}
1.81 +
1.82 + template<class RET, CALL_TEMPLATE_ARGS>
1.83 + RET call(CALL_FORMAL_ARGS) const {
1.84 + if (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS))
1.85 + detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS);
1.86 + else
1.87 + detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS);
1.88 + }
1.89 +};
1.90 +
1.91 +
1.92 +
1.93 +// If then else
1.94 +
1.95 +template <class Arg1, class Arg2, class Arg3>
1.96 +inline const
1.97 +lambda_functor<
1.98 + lambda_functor_base<
1.99 + ifthenelse_action,
1.100 + tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
1.101 + >
1.102 +>
1.103 +if_then_else(const lambda_functor<Arg1>& a1, const lambda_functor<Arg2>& a2,
1.104 + const lambda_functor<Arg3>& a3) {
1.105 + return
1.106 + lambda_functor_base<
1.107 + ifthenelse_action,
1.108 + tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
1.109 + >
1.110 + (tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> >
1.111 + (a1, a2, a3) );
1.112 +}
1.113 +
1.114 +// Our version of operator?:()
1.115 +
1.116 +template <class Arg1, class Arg2, class Arg3>
1.117 +inline const
1.118 + lambda_functor<
1.119 + lambda_functor_base<
1.120 + other_action<ifthenelsereturn_action>,
1.121 + tuple<lambda_functor<Arg1>,
1.122 + typename const_copy_argument<Arg2>::type,
1.123 + typename const_copy_argument<Arg3>::type>
1.124 + >
1.125 +>
1.126 +if_then_else_return(const lambda_functor<Arg1>& a1,
1.127 + const Arg2 & a2,
1.128 + const Arg3 & a3) {
1.129 + return
1.130 + lambda_functor_base<
1.131 + other_action<ifthenelsereturn_action>,
1.132 + tuple<lambda_functor<Arg1>,
1.133 + typename const_copy_argument<Arg2>::type,
1.134 + typename const_copy_argument<Arg3>::type>
1.135 + > ( tuple<lambda_functor<Arg1>,
1.136 + typename const_copy_argument<Arg2>::type,
1.137 + typename const_copy_argument<Arg3>::type> (a1, a2, a3) );
1.138 +}
1.139 +
1.140 +namespace detail {
1.141 +
1.142 +// return type specialization for conditional expression begins -----------
1.143 +// start reading below and move upwards
1.144 +
1.145 +// PHASE 6:1
1.146 +// check if A is conbertible to B and B to A
1.147 +template<int Phase, bool AtoB, bool BtoA, bool SameType, class A, class B>
1.148 +struct return_type_2_ifthenelsereturn;
1.149 +
1.150 +// if A can be converted to B and vice versa -> ambiguous
1.151 +template<int Phase, class A, class B>
1.152 +struct return_type_2_ifthenelsereturn<Phase, true, true, false, A, B> {
1.153 + typedef
1.154 + detail::return_type_deduction_failure<return_type_2_ifthenelsereturn> type;
1.155 + // ambiguous type in conditional expression
1.156 +};
1.157 +// if A can be converted to B and vice versa and are of same type
1.158 +template<int Phase, class A, class B>
1.159 +struct return_type_2_ifthenelsereturn<Phase, true, true, true, A, B> {
1.160 + typedef A type;
1.161 +};
1.162 +
1.163 +
1.164 +// A can be converted to B
1.165 +template<int Phase, class A, class B>
1.166 +struct return_type_2_ifthenelsereturn<Phase, true, false, false, A, B> {
1.167 + typedef B type;
1.168 +};
1.169 +
1.170 +// B can be converted to A
1.171 +template<int Phase, class A, class B>
1.172 +struct return_type_2_ifthenelsereturn<Phase, false, true, false, A, B> {
1.173 + typedef A type;
1.174 +};
1.175 +
1.176 +// neither can be converted. Then we drop the potential references, and
1.177 +// try again
1.178 +template<class A, class B>
1.179 +struct return_type_2_ifthenelsereturn<1, false, false, false, A, B> {
1.180 + // it is safe to add const, since the result will be an rvalue and thus
1.181 + // const anyway. The const are needed eg. if the types
1.182 + // are 'const int*' and 'void *'. The remaining type should be 'const void*'
1.183 + typedef const typename boost::remove_reference<A>::type plainA;
1.184 + typedef const typename boost::remove_reference<B>::type plainB;
1.185 + // TODO: Add support for volatile ?
1.186 +
1.187 + typedef typename
1.188 + return_type_2_ifthenelsereturn<
1.189 + 2,
1.190 + boost::is_convertible<plainA,plainB>::value,
1.191 + boost::is_convertible<plainB,plainA>::value,
1.192 + boost::is_same<plainA,plainB>::value,
1.193 + plainA,
1.194 + plainB>::type type;
1.195 +};
1.196 +
1.197 +// PHASE 6:2
1.198 +template<class A, class B>
1.199 +struct return_type_2_ifthenelsereturn<2, false, false, false, A, B> {
1.200 + typedef
1.201 + detail::return_type_deduction_failure<return_type_2_ifthenelsereturn> type;
1.202 + // types_do_not_match_in_conditional_expression
1.203 +};
1.204 +
1.205 +
1.206 +
1.207 +// PHASE 5: now we know that types are not arithmetic.
1.208 +template<class A, class B>
1.209 +struct non_numeric_types {
1.210 + typedef typename
1.211 + return_type_2_ifthenelsereturn<
1.212 + 1, // phase 1
1.213 + is_convertible<A,B>::value,
1.214 + is_convertible<B,A>::value,
1.215 + is_same<A,B>::value,
1.216 + A,
1.217 + B>::type type;
1.218 +};
1.219 +
1.220 +// PHASE 4 :
1.221 +// the base case covers arithmetic types with differing promote codes
1.222 +// use the type deduction of arithmetic_actions
1.223 +template<int CodeA, int CodeB, class A, class B>
1.224 +struct arithmetic_or_not {
1.225 + typedef typename
1.226 + return_type_2<arithmetic_action<plus_action>, A, B>::type type;
1.227 + // plus_action is just a random pick, has to be a concrete instance
1.228 +};
1.229 +
1.230 +// this case covers the case of artihmetic types with the same promote codes.
1.231 +// non numeric deduction is used since e.g. integral promotion is not
1.232 +// performed with operator ?:
1.233 +template<int CodeA, class A, class B>
1.234 +struct arithmetic_or_not<CodeA, CodeA, A, B> {
1.235 + typedef typename non_numeric_types<A, B>::type type;
1.236 +};
1.237 +
1.238 +// if either A or B has promote code -1 it is not an arithmetic type
1.239 +template<class A, class B>
1.240 +struct arithmetic_or_not <-1, -1, A, B> {
1.241 + typedef typename non_numeric_types<A, B>::type type;
1.242 +};
1.243 +template<int CodeB, class A, class B>
1.244 +struct arithmetic_or_not <-1, CodeB, A, B> {
1.245 + typedef typename non_numeric_types<A, B>::type type;
1.246 +};
1.247 +template<int CodeA, class A, class B>
1.248 +struct arithmetic_or_not <CodeA, -1, A, B> {
1.249 + typedef typename non_numeric_types<A, B>::type type;
1.250 +};
1.251 +
1.252 +
1.253 +
1.254 +
1.255 +// PHASE 3 : Are the types same?
1.256 +// No, check if they are arithmetic or not
1.257 +template <class A, class B>
1.258 +struct same_or_not {
1.259 + typedef typename detail::remove_reference_and_cv<A>::type plainA;
1.260 + typedef typename detail::remove_reference_and_cv<B>::type plainB;
1.261 +
1.262 + typedef typename
1.263 + arithmetic_or_not<
1.264 + detail::promote_code<plainA>::value,
1.265 + detail::promote_code<plainB>::value,
1.266 + A,
1.267 + B>::type type;
1.268 +};
1.269 +// Yes, clear.
1.270 +template <class A> struct same_or_not<A, A> {
1.271 + typedef A type;
1.272 +};
1.273 +
1.274 +} // detail
1.275 +
1.276 +// PHASE 2 : Perform first the potential array_to_pointer conversion
1.277 +template<class A, class B>
1.278 +struct return_type_2<other_action<ifthenelsereturn_action>, A, B> {
1.279 +
1.280 + typedef typename detail::array_to_pointer<A>::type A1;
1.281 + typedef typename detail::array_to_pointer<B>::type B1;
1.282 +
1.283 + typedef typename
1.284 + boost::add_const<typename detail::same_or_not<A1, B1>::type>::type type;
1.285 +};
1.286 +
1.287 +// PHASE 1 : Deduction is based on the second and third operand
1.288 +
1.289 +
1.290 +// return type specialization for conditional expression ends -----------
1.291 +
1.292 +
1.293 +// Specialization of lambda_functor_base for if_then_else_return.
1.294 +template<class Args>
1.295 +class
1.296 +lambda_functor_base<other_action<ifthenelsereturn_action>, Args> {
1.297 +public:
1.298 + Args args;
1.299 +
1.300 + template <class SigArgs> struct sig {
1.301 + private:
1.302 + typedef typename detail::nth_return_type_sig<1, Args, SigArgs>::type ret1;
1.303 + typedef typename detail::nth_return_type_sig<2, Args, SigArgs>::type ret2;
1.304 + public:
1.305 + typedef typename return_type_2<
1.306 + other_action<ifthenelsereturn_action>, ret1, ret2
1.307 + >::type type;
1.308 + };
1.309 +
1.310 +public:
1.311 + explicit lambda_functor_base(const Args& a) : args(a) {}
1.312 +
1.313 + template<class RET, CALL_TEMPLATE_ARGS>
1.314 + RET call(CALL_FORMAL_ARGS) const {
1.315 + return (detail::select(boost::tuples::get<0>(args), CALL_ACTUAL_ARGS)) ?
1.316 + detail::select(boost::tuples::get<1>(args), CALL_ACTUAL_ARGS)
1.317 + :
1.318 + detail::select(boost::tuples::get<2>(args), CALL_ACTUAL_ARGS);
1.319 + }
1.320 +};
1.321 +
1.322 + // The code below is from Joel de Guzman, some name changes etc.
1.323 + // has been made.
1.324 +
1.325 +///////////////////////////////////////////////////////////////////////////////
1.326 +//
1.327 +// if_then_else_composite
1.328 +//
1.329 +// This composite has two (2) forms:
1.330 +//
1.331 +// if_(condition)
1.332 +// [
1.333 +// statement
1.334 +// ]
1.335 +//
1.336 +// and
1.337 +//
1.338 +// if_(condition)
1.339 +// [
1.340 +// true_statement
1.341 +// ]
1.342 +// .else_
1.343 +// [
1.344 +// false_statement
1.345 +// ]
1.346 +//
1.347 +// where condition is an lambda_functor that evaluates to bool. If condition
1.348 +// is true, the true_statement (again an lambda_functor) is executed
1.349 +// otherwise, the false_statement (another lambda_functor) is executed. The
1.350 +// result type of this is void. Note the trailing underscore after
1.351 +// if_ and the the leading dot and the trailing underscore before
1.352 +// and after .else_.
1.353 +//
1.354 +///////////////////////////////////////////////////////////////////////////////
1.355 +template <typename CondT, typename ThenT, typename ElseT>
1.356 +struct if_then_else_composite {
1.357 +
1.358 + typedef if_then_else_composite<CondT, ThenT, ElseT> self_t;
1.359 +
1.360 + template <class SigArgs>
1.361 + struct sig { typedef void type; };
1.362 +
1.363 + if_then_else_composite(
1.364 + CondT const& cond_,
1.365 + ThenT const& then_,
1.366 + ElseT const& else__)
1.367 + : cond(cond_), then(then_), else_(else__) {}
1.368 +
1.369 + template <class Ret, CALL_TEMPLATE_ARGS>
1.370 + Ret call(CALL_FORMAL_ARGS) const
1.371 + {
1.372 + if (cond.internal_call(CALL_ACTUAL_ARGS))
1.373 + then.internal_call(CALL_ACTUAL_ARGS);
1.374 + else
1.375 + else_.internal_call(CALL_ACTUAL_ARGS);
1.376 + }
1.377 +
1.378 + CondT cond; ThenT then; ElseT else_; // lambda_functors
1.379 +};
1.380 +
1.381 +//////////////////////////////////
1.382 +template <typename CondT, typename ThenT>
1.383 +struct else_gen {
1.384 +
1.385 + else_gen(CondT const& cond_, ThenT const& then_)
1.386 + : cond(cond_), then(then_) {}
1.387 +
1.388 + template <typename ElseT>
1.389 + lambda_functor<if_then_else_composite<CondT, ThenT,
1.390 + typename as_lambda_functor<ElseT>::type> >
1.391 + operator[](ElseT const& else_)
1.392 + {
1.393 + typedef if_then_else_composite<CondT, ThenT,
1.394 + typename as_lambda_functor<ElseT>::type>
1.395 + result;
1.396 +
1.397 + return result(cond, then, to_lambda_functor(else_));
1.398 + }
1.399 +
1.400 + CondT cond; ThenT then;
1.401 +};
1.402 +
1.403 +//////////////////////////////////
1.404 +template <typename CondT, typename ThenT>
1.405 +struct if_then_composite {
1.406 +
1.407 + template <class SigArgs>
1.408 + struct sig { typedef void type; };
1.409 +
1.410 + if_then_composite(CondT const& cond_, ThenT const& then_)
1.411 + : cond(cond_), then(then_), else_(cond, then) {}
1.412 +
1.413 + template <class Ret, CALL_TEMPLATE_ARGS>
1.414 + Ret call(CALL_FORMAL_ARGS) const
1.415 + {
1.416 + if (cond.internal_call(CALL_ACTUAL_ARGS))
1.417 + then.internal_call(CALL_ACTUAL_ARGS);
1.418 + }
1.419 +
1.420 + CondT cond; ThenT then; // lambda_functors
1.421 + else_gen<CondT, ThenT> else_;
1.422 +};
1.423 +
1.424 +//////////////////////////////////
1.425 +template <typename CondT>
1.426 +struct if_gen {
1.427 +
1.428 + if_gen(CondT const& cond_)
1.429 + : cond(cond_) {}
1.430 +
1.431 + template <typename ThenT>
1.432 + lambda_functor<if_then_composite<
1.433 + typename as_lambda_functor<CondT>::type,
1.434 + typename as_lambda_functor<ThenT>::type> >
1.435 + operator[](ThenT const& then) const
1.436 + {
1.437 + typedef if_then_composite<
1.438 + typename as_lambda_functor<CondT>::type,
1.439 + typename as_lambda_functor<ThenT>::type>
1.440 + result;
1.441 +
1.442 + return result(
1.443 + to_lambda_functor(cond),
1.444 + to_lambda_functor(then));
1.445 + }
1.446 +
1.447 + CondT cond;
1.448 +};
1.449 +
1.450 +//////////////////////////////////
1.451 +template <typename CondT>
1.452 +inline if_gen<CondT>
1.453 +if_(CondT const& cond)
1.454 +{
1.455 + return if_gen<CondT>(cond);
1.456 +}
1.457 +
1.458 +
1.459 +
1.460 +} // lambda
1.461 +} // boost
1.462 +
1.463 +#endif // BOOST_LAMBDA_IF_HPP
1.464 +
1.465 +