1 /////////////////////////////////////////////////////////////////////////////// 2 /// \file fusion.hpp 3 /// Make any Proto expression a valid Fusion sequence 4 // 5 // Copyright 2008 Eric Niebler. Distributed under the Boost 6 // Software License, Version 1.0. (See accompanying file 7 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 9 #ifndef BOOST_PROTO_FUSION_HPP_EAN_11_04_2006 10 #define BOOST_PROTO_FUSION_HPP_EAN_11_04_2006 11 12 #include <boost/config.hpp> 13 #include <boost/mpl/if.hpp> 14 #include <boost/mpl/bool.hpp> 15 #include <boost/mpl/long.hpp> 16 #include <boost/mpl/sequence_tag_fwd.hpp> 17 #include <boost/utility/enable_if.hpp> 18 #include <boost/fusion/include/is_view.hpp> 19 #include <boost/fusion/include/tag_of_fwd.hpp> 20 #include <boost/fusion/include/category_of.hpp> 21 #include <boost/fusion/include/iterator_base.hpp> 22 #include <boost/fusion/include/intrinsic.hpp> 23 #include <boost/fusion/include/single_view.hpp> 24 #include <boost/fusion/include/transform.hpp> 25 #include <boost/fusion/include/as_list.hpp> 26 #include <boost/fusion/include/is_segmented.hpp> 27 #include <boost/fusion/sequence/comparison/enable_comparison.hpp> 28 #include <boost/proto/proto_fwd.hpp> 29 #include <boost/proto/traits.hpp> 30 #include <boost/proto/eval.hpp> 31 #include <boost/proto/make_expr.hpp> 32 33 #ifdef BOOST_MSVC 34 #pragma warning(push) 35 #pragma warning(disable : 4510) // default constructor could not be generated 36 #pragma warning(disable : 4512) // assignment operator could not be generated 37 #pragma warning(disable : 4610) // can never be instantiated - user defined constructor required 38 #endif 39 40 namespace boost { namespace proto 41 { 42 namespace detail 43 { 44 template<typename Expr, long Pos> 45 struct expr_iterator 46 : fusion::iterator_base<expr_iterator<Expr, Pos> > 47 { 48 typedef Expr expr_type; 49 static const long index = Pos; 50 typedef fusion::random_access_traversal_tag category; 51 typedef 52 tag::proto_expr_iterator< 53 typename Expr::proto_tag 54 , typename Expr::proto_domain 55 > 56 fusion_tag; 57 expr_iteratorboost::proto::detail::expr_iterator58 explicit expr_iterator(Expr &e) 59 : expr(e) 60 {} 61 62 Expr &expr; 63 }; 64 65 template<typename Tag> 66 struct as_element 67 { 68 template<typename Sig> 69 struct result; 70 71 template<typename This, typename Expr> 72 struct result<This(Expr)> 73 : result<This(Expr const &)> 74 {}; 75 76 template<typename This, typename Expr> 77 struct result<This(Expr &)> 78 : mpl::if_c< 79 is_same<Tag, typename Expr::proto_tag>::value 80 , flat_view<Expr> 81 , fusion::single_view<Expr &> 82 > 83 {}; 84 85 template<typename Expr> 86 typename result<as_element(Expr &)>::type const operator ()boost::proto::detail::as_element87 operator ()(Expr &e) const 88 { 89 return typename result<as_element(Expr &)>::type(e); 90 } 91 92 template<typename Expr> 93 typename result<as_element(Expr const &)>::type const operator ()boost::proto::detail::as_element94 operator ()(Expr const &e) const 95 { 96 return typename result<as_element(Expr const &)>::type(e); 97 } 98 }; 99 100 template<typename Expr> 101 struct flat_view 102 : fusion::sequence_base<flat_view<Expr> > 103 { 104 typedef fusion::forward_traversal_tag category; 105 typedef 106 tag::proto_flat_view< 107 typename Expr::proto_tag 108 , typename Expr::proto_domain 109 > 110 fusion_tag; 111 typedef 112 typename fusion::result_of::as_list< 113 typename fusion::result_of::transform< 114 Expr 115 , as_element<typename Expr::proto_tag> 116 >::type 117 >::type 118 segments_type; 119 flat_viewboost::proto::detail::flat_view120 explicit flat_view(Expr &e) 121 : segs_(fusion::as_list(fusion::transform(e, as_element<typename Expr::proto_tag>()))) 122 {} 123 124 segments_type segs_; 125 }; 126 } 127 128 namespace result_of 129 { 130 template<typename Expr> 131 struct flatten 132 : flatten<Expr const &> 133 {}; 134 135 template<typename Expr> 136 struct flatten<Expr &> 137 { 138 typedef detail::flat_view<Expr> type; 139 }; 140 } 141 142 namespace functional 143 { 144 /// \brief A PolymorphicFunctionObject type that returns a "flattened" 145 /// view of a Proto expression tree. 146 /// 147 /// A PolymorphicFunctionObject type that returns a "flattened" 148 /// view of a Proto expression tree. For a tree with a top-most node 149 /// tag of type \c T, the elements of the flattened sequence are 150 /// determined by recursing into each child node with the same 151 /// tag type and returning those nodes of different type. So for 152 /// instance, the Proto expression tree corresponding to the 153 /// expression <tt>a | b | c</tt> has a flattened view with elements 154 /// [a, b, c], even though the tree is grouped as 155 /// <tt>((a | b) | c)</tt>. 156 struct flatten 157 { 158 BOOST_PROTO_CALLABLE() 159 160 template<typename Sig> 161 struct result; 162 163 template<typename This, typename Expr> 164 struct result<This(Expr)> 165 : result<This(Expr const &)> 166 {}; 167 168 template<typename This, typename Expr> 169 struct result<This(Expr &)> 170 { 171 typedef proto::detail::flat_view<Expr> type; 172 }; 173 174 template<typename Expr> 175 proto::detail::flat_view<Expr> const operator ()boost::proto::functional::flatten176 operator ()(Expr &e) const 177 { 178 return proto::detail::flat_view<Expr>(e); 179 } 180 181 template<typename Expr> 182 proto::detail::flat_view<Expr const> const operator ()boost::proto::functional::flatten183 operator ()(Expr const &e) const 184 { 185 return proto::detail::flat_view<Expr const>(e); 186 } 187 }; 188 } 189 190 /// \brief A function that returns a "flattened" 191 /// view of a Proto expression tree. 192 /// 193 /// For a tree with a top-most node 194 /// tag of type \c T, the elements of the flattened sequence are 195 /// determined by recursing into each child node with the same 196 /// tag type and returning those nodes of different type. So for 197 /// instance, the Proto expression tree corresponding to the 198 /// expression <tt>a | b | c</tt> has a flattened view with elements 199 /// [a, b, c], even though the tree is grouped as 200 /// <tt>((a | b) | c)</tt>. 201 template<typename Expr> 202 proto::detail::flat_view<Expr> const flatten(Expr & e)203 flatten(Expr &e) 204 { 205 return proto::detail::flat_view<Expr>(e); 206 } 207 208 /// \overload 209 /// 210 template<typename Expr> 211 proto::detail::flat_view<Expr const> const flatten(Expr const & e)212 flatten(Expr const &e) 213 { 214 return proto::detail::flat_view<Expr const>(e); 215 } 216 217 /// INTERNAL ONLY 218 /// 219 template<typename Context> 220 struct eval_fun 221 : proto::callable 222 { eval_funboost::proto::eval_fun223 explicit eval_fun(Context &ctx) 224 : ctx_(ctx) 225 {} 226 227 template<typename Sig> 228 struct result; 229 230 template<typename This, typename Expr> 231 struct result<This(Expr)> 232 : result<This(Expr const &)> 233 {}; 234 235 template<typename This, typename Expr> 236 struct result<This(Expr &)> 237 : proto::result_of::eval<Expr, Context> 238 {}; 239 240 template<typename Expr> 241 typename proto::result_of::eval<Expr, Context>::type operator ()boost::proto::eval_fun242 operator ()(Expr &e) const 243 { 244 return proto::eval(e, this->ctx_); 245 } 246 247 template<typename Expr> 248 typename proto::result_of::eval<Expr const, Context>::type operator ()boost::proto::eval_fun249 operator ()(Expr const &e) const 250 { 251 return proto::eval(e, this->ctx_); 252 } 253 254 private: 255 Context &ctx_; 256 }; 257 258 /// INTERNAL ONLY 259 /// 260 template<typename Context> 261 struct is_callable<eval_fun<Context> > 262 : mpl::true_ 263 {}; 264 }} 265 266 namespace boost { namespace fusion 267 { 268 namespace extension 269 { 270 template<typename Tag> 271 struct is_sequence_impl; 272 273 template<typename Tag, typename Domain> 274 struct is_sequence_impl<proto::tag::proto_flat_view<Tag, Domain> > 275 { 276 template<typename Sequence> 277 struct apply 278 : mpl::true_ 279 {}; 280 }; 281 282 template<typename Tag, typename Domain> 283 struct is_sequence_impl<proto::tag::proto_expr<Tag, Domain> > 284 { 285 template<typename Sequence> 286 struct apply 287 : mpl::true_ 288 {}; 289 }; 290 291 template<typename Tag> 292 struct is_view_impl; 293 294 template<typename Tag, typename Domain> 295 struct is_view_impl<proto::tag::proto_flat_view<Tag, Domain> > 296 { 297 template<typename Sequence> 298 struct apply 299 : mpl::true_ 300 {}; 301 }; 302 303 template<typename Tag, typename Domain> 304 struct is_view_impl<proto::tag::proto_expr<Tag, Domain> > 305 { 306 template<typename Sequence> 307 struct apply 308 : mpl::false_ 309 {}; 310 }; 311 312 template<typename Tag> 313 struct value_of_impl; 314 315 template<typename Tag, typename Domain> 316 struct value_of_impl<proto::tag::proto_expr_iterator<Tag, Domain> > 317 { 318 template< 319 typename Iterator 320 , long Arity = proto::arity_of<typename Iterator::expr_type>::value 321 > 322 struct apply 323 { 324 typedef 325 typename proto::result_of::child_c< 326 typename Iterator::expr_type 327 , Iterator::index 328 >::value_type 329 type; 330 }; 331 332 template<typename Iterator> 333 struct apply<Iterator, 0> 334 { 335 typedef 336 typename proto::result_of::value< 337 typename Iterator::expr_type 338 >::value_type 339 type; 340 }; 341 }; 342 343 template<typename Tag> 344 struct deref_impl; 345 346 template<typename Tag, typename Domain> 347 struct deref_impl<proto::tag::proto_expr_iterator<Tag, Domain> > 348 { 349 template< 350 typename Iterator 351 , long Arity = proto::arity_of<typename Iterator::expr_type>::value 352 > 353 struct apply 354 { 355 typedef 356 typename proto::result_of::child_c< 357 typename Iterator::expr_type & 358 , Iterator::index 359 >::type 360 type; 361 callboost::fusion::extension::deref_impl::apply362 static type call(Iterator const &iter) 363 { 364 return proto::child_c<Iterator::index>(iter.expr); 365 } 366 }; 367 368 template<typename Iterator> 369 struct apply<Iterator, 0> 370 { 371 typedef 372 typename proto::result_of::value< 373 typename Iterator::expr_type & 374 >::type 375 type; 376 callboost::fusion::extension::deref_impl::apply377 static type call(Iterator const &iter) 378 { 379 return proto::value(iter.expr); 380 } 381 }; 382 }; 383 384 template<typename Tag> 385 struct advance_impl; 386 387 template<typename Tag, typename Domain> 388 struct advance_impl<proto::tag::proto_expr_iterator<Tag, Domain> > 389 { 390 template<typename Iterator, typename N> 391 struct apply 392 { 393 typedef 394 proto::detail::expr_iterator< 395 typename Iterator::expr_type 396 , Iterator::index + N::value 397 > 398 type; 399 callboost::fusion::extension::advance_impl::apply400 static type call(Iterator const &iter) 401 { 402 return type(iter.expr); 403 } 404 }; 405 }; 406 407 template<typename Tag> 408 struct distance_impl; 409 410 template<typename Tag, typename Domain> 411 struct distance_impl<proto::tag::proto_expr_iterator<Tag, Domain> > 412 { 413 template<typename IteratorFrom, typename IteratorTo> 414 struct apply 415 : mpl::long_<IteratorTo::index - IteratorFrom::index> 416 {}; 417 }; 418 419 template<typename Tag> 420 struct next_impl; 421 422 template<typename Tag, typename Domain> 423 struct next_impl<proto::tag::proto_expr_iterator<Tag, Domain> > 424 { 425 template<typename Iterator> 426 struct apply 427 : advance_impl<proto::tag::proto_expr_iterator<Tag, Domain> >::template apply<Iterator, mpl::long_<1> > 428 {}; 429 }; 430 431 template<typename Tag> 432 struct prior_impl; 433 434 template<typename Tag, typename Domain> 435 struct prior_impl<proto::tag::proto_expr_iterator<Tag, Domain> > 436 { 437 template<typename Iterator> 438 struct apply 439 : advance_impl<proto::tag::proto_expr_iterator<Tag, Domain> >::template apply<Iterator, mpl::long_<-1> > 440 {}; 441 }; 442 443 template<typename Tag> 444 struct category_of_impl; 445 446 template<typename Tag, typename Domain> 447 struct category_of_impl<proto::tag::proto_expr<Tag, Domain> > 448 { 449 template<typename Sequence> 450 struct apply 451 { 452 typedef random_access_traversal_tag type; 453 }; 454 }; 455 456 template<typename Tag> 457 struct size_impl; 458 459 template<typename Tag, typename Domain> 460 struct size_impl<proto::tag::proto_expr<Tag, Domain> > 461 { 462 template<typename Sequence> 463 struct apply 464 : mpl::long_<0 == Sequence::proto_arity_c ? 1 : Sequence::proto_arity_c> 465 {}; 466 }; 467 468 template<typename Tag> 469 struct begin_impl; 470 471 template<typename Tag, typename Domain> 472 struct begin_impl<proto::tag::proto_expr<Tag, Domain> > 473 { 474 template<typename Sequence> 475 struct apply 476 { 477 typedef proto::detail::expr_iterator<Sequence, 0> type; 478 callboost::fusion::extension::begin_impl::apply479 static type call(Sequence &seq) 480 { 481 return type(seq); 482 } 483 }; 484 }; 485 486 template<typename Tag> 487 struct end_impl; 488 489 template<typename Tag, typename Domain> 490 struct end_impl<proto::tag::proto_expr<Tag, Domain> > 491 { 492 template<typename Sequence> 493 struct apply 494 { 495 typedef 496 proto::detail::expr_iterator< 497 Sequence 498 , 0 == Sequence::proto_arity_c ? 1 : Sequence::proto_arity_c 499 > 500 type; 501 callboost::fusion::extension::end_impl::apply502 static type call(Sequence &seq) 503 { 504 return type(seq); 505 } 506 }; 507 }; 508 509 template<typename Tag> 510 struct value_at_impl; 511 512 template<typename Tag, typename Domain> 513 struct value_at_impl<proto::tag::proto_expr<Tag, Domain> > 514 { 515 template< 516 typename Sequence 517 , typename Index 518 , long Arity = proto::arity_of<Sequence>::value 519 > 520 struct apply 521 { 522 typedef 523 typename proto::result_of::child_c< 524 Sequence 525 , Index::value 526 >::value_type 527 type; 528 }; 529 530 template<typename Sequence, typename Index> 531 struct apply<Sequence, Index, 0> 532 { 533 typedef 534 typename proto::result_of::value< 535 Sequence 536 >::value_type 537 type; 538 }; 539 }; 540 541 template<typename Tag> 542 struct at_impl; 543 544 template<typename Tag, typename Domain> 545 struct at_impl<proto::tag::proto_expr<Tag, Domain> > 546 { 547 template< 548 typename Sequence 549 , typename Index 550 , long Arity = proto::arity_of<Sequence>::value 551 > 552 struct apply 553 { 554 typedef 555 typename proto::result_of::child_c< 556 Sequence & 557 , Index::value 558 >::type 559 type; 560 callboost::fusion::extension::at_impl::apply561 static type call(Sequence &seq) 562 { 563 return proto::child_c<Index::value>(seq); 564 } 565 }; 566 567 template<typename Sequence, typename Index> 568 struct apply<Sequence, Index, 0> 569 { 570 typedef 571 typename proto::result_of::value< 572 Sequence & 573 >::type 574 type; 575 callboost::fusion::extension::at_impl::apply576 static type call(Sequence &seq) 577 { 578 return proto::value(seq); 579 } 580 }; 581 }; 582 583 template<typename Tag> 584 struct convert_impl; 585 586 template<typename Tag, typename Domain> 587 struct convert_impl<proto::tag::proto_expr<Tag, Domain> > 588 { 589 template<typename Sequence> 590 struct apply 591 { 592 typedef 593 typename proto::result_of::unpack_expr< 594 Tag 595 , Domain 596 , Sequence 597 >::type 598 type; 599 callboost::fusion::extension::convert_impl::apply600 static type call(Sequence& seq) 601 { 602 return proto::unpack_expr<Tag, Domain>(seq); 603 } 604 }; 605 }; 606 607 template<typename Tag, typename Domain> 608 struct convert_impl<proto::tag::proto_flat_view<Tag, Domain> > 609 { 610 template<typename Sequence> 611 struct apply 612 { 613 typedef 614 typename proto::result_of::unpack_expr< 615 Tag 616 , Domain 617 , Sequence 618 >::type 619 type; 620 callboost::fusion::extension::convert_impl::apply621 static type call(Sequence& seq) 622 { 623 return proto::unpack_expr<Tag, Domain>(seq); 624 } 625 }; 626 }; 627 628 template<typename Tag> 629 struct is_segmented_impl; 630 631 template<typename Tag, typename Domain> 632 struct is_segmented_impl<proto::tag::proto_flat_view<Tag, Domain> > 633 { 634 template<typename Iterator> 635 struct apply 636 : mpl::true_ 637 {}; 638 }; 639 640 template<typename Tag> 641 struct segments_impl; 642 643 template<typename Tag, typename Domain> 644 struct segments_impl<proto::tag::proto_flat_view<Tag, Domain> > 645 { 646 template<typename Sequence> 647 struct apply 648 { 649 typedef typename Sequence::segments_type const &type; 650 callboost::fusion::extension::segments_impl::apply651 static type call(Sequence &sequence) 652 { 653 return sequence.segs_; 654 } 655 }; 656 }; 657 658 template<typename Tag, typename Domain> 659 struct category_of_impl<proto::tag::proto_flat_view<Tag, Domain> > 660 { 661 template<typename Sequence> 662 struct apply 663 { 664 typedef forward_traversal_tag type; 665 }; 666 }; 667 } 668 669 namespace traits 670 { 671 template<typename Seq1, typename Seq2> 672 struct enable_equality< 673 Seq1 674 , Seq2 675 , typename enable_if_c< 676 mpl::or_< 677 proto::is_expr<Seq1> 678 , proto::is_expr<Seq2> 679 >::value 680 >::type 681 > 682 : mpl::false_ 683 {}; 684 685 template<typename Seq1, typename Seq2> 686 struct enable_comparison< 687 Seq1 688 , Seq2 689 , typename enable_if_c< 690 mpl::or_< 691 proto::is_expr<Seq1> 692 , proto::is_expr<Seq2> 693 >::value 694 >::type 695 > 696 : mpl::false_ 697 {}; 698 } 699 }} 700 701 namespace boost { namespace mpl 702 { 703 template<typename Tag, typename Args, long Arity> 704 struct sequence_tag< proto::expr<Tag, Args, Arity> > 705 { 706 typedef fusion::fusion_sequence_tag type; 707 }; 708 709 template<typename Tag, typename Args, long Arity> 710 struct sequence_tag< proto::basic_expr<Tag, Args, Arity> > 711 { 712 typedef fusion::fusion_sequence_tag type; 713 }; 714 }} 715 716 #ifdef BOOST_MSVC 717 #pragma warning(pop) 718 #endif 719 720 #endif 721