the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 462 lines 13 kB view raw
1// Boost Lambda Library -- if.hpp ------------------------------------------ 2 3// Copyright (C) 1999, 2000 Jaakko Jarvi (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 24namespace boost { 25namespace lambda { 26 27// -- if control construct actions ---------------------- 28 29class ifthen_action {}; 30class ifthenelse_action {}; 31class ifthenelsereturn_action {}; 32 33// Specialization for if_then. 34template<class Args> 35class 36lambda_functor_base<ifthen_action, Args> { 37public: 38 Args args; 39 template <class T> struct sig { typedef void type; }; 40public: 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 51template <class Arg1, class Arg2> 52inline const 53lambda_functor< 54 lambda_functor_base< 55 ifthen_action, 56 tuple<lambda_functor<Arg1>, lambda_functor<Arg2> > 57 > 58> 59if_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. 70template<class Args> 71class 72lambda_functor_base<ifthenelse_action, Args> { 73public: 74 Args args; 75 template <class T> struct sig { typedef void type; }; 76public: 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 92template <class Arg1, class Arg2, class Arg3> 93inline const 94lambda_functor< 95 lambda_functor_base< 96 ifthenelse_action, 97 tuple<lambda_functor<Arg1>, lambda_functor<Arg2>, lambda_functor<Arg3> > 98 > 99> 100if_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 113template <class Arg1, class Arg2, class Arg3> 114inline 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> 123if_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 137namespace 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 144template<int Phase, bool AtoB, bool BtoA, bool SameType, class A, class B> 145struct return_type_2_ifthenelsereturn; 146 147// if A can be converted to B and vice versa -> ambiguous 148template<int Phase, class A, class B> 149struct 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 155template<int Phase, class A, class B> 156struct return_type_2_ifthenelsereturn<Phase, true, true, true, A, B> { 157 typedef A type; 158}; 159 160 161// A can be converted to B 162template<int Phase, class A, class B> 163struct return_type_2_ifthenelsereturn<Phase, true, false, false, A, B> { 164 typedef B type; 165}; 166 167// B can be converted to A 168template<int Phase, class A, class B> 169struct 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 175template<class A, class B> 176struct 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 195template<class A, class B> 196struct 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. 205template<class A, class B> 206struct 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 220template<int CodeA, int CodeB, class A, class B> 221struct 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 ?: 230template<int CodeA, class A, class B> 231struct 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 236template<class A, class B> 237struct arithmetic_or_not <-1, -1, A, B> { 238 typedef typename non_numeric_types<A, B>::type type; 239}; 240template<int CodeB, class A, class B> 241struct arithmetic_or_not <-1, CodeB, A, B> { 242 typedef typename non_numeric_types<A, B>::type type; 243}; 244template<int CodeA, class A, class B> 245struct 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 254template <class A, class B> 255struct 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. 267template <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 274template<class A, class B> 275struct 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. 291template<class Args> 292class 293lambda_functor_base<other_action<ifthenelsereturn_action>, Args> { 294public: 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 307public: 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 leading dot and the trailing underscore before 349// and after .else_. 350// 351/////////////////////////////////////////////////////////////////////////////// 352template <typename CondT, typename ThenT, typename ElseT> 353struct 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////////////////////////////////// 379template <typename CondT, typename ThenT> 380struct 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////////////////////////////////// 401template <typename CondT, typename ThenT> 402struct 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////////////////////////////////// 422template <typename CondT> 423struct 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////////////////////////////////// 448template <typename CondT> 449inline if_gen<CondT> 450if_(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