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