annotate DEPENDENCIES/generic/include/boost/lambda/if.hpp @ 133:4acb5d8d80b6 tip

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