1 #ifndef BOOST_PP_IS_ITERATING 2 /////////////////////////////////////////////////////////////////////////////// 3 // Copyright 2008 Eric Niebler. Distributed under the Boost 4 // Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // This example contains a full-featured reimplementation of the old, 8 // now-deprecated Boost Lambda Library (BLL) on top of Boost.Proto. It 9 // is necessarily complex to accomodate all the quirks and inconsistencies 10 // of that old library, but it is a good example of how to build a 11 // complete and full-featured EDLS using Proto. 12 #ifndef BOOST_LAMBDA_HPP_EAN_04_19_2008 13 #define BOOST_LAMBDA_HPP_EAN_04_19_2008 14 15 #include <iosfwd> 16 #include <typeinfo> 17 #include <algorithm> 18 #include <boost/ref.hpp> 19 #include <boost/assert.hpp> 20 #include <boost/mpl/or.hpp> 21 #include <boost/mpl/int.hpp> 22 #include <boost/mpl/void.hpp> 23 #include <boost/mpl/identity.hpp> 24 #include <boost/mpl/next_prior.hpp> 25 #include <boost/mpl/min_max.hpp> 26 #include <boost/mpl/assert.hpp> 27 #include <boost/preprocessor.hpp> 28 #include <boost/utility/enable_if.hpp> 29 #include <boost/utility/result_of.hpp> 30 #include <boost/fusion/include/vector.hpp> 31 #include <boost/type_traits/add_reference.hpp> 32 #include <boost/type_traits/remove_reference.hpp> 33 #include <boost/type_traits/remove_const.hpp> 34 #include <boost/type_traits/is_same.hpp> 35 #include <boost/proto/proto.hpp> 36 37 #ifndef BOOST_LAMBDA_MAX_ARITY 38 # define BOOST_LAMBDA_MAX_ARITY 3 39 #endif 40 41 #ifdef _MSC_VER 42 # pragma warning(push) 43 # pragma warning(disable: 4355) // 'this' : used in base member initializer list 44 # pragma warning(disable: 4065) // switch statement contains 'default' but no 'case' labels 45 #endif 46 47 namespace boost { namespace lambda 48 { 49 namespace tag 50 { 51 struct if_ {}; 52 struct if_else_ {}; 53 struct for_ {}; 54 struct while_ {}; 55 struct do_while_ {}; 56 struct protect {}; 57 struct try_ {}; 58 struct throw_ {}; 59 struct rethrow_ {}; 60 struct switch_ {}; 61 struct default_ {}; 62 template<int I> struct case_ { static const int value = I; }; 63 template<typename E> struct catch_ { typedef E exception_type; }; 64 struct catch_all_ { typedef catch_all_ exception_type; }; 65 }; 66 67 template<typename Int> 68 struct placeholder 69 { 70 typedef typename Int::tag tag; 71 typedef typename Int::value_type value_type; 72 typedef placeholder<Int> type; 73 typedef placeholder<typename Int::next> next; 74 typedef placeholder<typename Int::prior> prior; 75 static const value_type value = Int::value; 76 operator <<(std::ostream & sout,placeholder)77 friend std::ostream &operator<<(std::ostream &sout, placeholder) 78 { 79 return sout << "boost::lambda::_" << (Int::value+1); 80 } 81 }; 82 83 struct exception_placeholder 84 {}; 85 86 struct no_exception_type {}; 87 no_exception_type const no_exception = {}; 88 89 // Calculate the arity of a lambda expression 90 struct Arity 91 : proto::or_< 92 proto::when<proto::terminal<placeholder<proto::_> >, mpl::next<proto::_value>()> 93 , proto::when<proto::terminal<proto::_>, mpl::int_<0>()> 94 , proto::otherwise<proto::fold<proto::_, mpl::int_<0>(), mpl::max<proto::_state, Arity>()> > 95 > 96 {}; 97 98 // True when a lambda expression can be applied with no arguments and 99 // without an active exception object 100 struct IsNullary 101 : proto::or_< 102 proto::when<proto::terminal<placeholder<proto::_> >, mpl::false_()> 103 , proto::when<proto::terminal<exception_placeholder>, mpl::false_()> 104 , proto::when<proto::terminal<proto::_>, mpl::true_()> 105 , proto::otherwise<proto::fold<proto::_, mpl::true_(), mpl::and_<proto::_state, IsNullary>()> > 106 > 107 {}; 108 109 struct Eval; 110 111 template<typename Expr, typename State, typename Data> 112 typename boost::result_of<Eval(Expr&, State&, Data&)>::type 113 eval_lambda(Expr& e, State& s, Data& d); 114 115 struct EvalWhile : proto::transform<EvalWhile> 116 { 117 template<typename Expr, typename State, typename Data> 118 struct impl : proto::transform_impl<Expr, State, Data> 119 { 120 typedef mpl::void_ result_type; 121 operator ()boost::lambda::EvalWhile::impl122 result_type operator()( 123 typename impl::expr_param expr 124 , typename impl::state_param state 125 , typename impl::data_param data 126 ) const 127 { 128 while(eval_lambda(proto::left(expr), state, data)) 129 { 130 eval_lambda(proto::right(expr), state, data); 131 } 132 return result_type(); 133 } 134 }; 135 }; 136 137 struct EvalDoWhile : proto::transform<EvalDoWhile> 138 { 139 template<typename Expr, typename State, typename Data> 140 struct impl : proto::transform_impl<Expr, State, Data> 141 { 142 typedef mpl::void_ result_type; 143 operator ()boost::lambda::EvalDoWhile::impl144 result_type operator()( 145 typename impl::expr_param expr 146 , typename impl::state_param state 147 , typename impl::data_param data 148 ) const 149 { 150 do 151 { 152 eval_lambda(proto::child_c<0>(expr), state, data); 153 } 154 while(eval_lambda(proto::child_c<1>(expr), state, data)); 155 156 return result_type(); 157 } 158 }; 159 }; 160 161 struct EvalFor : proto::transform<EvalFor> 162 { 163 template<typename Expr, typename State, typename Data> 164 struct impl : proto::transform_impl<Expr, State, Data> 165 { 166 typedef mpl::void_ result_type; 167 operator ()boost::lambda::EvalFor::impl168 result_type operator()( 169 typename impl::expr_param expr 170 , typename impl::state_param state 171 , typename impl::data_param data 172 ) const 173 { 174 for(eval_lambda(proto::child_c<0>(expr), state, data) 175 ; eval_lambda(proto::child_c<1>(expr), state, data) 176 ; eval_lambda(proto::child_c<2>(expr), state, data)) 177 { 178 eval_lambda(proto::child_c<3>(expr), state, data); 179 } 180 return result_type(); 181 } 182 }; 183 }; 184 185 struct EvalIf : proto::transform<EvalIf> 186 { 187 template<typename Expr, typename State, typename Data> 188 struct impl : proto::transform_impl<Expr, State, Data> 189 { 190 typedef mpl::void_ result_type; 191 operator ()boost::lambda::EvalIf::impl192 result_type operator()( 193 typename impl::expr_param expr 194 , typename impl::state_param state 195 , typename impl::data_param data 196 ) const 197 { 198 if(eval_lambda(proto::left(expr), state, data)) 199 { 200 eval_lambda(proto::right(expr), state, data); 201 } 202 return result_type(); 203 } 204 }; 205 }; 206 207 struct EvalIfElse : proto::transform<EvalIfElse> 208 { 209 template<typename Expr, typename State, typename Data> 210 struct impl : proto::transform_impl<Expr, State, Data> 211 { 212 typedef mpl::void_ result_type; 213 operator ()boost::lambda::EvalIfElse::impl214 result_type operator()( 215 typename impl::expr_param expr 216 , typename impl::state_param state 217 , typename impl::data_param data 218 ) const 219 { 220 if(eval_lambda(proto::child_c<0>(expr), state, data)) 221 { 222 eval_lambda(proto::child_c<1>(expr), state, data); 223 } 224 else 225 { 226 eval_lambda(proto::child_c<2>(expr), state, data); 227 } 228 return result_type(); 229 } 230 }; 231 }; 232 233 struct EvalException : proto::transform<EvalException> 234 { 235 template<typename Expr, typename State, typename Data> 236 struct impl : proto::transform_impl<Expr, State, Data> 237 { 238 typedef typename remove_const<typename impl::state>::type result_type; 239 BOOST_MPL_ASSERT_NOT((is_same<result_type, no_exception_type>)); 240 BOOST_MPL_ASSERT_NOT((is_same<result_type, tag::catch_all_>)); 241 operator ()boost::lambda::EvalException::impl242 typename impl::state_param operator()( 243 typename impl::expr_param 244 , typename impl::state_param state 245 , typename impl::data_param 246 ) const 247 { 248 return state; 249 } 250 }; 251 }; 252 253 struct EvalSwitch : proto::transform<EvalSwitch> 254 { 255 template<typename Expr, typename State, typename Data, long Arity, typename BackTag> 256 struct impl2; 257 258 #define M0(Z, N, DATA) \ 259 case proto::tag_of<typename proto::result_of::child_c<Expr, N>::type>::type::value: \ 260 eval_lambda(proto::child_c<N>(expr), state, data); \ 261 break; \ 262 /**/ 263 264 #define M1(Z, N, DATA) \ 265 template<typename Expr, typename State, typename Data, typename BackTag> \ 266 struct impl2<Expr, State, Data, N, BackTag> \ 267 : proto::transform_impl<Expr, State, Data> \ 268 { \ 269 typedef void result_type; \ 270 \ 271 void operator()( \ 272 typename impl2::expr_param expr \ 273 , typename impl2::state_param state \ 274 , typename impl2::data_param data \ 275 ) const \ 276 { \ 277 switch(eval_lambda(proto::child_c<0>(expr), state, data)) \ 278 { \ 279 BOOST_PP_REPEAT_FROM_TO_ ## Z(1, N, M0, ~) \ 280 default: \ 281 break; \ 282 } \ 283 } \ 284 }; \ 285 \ 286 template<typename Expr, typename State, typename Data> \ 287 struct impl2<Expr, State, Data, N, tag::default_> \ 288 : proto::transform_impl<Expr, State, Data> \ 289 { \ 290 typedef void result_type; \ 291 \ 292 void operator()( \ 293 typename impl2::expr_param expr \ 294 , typename impl2::state_param state \ 295 , typename impl2::data_param data \ 296 ) const \ 297 { \ 298 switch(eval_lambda(proto::child_c<0>(expr), state, data)) \ 299 { \ 300 BOOST_PP_REPEAT_FROM_TO_ ## Z(1, BOOST_PP_DEC(N), M0, ~) \ 301 default:; \ 302 eval_lambda(proto::child_c<BOOST_PP_DEC(N)>(expr), state, data); \ 303 break; \ 304 } \ 305 } \ 306 }; \ 307 /**/ 308 BOOST_PP_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1, ~) 309 #undef M0 310 #undef M1 311 312 template<typename Expr, typename State, typename Data> 313 struct impl 314 : impl2< 315 Expr 316 , State 317 , Data 318 , proto::arity_of<Expr>::value 319 , typename proto::tag_of< 320 typename proto::result_of::child_c< 321 Expr 322 , proto::arity_of<Expr>::value-1 323 >::type 324 >::type 325 > 326 {}; 327 }; 328 329 struct throw_fun 330 { 331 BOOST_PROTO_CALLABLE() 332 typedef void result_type; 333 template<typename Expr> operator ()boost::lambda::throw_fun334 void operator()(Expr const &e) const 335 { 336 throw e; 337 } 338 }; 339 340 struct unwrap_ref : proto::callable 341 { 342 template<typename Sig> 343 struct result; 344 345 template<typename This, typename T> 346 struct result<This(reference_wrapper<T>)> 347 { 348 typedef T &type; 349 }; 350 351 template<typename This, typename T> 352 struct result<This(T &)> 353 : result<This(T)> 354 {}; 355 356 template<typename T> operator ()boost::lambda::unwrap_ref357 T &operator()(reference_wrapper<T> const &ref) const 358 { 359 return ref; 360 } 361 }; 362 363 struct anytype 364 { 365 template<typename T> anytypeboost::lambda::anytype366 anytype(T &) { BOOST_ASSERT(false); } 367 template<typename T> operator T&boost::lambda::anytype368 operator T &() const { BOOST_ASSERT(false); throw; } 369 private: 370 anytype(); 371 }; 372 373 struct rethrow_fun 374 { 375 BOOST_PROTO_CALLABLE() 376 typedef anytype result_type; 377 template<typename State> operator ()boost::lambda::rethrow_fun378 anytype operator()(State const &) const 379 { 380 BOOST_MPL_ASSERT_NOT((is_same<State, no_exception_type>)); 381 throw; 382 } 383 }; 384 385 struct Cases 386 { 387 template<typename Tag> 388 struct case_ 389 : proto::otherwise<proto::_default<Eval> > 390 {}; 391 392 template<typename E> 393 struct case_<tag::catch_<E> > 394 : proto::otherwise<Eval(proto::_child)> 395 {}; 396 397 template<int I> 398 struct case_<tag::case_<I> > 399 : proto::otherwise<Eval(proto::_child)> 400 {}; 401 }; 402 403 template<> struct Cases::case_<tag::while_> : proto::otherwise<EvalWhile> {}; 404 template<> struct Cases::case_<tag::for_> : proto::otherwise<EvalFor> {}; 405 template<> struct Cases::case_<tag::if_> : proto::otherwise<EvalIf> {}; 406 template<> struct Cases::case_<tag::if_else_> : proto::otherwise<EvalIfElse> {}; 407 template<> struct Cases::case_<tag::do_while_> : proto::otherwise<EvalDoWhile> {}; 408 template<> struct Cases::case_<tag::switch_> : proto::otherwise<EvalSwitch> {}; 409 template<> struct Cases::case_<tag::protect> : proto::otherwise<proto::_child> {}; 410 template<> struct Cases::case_<tag::default_> : proto::otherwise<Eval(proto::_child)> {}; 411 template<> struct Cases::case_<tag::catch_all_> : proto::otherwise<Eval(proto::_child)> {}; 412 413 template<> 414 struct Cases::case_<proto::tag::terminal> 415 : proto::or_< 416 proto::when< 417 proto::terminal<placeholder<proto::_> > 418 , proto::functional::at(proto::_data, proto::_value) 419 > 420 , proto::when< 421 proto::terminal<exception_placeholder> 422 , EvalException 423 > 424 , proto::when< 425 proto::terminal<reference_wrapper<proto::_> > 426 , unwrap_ref(proto::_value) 427 > 428 , proto::otherwise<proto::_default<Eval> > 429 > 430 {}; 431 432 template<> 433 struct Cases::case_<proto::tag::function> 434 : proto::or_< 435 proto::when< 436 proto::function<proto::terminal<rethrow_fun> > 437 , rethrow_fun(proto::_state) 438 > 439 , proto::otherwise<proto::_default<Eval> > 440 > 441 {}; 442 443 struct Eval 444 : proto::switch_<Cases> 445 {}; 446 447 template<typename Expr, typename State, typename Data> 448 typename boost::result_of<Eval(Expr&, State&, Data&)>::type eval_lambda(Expr & e,State & s,Data & d)449 eval_lambda(Expr& e, State& s, Data& d) 450 { 451 return Eval()(e, s, d); 452 } 453 454 // Use a grammar to disable Proto's assignment operator overloads. 455 // We'll define our own because we want (x+=_1) to store x by 456 // reference. (In all other cases, variables are stored by value 457 // within lambda expressions.) 458 struct Grammar 459 : proto::switch_<struct AssignOps> 460 {}; 461 462 struct AssignOps 463 { 464 template<typename Tag> struct case_ : proto::_ {}; 465 }; 466 467 template<> struct AssignOps::case_<proto::tag::shift_left_assign> : proto::not_<proto::_> {}; 468 template<> struct AssignOps::case_<proto::tag::shift_right_assign> : proto::not_<proto::_> {}; 469 template<> struct AssignOps::case_<proto::tag::multiplies_assign> : proto::not_<proto::_> {}; 470 template<> struct AssignOps::case_<proto::tag::divides_assign> : proto::not_<proto::_> {}; 471 template<> struct AssignOps::case_<proto::tag::modulus_assign> : proto::not_<proto::_> {}; 472 template<> struct AssignOps::case_<proto::tag::plus_assign> : proto::not_<proto::_> {}; 473 template<> struct AssignOps::case_<proto::tag::minus_assign> : proto::not_<proto::_> {}; 474 template<> struct AssignOps::case_<proto::tag::bitwise_and_assign> : proto::not_<proto::_> {}; 475 template<> struct AssignOps::case_<proto::tag::bitwise_or_assign> : proto::not_<proto::_> {}; 476 template<> struct AssignOps::case_<proto::tag::bitwise_xor_assign> : proto::not_<proto::_> {}; 477 478 template<typename Expr> 479 struct llexpr; 480 481 // Wrap expressions in lambda::llexpr<>. 482 struct Generator 483 : proto::pod_generator<llexpr> 484 {}; 485 486 // The domain for the lambda library. 487 struct lldomain 488 : proto::domain<Generator, Grammar, proto::default_domain> 489 { 490 // Make all terminals and children held by value instead of by reference. 491 // Proto::domain<>::as_expr<> holds everything it can by value; the only 492 // exceptions are function types, abstract types, and iostreams. 493 template<typename T> 494 struct as_child 495 : proto_base_domain::as_expr<T> 496 {}; 497 498 // The exception is arrays, which should still be held by reference 499 template<typename T, std::size_t N> 500 struct as_child<T[N]> 501 : proto_base_domain::as_child<T[N]> 502 {}; 503 }; 504 505 template<typename Sig> 506 struct llresult; 507 508 template<typename This> 509 struct llresult<This()> 510 : mpl::if_c< 511 result_of<IsNullary(This &)>::type::value 512 , result_of<Eval(This &, no_exception_type const &, fusion::vector0<> &)> 513 , mpl::identity<void> 514 >::type 515 {}; 516 517 #define M0(Z, N, DATA) \ 518 template<typename This BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, typename A)> \ 519 struct llresult<This(BOOST_PP_ENUM_PARAMS_Z(Z, N, A))> \ 520 : result_of< \ 521 Eval( \ 522 This & \ 523 , no_exception_type const & \ 524 , BOOST_PP_CAT(fusion::vector, N)<BOOST_PP_ENUM_PARAMS_Z(Z, N, A)> & \ 525 ) \ 526 > \ 527 {}; \ 528 /**/ 529 BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_LAMBDA_MAX_ARITY), M0, ~) 530 #undef M0 531 532 template<typename Expr> 533 struct llexpr 534 { 535 BOOST_PROTO_BASIC_EXTENDS(Expr, llexpr<Expr>, lldomain) 536 BOOST_PROTO_EXTENDS_ASSIGN() 537 BOOST_PROTO_EXTENDS_SUBSCRIPT() 538 539 template<typename Sig> 540 struct result 541 : llresult<Sig> 542 {}; 543 544 typename result<llexpr const()>::type operator ()boost::lambda::llexpr545 operator()() const 546 { 547 fusion::vector0<> args; 548 return eval_lambda(*this, no_exception, args); 549 } 550 551 #define M1(Z, N, _) ((0)(1)) 552 553 #define M2(R, PRODUCT) M3(R, BOOST_PP_SEQ_SIZE(PRODUCT), PRODUCT) 554 555 #define M3(R, SIZE, PRODUCT) \ 556 template<BOOST_PP_ENUM_PARAMS(SIZE, typename A)> \ 557 typename result<llexpr const(BOOST_PP_SEQ_FOR_EACH_I_R(R, M5, ~, PRODUCT))>::type \ 558 operator ()(BOOST_PP_SEQ_FOR_EACH_I_R(R, M4, ~, PRODUCT)) const \ 559 { \ 560 BOOST_MPL_ASSERT_RELATION(result_of<Arity(Expr const &)>::type::value, <=, SIZE); \ 561 BOOST_PP_CAT(fusion::vector, SIZE)<BOOST_PP_SEQ_FOR_EACH_I_R(R, M5, ~, PRODUCT)> args \ 562 (BOOST_PP_SEQ_FOR_EACH_I_R(R, M6, ~, PRODUCT)); \ 563 return eval_lambda(*this, no_exception, args); \ 564 } \ 565 /**/ 566 567 #define M4(R, _, I, ELEM) \ 568 BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(A, I) BOOST_PP_CAT(C, ELEM) &BOOST_PP_CAT(a, I) \ 569 /**/ 570 571 #define M5(R, _, I, ELEM) \ 572 BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(A, I) BOOST_PP_CAT(C, ELEM)& \ 573 /**/ 574 575 #define M6(R, _, I, ELEM) \ 576 BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(a, I) \ 577 /**/ 578 579 #define C0 580 581 #define C1 const 582 583 #define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_LAMBDA_MAX_ARITY, "lambda.hpp")) 584 #include BOOST_PP_ITERATE() 585 586 #undef C0 587 #undef C1 588 #undef M1 589 #undef M2 590 #undef M3 591 #undef M4 592 #undef M5 593 #undef M6 594 }; 595 596 typedef llexpr<proto::terminal<placeholder<mpl::int_<0> > >::type> placeholder1_type; 597 typedef llexpr<proto::terminal<placeholder<mpl::int_<1> > >::type> placeholder2_type; 598 typedef llexpr<proto::terminal<placeholder<mpl::int_<2> > >::type> placeholder3_type; 599 600 placeholder1_type const _1 = {{{}}}; 601 placeholder2_type const _2 = {{{}}}; 602 placeholder3_type const _3 = {{{}}}; 603 604 placeholder1_type const free1 = {{{}}}; 605 placeholder2_type const free2 = {{{}}}; 606 placeholder3_type const free3 = {{{}}}; 607 608 typedef llexpr<proto::terminal<exception_placeholder>::type> placeholderE_type; 609 placeholderE_type const _e = {{{}}}; 610 611 struct byref 612 { 613 template<typename Sig> 614 struct result; 615 616 template<typename This, typename T> 617 struct result<This(T &)> 618 { 619 typedef llexpr<typename proto::terminal<T &>::type> type; 620 }; 621 622 template<typename This, typename T> 623 struct result<This(llexpr<T> &)> 624 { 625 typedef boost::reference_wrapper<llexpr<T> > type; 626 }; 627 628 template<typename This, typename T> 629 struct result<This(llexpr<T> const &)> 630 { 631 typedef boost::reference_wrapper<llexpr<T> const> type; 632 }; 633 634 template<typename T> operator ()boost::lambda::byref635 typename result<byref(T &)>::type operator()(T &t) const 636 { 637 typename result<byref(T &)>::type that = {{t}}; 638 return that; 639 } 640 641 template<typename T> operator ()boost::lambda::byref642 typename result<byref(T const &)>::type operator()(T const &t) const 643 { 644 typename result<byref(T const &)>::type that = {{t}}; 645 return that; 646 } 647 648 template<typename T> operator ()boost::lambda::byref649 boost::reference_wrapper<llexpr<T> > operator()(llexpr<T> &t) const 650 { 651 return boost::ref(t); 652 } 653 654 template<typename T> operator ()boost::lambda::byref655 boost::reference_wrapper<llexpr<T> const> operator()(llexpr<T> const &t) const 656 { 657 return boost::ref(t); 658 } 659 }; 660 661 namespace exprns_ 662 { 663 // Ugh, the assign operators (and only the assign operators) store 664 // their left terminals by reference. That requires this special handling. 665 #define BOOST_LAMBDA_DEFINE_ASSIGN_OP(OP, TAG) \ 666 template<typename T, typename U> \ 667 typename proto::result_of::make_expr< \ 668 TAG \ 669 , lldomain \ 670 , typename boost::result_of<byref(T &)>::type \ 671 , U & \ 672 >::type const \ 673 operator OP(T &t, U &u) \ 674 { \ 675 return proto::make_expr<TAG, lldomain>(byref()(t), boost::ref(u)); \ 676 } \ 677 template<typename T, typename U> \ 678 typename proto::result_of::make_expr< \ 679 TAG \ 680 , lldomain \ 681 , typename boost::result_of<byref(T &)>::type \ 682 , U const & \ 683 >::type const \ 684 operator OP(T &t, U const &u) \ 685 { \ 686 return proto::make_expr<TAG, lldomain>(byref()(t), boost::ref(u)); \ 687 } \ 688 /**/ 689 690 BOOST_LAMBDA_DEFINE_ASSIGN_OP(<<=, boost::proto::tag::shift_left_assign) 691 BOOST_LAMBDA_DEFINE_ASSIGN_OP(>>=, boost::proto::tag::shift_right_assign) 692 BOOST_LAMBDA_DEFINE_ASSIGN_OP(*= , boost::proto::tag::multiplies_assign) 693 BOOST_LAMBDA_DEFINE_ASSIGN_OP(/= , boost::proto::tag::divides_assign) 694 BOOST_LAMBDA_DEFINE_ASSIGN_OP(%= , boost::proto::tag::modulus_assign) 695 BOOST_LAMBDA_DEFINE_ASSIGN_OP(+= , boost::proto::tag::plus_assign) 696 BOOST_LAMBDA_DEFINE_ASSIGN_OP(-= , boost::proto::tag::minus_assign) 697 BOOST_LAMBDA_DEFINE_ASSIGN_OP(&= , boost::proto::tag::bitwise_and_assign) 698 BOOST_LAMBDA_DEFINE_ASSIGN_OP(|= , boost::proto::tag::bitwise_or_assign) 699 BOOST_LAMBDA_DEFINE_ASSIGN_OP(^= , boost::proto::tag::bitwise_xor_assign) 700 } 701 702 template<typename T> 703 struct var_type 704 { 705 typedef llexpr<typename proto::terminal<T &>::type> type; 706 }; 707 708 template<typename T> 709 llexpr<typename proto::terminal<T &>::type> const var(T & t)710 var(T &t) 711 { 712 llexpr<typename proto::terminal<T &>::type> that = {{t}}; 713 return that; 714 } 715 716 template<typename T> 717 struct constant_type 718 : proto::result_of::make_expr< 719 proto::tag::terminal 720 , lldomain 721 , T const & 722 > 723 {}; 724 725 template<typename T> 726 typename constant_type<T>::type const constant(T const & t)727 constant(T const &t) 728 { 729 typename constant_type<T>::type that = {{t}}; 730 return that; 731 } 732 733 template<typename T> 734 struct constant_ref_type 735 { 736 typedef llexpr<typename proto::terminal<T const &>::type> type; 737 }; 738 739 template<typename T> 740 llexpr<typename proto::terminal<T const &>::type> const constant_ref(T const & t)741 constant_ref(T const &t) 742 { 743 llexpr<typename proto::terminal<T const &>::type> that = {{t}}; 744 return that; 745 } 746 747 template<typename Cond> 748 struct while_generator 749 { while_generatorboost::lambda::while_generator750 explicit while_generator(Cond const &c) 751 : cond(c) 752 {} 753 754 template<typename Body> 755 typename proto::result_of::make_expr< 756 tag::while_ 757 , lldomain 758 , Cond const & 759 , Body const & 760 >::type const operator []boost::lambda::while_generator761 operator[](Body const &body) const 762 { 763 return proto::make_expr<tag::while_, lldomain>( 764 boost::ref(this->cond) 765 , boost::ref(body) 766 ); 767 } 768 769 private: 770 Cond const &cond; 771 }; 772 773 template<typename Expr> while_(Expr const & expr)774 while_generator<Expr> while_(Expr const &expr) 775 { 776 return while_generator<Expr>(expr); 777 } 778 779 template<typename Expr> 780 struct else_generator 781 { 782 typedef typename proto::result_of::left<Expr const &>::type condition_type; 783 typedef typename proto::result_of::right<Expr const &>::type body1_type; 784 else_generatorboost::lambda::else_generator785 explicit else_generator(Expr const &expr) 786 : if_(expr) 787 {} 788 789 template<typename Body2> 790 typename proto::result_of::make_expr< 791 tag::if_else_ 792 , lldomain 793 , condition_type 794 , body1_type 795 , Body2 const & 796 >::type const operator []boost::lambda::else_generator797 operator[](Body2 const &body2) const 798 { 799 return proto::make_expr<tag::if_else_, lldomain>( 800 boost::ref(proto::left(this->if_)) 801 , boost::ref(proto::right(this->if_)) 802 , boost::ref(body2) 803 ); 804 } 805 806 private: 807 Expr const &if_; 808 }; 809 810 template<typename Expr> 811 struct with_else : Expr 812 { 813 template<typename T> with_elseboost::lambda::with_else814 with_else(T const &expr) 815 : Expr(expr) 816 , else_(*this) 817 {} 818 819 else_generator<Expr> else_; 820 }; 821 822 template<typename Cond> 823 struct if_generator 824 { if_generatorboost::lambda::if_generator825 explicit if_generator(Cond const &c) 826 : cond(c) 827 {} 828 829 template<typename Body> 830 with_else< 831 typename proto::result_of::make_expr< 832 tag::if_ 833 , lldomain 834 , Cond const & 835 , Body const & 836 >::type 837 > const operator []boost::lambda::if_generator838 operator[](Body const &body) const 839 { 840 return proto::make_expr<tag::if_, lldomain>( 841 boost::ref(this->cond) 842 , boost::ref(body) 843 ); 844 } 845 846 private: 847 Cond const &cond; 848 }; 849 850 template<typename Expr> if_(Expr const & expr)851 if_generator<Expr> if_(Expr const &expr) 852 { 853 return if_generator<Expr>(expr); 854 } 855 856 template<typename Init, typename Cond, typename Oper> 857 struct for_generator 858 { for_generatorboost::lambda::for_generator859 explicit for_generator(Init const &i, Cond const &c, Oper const &o) 860 : init(i) 861 , cond(c) 862 , oper(o) 863 {} 864 865 template<typename Body> 866 typename proto::result_of::make_expr< 867 tag::for_ 868 , lldomain 869 , Init const & 870 , Cond const & 871 , Oper const & 872 , Body const & 873 >::type const operator []boost::lambda::for_generator874 operator[](Body const &body) const 875 { 876 return proto::make_expr<tag::for_, lldomain>( 877 boost::ref(this->init) 878 , boost::ref(this->cond) 879 , boost::ref(this->oper) 880 , boost::ref(body) 881 ); 882 } 883 884 private: 885 Init const &init; 886 Cond const &cond; 887 Oper const &oper; 888 }; 889 890 template<typename Init, typename Cond, typename Oper> for_(Init const & i,Cond const & c,Oper const & o)891 for_generator<Init, Cond, Oper> for_(Init const &i, Cond const &c, Oper const &o) 892 { 893 return for_generator<Init, Cond, Oper>(i, c, o); 894 } 895 896 template<typename Body> 897 struct do_while_generator 898 { do_while_generatorboost::lambda::do_while_generator899 explicit do_while_generator(Body const &b) 900 : body(b) 901 {} 902 903 template<typename Cond> 904 typename proto::result_of::make_expr< 905 tag::do_while_ 906 , lldomain 907 , Body const & 908 , Cond const & 909 >::type const operator ()boost::lambda::do_while_generator910 operator()(Cond const &cond) const 911 { 912 return proto::make_expr<tag::do_while_, lldomain>( 913 boost::ref(this->body) 914 , boost::ref(cond) 915 ); 916 } 917 918 private: 919 Body const &body; 920 }; 921 922 template<typename Body> 923 struct do_body 924 { do_bodyboost::lambda::do_body925 explicit do_body(Body const &body) 926 : while_(body) 927 {} 928 929 do_while_generator<Body> while_; 930 }; 931 932 struct do_generator 933 { 934 template<typename Body> operator []boost::lambda::do_generator935 do_body<Body> operator[](Body const &body) const 936 { 937 return do_body<Body>(body); 938 } 939 }; 940 941 do_generator const do_ = {}; 942 943 struct noop_fun 944 { 945 typedef void result_type; operator ()boost::lambda::noop_fun946 void operator()() const {} 947 }; 948 949 typedef llexpr<proto::function<llexpr<proto::terminal<noop_fun>::type> >::type> noop_type; 950 noop_type const noop = {{{{{}}}}}; 951 952 template<typename Init, typename Cond, typename Oper> 953 typename proto::result_of::make_expr< 954 tag::for_ 955 , lldomain 956 , Init const & 957 , Cond const & 958 , Oper const & 959 , noop_type const & 960 >::type const for_loop(Init const & init,Cond const & cond,Oper const & oper)961 for_loop(Init const &init, Cond const &cond, Oper const &oper) 962 { 963 return proto::make_expr<tag::for_, lldomain>( 964 boost::ref(init) 965 , boost::ref(cond) 966 , boost::ref(oper) 967 , boost::ref(noop) 968 ); 969 } 970 971 template<typename Init, typename Cond, typename Oper, typename Body> 972 typename proto::result_of::make_expr< 973 tag::for_ 974 , lldomain 975 , Init const & 976 , Cond const & 977 , Oper const & 978 , Body const & 979 >::type const for_loop(Init const & init,Cond const & cond,Oper const & oper,Body const & body)980 for_loop(Init const &init, Cond const &cond, Oper const &oper, Body const &body) 981 { 982 return proto::make_expr<tag::for_>( 983 boost::ref(init) 984 , boost::ref(cond) 985 , boost::ref(oper) 986 , boost::ref(body) 987 ); 988 } 989 990 template<typename Cond, typename Body> 991 typename proto::result_of::make_expr< 992 tag::while_ 993 , lldomain 994 , Cond const & 995 , Body const & 996 >::type const while_loop(Cond const & cond,Body const & body)997 while_loop(Cond const &cond, Body const &body) 998 { 999 return proto::make_expr<tag::while_, lldomain>( 1000 boost::ref(cond) 1001 , boost::ref(body) 1002 ); 1003 } 1004 1005 template<typename Cond> 1006 typename proto::result_of::make_expr< 1007 tag::while_ 1008 , lldomain 1009 , Cond const & 1010 , noop_type const & 1011 >::type const while_loop(Cond const & cond)1012 while_loop(Cond const &cond) 1013 { 1014 return proto::make_expr<tag::while_, lldomain>( 1015 boost::ref(cond) 1016 , boost::ref(noop) 1017 ); 1018 } 1019 1020 template<typename Cond, typename Body> 1021 typename proto::result_of::make_expr< 1022 tag::do_while_ 1023 , lldomain 1024 , Body const & 1025 , Cond const & 1026 >::type const do_while_loop(Cond const & cond,Body const & body)1027 do_while_loop(Cond const &cond, Body const &body) 1028 { 1029 return proto::make_expr<tag::do_while_, lldomain>( 1030 boost::ref(body) 1031 , boost::ref(cond) 1032 ); 1033 } 1034 1035 template<typename Cond> 1036 typename proto::result_of::make_expr< 1037 tag::do_while_ 1038 , lldomain 1039 , noop_type const & 1040 , Cond const & 1041 >::type const do_while_loop(Cond const & cond)1042 do_while_loop(Cond const &cond) 1043 { 1044 return proto::make_expr<tag::do_while_, lldomain>( 1045 boost::ref(noop) 1046 , boost::ref(cond) 1047 ); 1048 } 1049 1050 template<typename Cond, typename Body1> 1051 typename proto::result_of::make_expr< 1052 tag::if_ 1053 , lldomain 1054 , Cond const & 1055 , Body1 const & 1056 >::type const if_then(Cond const & cond,Body1 const & body1)1057 if_then(Cond const &cond, Body1 const &body1) 1058 { 1059 return proto::make_expr<tag::if_, lldomain>( 1060 boost::ref(cond) 1061 , boost::ref(body1) 1062 ); 1063 } 1064 1065 template<typename Cond, typename Body1, typename Body2> 1066 typename proto::result_of::make_expr< 1067 tag::if_else_ 1068 , lldomain 1069 , Cond const & 1070 , Body1 const & 1071 , Body2 const & 1072 >::type const if_then_else(Cond const & cond,Body1 const & body1,Body2 const & body2)1073 if_then_else(Cond const &cond, Body1 const &body1, Body2 const &body2) 1074 { 1075 return proto::make_expr<tag::if_else_, lldomain>( 1076 boost::ref(cond) 1077 , boost::ref(body1) 1078 , boost::ref(body2) 1079 ); 1080 } 1081 1082 template<typename Cond, typename Body1, typename Body2> 1083 typename proto::result_of::make_expr< 1084 proto::tag::if_else_ 1085 , lldomain 1086 , Cond const & 1087 , Body1 const & 1088 , Body2 const & 1089 >::type const if_then_else_return(Cond const & cond,Body1 const & body1,Body2 const & body2)1090 if_then_else_return(Cond const &cond, Body1 const &body1, Body2 const &body2) 1091 { 1092 return proto::make_expr<proto::tag::if_else_, lldomain>( 1093 boost::ref(cond) 1094 , boost::ref(body1) 1095 , boost::ref(body2) 1096 ); 1097 } 1098 1099 template<typename T> make_const(T const & t)1100 T const &make_const(T const &t) 1101 { 1102 return t; 1103 } 1104 1105 #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \ 1106 template<typename_A(N)> \ 1107 typename proto::result_of::make_expr< \ 1108 proto::tag::function \ 1109 , lldomain \ 1110 , A_const_ref(N) \ 1111 >::type const \ 1112 bind(A_const_ref_a(N)) \ 1113 { \ 1114 return proto::make_expr<proto::tag::function, lldomain>(ref_a(N)); \ 1115 } \ 1116 \ 1117 template<typename Ret, typename_A(N)> \ 1118 typename proto::result_of::make_expr< \ 1119 proto::tag::function \ 1120 , lldomain \ 1121 , A_const_ref(N) \ 1122 >::type const \ 1123 bind(A_const_ref_a(N)) \ 1124 { \ 1125 return proto::make_expr<proto::tag::function, lldomain>(ref_a(N)); \ 1126 } \ 1127 /**/ BOOST_PP_INC(BOOST_PROTO_MAX_ARITY)1128 BOOST_PROTO_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1) 1129 #undef M1 1130 1131 template<typename Ret, typename Expr> 1132 Expr const &ret(Expr const &expr) 1133 { 1134 return expr; 1135 } 1136 1137 template<typename Expr> const_parameters(Expr const & expr)1138 Expr const &const_parameters(Expr const &expr) 1139 { 1140 return expr; 1141 } 1142 1143 template<typename Expr> break_const(Expr const & expr)1144 Expr const &break_const(Expr const &expr) 1145 { 1146 return expr; 1147 } 1148 1149 template<typename Lambda> 1150 proto::unexpr<Lambda> const unlambda(Lambda const & lambda)1151 unlambda(Lambda const &lambda) 1152 { 1153 return proto::unexpr<Lambda>(lambda); 1154 } 1155 1156 template<typename Lambda> 1157 typename proto::result_of::make_expr< 1158 tag::protect 1159 , lldomain 1160 , Lambda const & 1161 >::type const protect(Lambda const & lambda)1162 protect(Lambda const &lambda) 1163 { 1164 return proto::make_expr<tag::protect, lldomain>(boost::ref(lambda)); 1165 } 1166 1167 template<typename T> std_functor(T const & t)1168 T const std_functor(T const &t) 1169 { 1170 return t; 1171 } 1172 1173 template<typename T> 1174 struct ll_static_cast_fun 1175 { 1176 typedef T result_type; 1177 1178 template<typename U> operator ()boost::lambda::ll_static_cast_fun1179 T operator()(U &u) const 1180 { 1181 return static_cast<T>(u); 1182 } 1183 1184 template<typename U> operator ()boost::lambda::ll_static_cast_fun1185 T operator()(U const &u) const 1186 { 1187 return static_cast<T>(u); 1188 } 1189 }; 1190 1191 template<typename T, typename U> 1192 typename proto::result_of::make_expr< 1193 proto::tag::function 1194 , lldomain 1195 , ll_static_cast_fun<T> 1196 , U const & 1197 >::type ll_static_cast(U const & u)1198 ll_static_cast(U const &u) 1199 { 1200 ll_static_cast_fun<T> fun; 1201 return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u)); 1202 } 1203 1204 template<typename T> 1205 struct ll_const_cast_fun 1206 { 1207 typedef T result_type; 1208 1209 template<typename U> operator ()boost::lambda::ll_const_cast_fun1210 T operator()(U &u) const 1211 { 1212 return const_cast<T>(u); 1213 } 1214 1215 template<typename U> operator ()boost::lambda::ll_const_cast_fun1216 T operator()(U const &u) const 1217 { 1218 return const_cast<T>(u); 1219 } 1220 }; 1221 1222 template<typename T, typename U> 1223 typename proto::result_of::make_expr< 1224 proto::tag::function 1225 , lldomain 1226 , ll_const_cast_fun<T> 1227 , U const & 1228 >::type ll_const_cast(U const & u)1229 ll_const_cast(U const &u) 1230 { 1231 ll_const_cast_fun<T> fun; 1232 return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u)); 1233 } 1234 1235 template<typename T> 1236 struct ll_dynamic_cast_fun 1237 { 1238 typedef T result_type; 1239 1240 template<typename U> operator ()boost::lambda::ll_dynamic_cast_fun1241 T operator()(U &u) const 1242 { 1243 return dynamic_cast<T>(u); 1244 } 1245 1246 template<typename U> operator ()boost::lambda::ll_dynamic_cast_fun1247 T operator()(U const &u) const 1248 { 1249 return dynamic_cast<T>(u); 1250 } 1251 }; 1252 1253 template<typename T, typename U> 1254 typename proto::result_of::make_expr< 1255 proto::tag::function 1256 , lldomain 1257 , ll_dynamic_cast_fun<T> 1258 , U const & 1259 >::type ll_dynamic_cast(U const & u)1260 ll_dynamic_cast(U const &u) 1261 { 1262 ll_dynamic_cast_fun<T> fun; 1263 return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u)); 1264 } 1265 1266 template<typename T> 1267 struct ll_reinterpret_cast_fun 1268 { 1269 typedef T result_type; 1270 1271 template<typename U> operator ()boost::lambda::ll_reinterpret_cast_fun1272 T operator()(U &u) const 1273 { 1274 return reinterpret_cast<T>(u); 1275 } 1276 1277 template<typename U> operator ()boost::lambda::ll_reinterpret_cast_fun1278 T operator()(U const &u) const 1279 { 1280 return reinterpret_cast<T>(u); 1281 } 1282 }; 1283 1284 template<typename T, typename U> 1285 typename proto::result_of::make_expr< 1286 proto::tag::function 1287 , lldomain 1288 , ll_reinterpret_cast_fun<T> 1289 , U const & 1290 >::type ll_reinterpret_cast(U const & u)1291 ll_reinterpret_cast(U const &u) 1292 { 1293 ll_reinterpret_cast_fun<T> fun; 1294 return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u)); 1295 } 1296 1297 struct ll_sizeof_fun 1298 { 1299 typedef std::size_t result_type; 1300 1301 template<typename U> operator ()boost::lambda::ll_sizeof_fun1302 std::size_t operator()(U const &) const 1303 { 1304 return sizeof(U); 1305 } 1306 }; 1307 1308 template<typename U> 1309 typename proto::result_of::make_expr< 1310 proto::tag::function 1311 , lldomain 1312 , ll_sizeof_fun 1313 , U const & 1314 >::type ll_sizeof(U const & u)1315 ll_sizeof(U const &u) 1316 { 1317 ll_sizeof_fun fun; 1318 return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u)); 1319 } 1320 1321 struct ll_typeid_fun 1322 { 1323 typedef std::type_info const &result_type; 1324 1325 template<typename U> operator ()boost::lambda::ll_typeid_fun1326 std::type_info const &operator()(U const &) const 1327 { 1328 return typeid(U); 1329 } 1330 }; 1331 1332 template<typename U> 1333 typename proto::result_of::make_expr< 1334 proto::tag::function 1335 , lldomain 1336 , ll_typeid_fun 1337 , U const & 1338 >::type ll_typeid(U const & u)1339 ll_typeid(U const &u) 1340 { 1341 ll_typeid_fun fun; 1342 return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u)); 1343 } 1344 1345 template<typename T> 1346 struct constructor 1347 { 1348 typedef T result_type; 1349 operator ()boost::lambda::constructor1350 T operator()() const 1351 { 1352 return T(); 1353 } 1354 1355 #define M0(Z, N, DATA) \ 1356 template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)> \ 1357 T operator()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) const \ 1358 { \ 1359 return T(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \ 1360 } \ 1361 /**/ 1362 BOOST_PP_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0, ~) 1363 #undef M0 1364 }; 1365 1366 template<typename T> 1367 struct new_ptr 1368 { 1369 typedef T *result_type; 1370 operator ()boost::lambda::new_ptr1371 T *operator()() const 1372 { 1373 return new T(); 1374 } 1375 1376 #define M0(Z, N, DATA) \ 1377 template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)> \ 1378 T *operator()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) const \ 1379 { \ 1380 return new T(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \ 1381 } \ 1382 /**/ 1383 BOOST_PP_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0, ~) 1384 #undef M0 1385 }; 1386 1387 struct destructor 1388 { 1389 typedef void result_type; 1390 1391 template<typename T> operator ()boost::lambda::destructor1392 void operator()(T const &t) const 1393 { 1394 t.~T(); 1395 } 1396 1397 template<typename T> operator ()boost::lambda::destructor1398 void operator()(T *const &t) const 1399 { 1400 (*t).~T(); 1401 } 1402 }; 1403 1404 struct delete_ptr 1405 { 1406 typedef void result_type; 1407 template<typename T> operator ()boost::lambda::delete_ptr1408 void operator()(T *t) const 1409 { 1410 delete t; 1411 } 1412 }; 1413 1414 template<typename T> 1415 struct new_array 1416 { 1417 typedef T *result_type; operator ()boost::lambda::new_array1418 T *operator()(std::size_t n) const 1419 { 1420 return new T[n]; 1421 } 1422 }; 1423 1424 struct delete_array 1425 { 1426 typedef void result_type; 1427 template<typename T> operator ()boost::lambda::delete_array1428 void operator()(T *t) const 1429 { 1430 delete[] t; 1431 } 1432 }; 1433 1434 template<typename T> 1435 struct type2type {}; 1436 1437 struct try_catch_nil {}; 1438 1439 template<typename Head, typename Tail> 1440 struct try_catch_cons : Tail 1441 { 1442 typedef typename Head::proto_tag::exception_type exception_type; 1443 try_catch_consboost::lambda::try_catch_cons1444 try_catch_cons(Head const &head, Tail const &tail) 1445 : Tail(tail) 1446 , head(head) 1447 {} 1448 1449 template<typename State, typename Data> 1450 typename result_of<Tail const(State const &, Data &)>::type operator ()boost::lambda::try_catch_cons1451 operator()(State const &state, Data &data) const 1452 { 1453 return this->invoke(state, data, type2type<exception_type>()); 1454 } 1455 1456 private: 1457 // catch(Exception const &) 1458 template<typename State, typename Data, typename Exception> 1459 typename result_of<Tail const(State const &, Data &)>::type invokeboost::lambda::try_catch_cons1460 invoke(State const &state, Data &data, type2type<Exception>) const 1461 { 1462 typedef typename result_of<Tail const(State const &, Data &)>::type result_type; 1463 try 1464 { 1465 return static_cast<result_type>(this->Tail::operator()(state, data)); 1466 } 1467 catch(Exception const &e) 1468 { 1469 return static_cast<result_type>(eval_lambda(this->head, e, data)); 1470 } 1471 } 1472 1473 // catch(...) 1474 template<typename State, typename Data> 1475 typename result_of<Tail const(State const &, Data &)>::type invokeboost::lambda::try_catch_cons1476 invoke(State const &state, Data &data, type2type<tag::catch_all_>) const 1477 { 1478 typedef typename result_of<Tail const(State const &, Data &)>::type result_type; 1479 try 1480 { 1481 return static_cast<result_type>(this->Tail::operator()(state, data)); 1482 } 1483 catch(...) 1484 { 1485 return static_cast<result_type>(eval_lambda(this->head, tag::catch_all_(), data)); 1486 } 1487 } 1488 1489 Head const &head; 1490 }; 1491 1492 template<typename Head> 1493 struct try_catch_cons<Head, try_catch_nil> : proto::callable 1494 { try_catch_consboost::lambda::try_catch_cons1495 try_catch_cons(Head const &head, try_catch_nil const &) 1496 : head(head) 1497 {} 1498 1499 template<typename Sig> 1500 struct result; 1501 1502 template<typename This, typename State, typename Data> 1503 struct result<This(State, Data)> 1504 : result_of<Eval(Head const &, State, Data)> 1505 {}; 1506 1507 template<typename State, typename Data> 1508 typename result_of<Eval(Head const &, State, Data)>::type operator ()boost::lambda::try_catch_cons1509 operator()(State const &state, Data &data) const 1510 { 1511 return eval_lambda(this->head, state, data); 1512 } 1513 1514 private: 1515 Head const &head; 1516 }; 1517 1518 struct try_catch_fun : proto::callable 1519 { 1520 template<typename Sig> 1521 struct result; 1522 1523 template<typename This, typename Fun, typename State, typename Data> 1524 struct result<This(Fun, State, Data)> 1525 : result_of<Fun(State, Data)> 1526 {}; 1527 1528 template<typename Fun, typename State, typename Data> 1529 typename result_of<Fun(State const &, Data &)>::type operator ()boost::lambda::try_catch_fun1530 operator()(Fun const &fun, State const &state, Data &data) const 1531 { 1532 return fun(state, data); 1533 } 1534 }; 1535 1536 template<> 1537 struct Cases::case_<tag::try_> 1538 : proto::otherwise< 1539 try_catch_fun( 1540 proto::fold< 1541 proto::_ 1542 , try_catch_nil() 1543 , try_catch_cons<proto::_, proto::_state>(proto::_, proto::_state) 1544 > 1545 , proto::_state 1546 , proto::_data 1547 ) 1548 > 1549 {}; 1550 1551 template<typename E, typename Expr> 1552 typename proto::result_of::make_expr<tag::catch_<E>, lldomain, Expr const &>::type const catch_exception(Expr const & expr)1553 catch_exception(Expr const &expr) 1554 { 1555 return proto::make_expr<tag::catch_<E>, lldomain>(boost::ref(expr)); 1556 } 1557 1558 template<typename E> 1559 typename proto::result_of::make_expr<tag::catch_<E>, lldomain, noop_type const &>::type const catch_exception()1560 catch_exception() 1561 { 1562 return proto::make_expr<tag::catch_<E>, lldomain>(boost::ref(noop)); 1563 } 1564 1565 template<typename Expr> 1566 typename proto::result_of::make_expr< 1567 tag::catch_all_ 1568 , lldomain 1569 , Expr const & 1570 >::type const catch_all(Expr const & expr)1571 catch_all(Expr const &expr) 1572 { 1573 return proto::make_expr<tag::catch_all_, lldomain>(boost::ref(expr)); 1574 } 1575 1576 inline 1577 proto::result_of::make_expr<tag::catch_all_, lldomain, noop_type const &>::type const catch_all()1578 catch_all() 1579 { 1580 return proto::make_expr<tag::catch_all_, lldomain>(boost::ref(noop)); 1581 } 1582 1583 #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \ 1584 template<typename_A(N)> \ 1585 typename proto::result_of::make_expr< \ 1586 tag::try_ \ 1587 , lldomain \ 1588 , A_const_ref(N) \ 1589 >::type const \ 1590 try_catch(A_const_ref_a(N)) \ 1591 { \ 1592 return proto::make_expr<tag::try_, lldomain>(ref_a(N)); \ 1593 } \ 1594 /**/ BOOST_PP_INC(BOOST_PROTO_MAX_ARITY)1595 BOOST_PROTO_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1) 1596 #undef M1 1597 1598 template<typename Expr> 1599 typename proto::result_of::make_expr< 1600 proto::tag::function 1601 , lldomain 1602 , throw_fun 1603 , Expr const & 1604 >::type const 1605 throw_exception(Expr const &expr) 1606 { 1607 throw_fun fun; 1608 return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(expr)); 1609 } 1610 1611 inline 1612 proto::result_of::make_expr<proto::tag::function, lldomain, rethrow_fun>::type const rethrow()1613 rethrow() 1614 { 1615 return proto::make_expr<proto::tag::function, lldomain>(rethrow_fun()); 1616 } 1617 1618 struct make_void_fun 1619 { 1620 typedef void result_type; 1621 template<typename T> operator ()boost::lambda::make_void_fun1622 void operator()(T const &) const 1623 {} 1624 }; 1625 1626 template<typename Expr> 1627 typename proto::result_of::make_expr< 1628 proto::tag::function 1629 , lldomain 1630 , make_void_fun 1631 , Expr const & 1632 >::type const make_void(Expr const & expr)1633 make_void(Expr const &expr) 1634 { 1635 make_void_fun fun; 1636 return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(expr)); 1637 } 1638 1639 #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \ 1640 template<typename_A(N)> \ 1641 typename proto::result_of::make_expr< \ 1642 tag::switch_ \ 1643 , lldomain \ 1644 , A_const_ref(N) \ 1645 >::type const \ 1646 switch_statement(A_const_ref_a(N)) \ 1647 { \ 1648 return proto::make_expr<tag::switch_, lldomain>(ref_a(N)); \ 1649 } \ 1650 /**/ BOOST_PP_INC(BOOST_PROTO_MAX_ARITY)1651 BOOST_PROTO_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1) 1652 #undef M1 1653 1654 template<int I, typename Expr> 1655 typename proto::result_of::make_expr<tag::case_<I>, lldomain, Expr const &>::type const 1656 case_statement(Expr const &expr) 1657 { 1658 return proto::make_expr<tag::case_<I>, lldomain>(boost::ref(expr)); 1659 } 1660 1661 template<int I> 1662 typename proto::result_of::make_expr<tag::case_<I>, lldomain, noop_type const &>::type const case_statement()1663 case_statement() 1664 { 1665 return proto::make_expr<tag::case_<I>, lldomain>(boost::ref(noop)); 1666 } 1667 1668 template<typename Expr> 1669 typename proto::result_of::make_expr<tag::default_, lldomain, Expr const &>::type const default_statement(Expr const & expr)1670 default_statement(Expr const &expr) 1671 { 1672 return proto::make_expr<tag::default_, lldomain>(boost::ref(expr)); 1673 } 1674 1675 inline 1676 proto::result_of::make_expr<tag::default_, lldomain, noop_type const &>::type const default_statement()1677 default_statement() 1678 { 1679 return proto::make_expr<tag::default_, lldomain>(boost::ref(noop)); 1680 } 1681 1682 namespace ll 1683 { 1684 struct for_each 1685 { 1686 template<typename Sig> 1687 struct result; 1688 1689 template<typename This, typename Begin, typename End, typename Fun> 1690 struct result<This(Begin, End, Fun)> 1691 : remove_const<typename remove_reference<Fun>::type> 1692 {}; 1693 1694 template<typename InIter, typename Fun> operator ()boost::lambda::ll::for_each1695 Fun operator()(InIter begin, InIter end, Fun fun) const 1696 { 1697 return std::for_each(begin, end, fun); 1698 } 1699 }; 1700 } 1701 1702 }} 1703 1704 namespace boost 1705 { 1706 template<typename Expr> 1707 struct result_of<lambda::llexpr<Expr>()> 1708 : lambda::llexpr<Expr>::template result<lambda::llexpr<Expr>()> 1709 {}; 1710 1711 template<typename Expr> 1712 struct result_of<lambda::llexpr<Expr> const()> 1713 : lambda::llexpr<Expr>::template result<lambda::llexpr<Expr> const()> 1714 {}; 1715 } 1716 1717 #ifdef _MSC_VER 1718 # pragma warning(pop) 1719 #endif 1720 1721 #endif 1722 1723 #else 1724 1725 BOOST_PP_SEQ_FOR_EACH_PRODUCT( 1726 M2, 1727 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), M1, ~) 1728 ) 1729 1730 #endif 1731