1 /*============================================================================= 2 Copyright (c) 2004 Angus Leeming 3 Copyright (c) 2004 Joel de Guzman 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 ==============================================================================*/ 8 #ifndef BOOST_PHOENIX_STL_CONTAINER_CONTAINER_HPP 9 #define BOOST_PHOENIX_STL_CONTAINER_CONTAINER_HPP 10 11 #include <boost/phoenix/core/limits.hpp> 12 #include <boost/mpl/and.hpp> 13 #include <boost/mpl/not.hpp> 14 #include <boost/mpl/or.hpp> 15 #include <boost/mpl/void.hpp> 16 #include <boost/phoenix/stl/container/detail/container.hpp> 17 #include <boost/phoenix/function/adapt_callable.hpp> 18 #include <boost/type_traits/is_const.hpp> 19 20 namespace boost { namespace phoenix 21 { 22 /////////////////////////////////////////////////////////////////////////////// 23 // 24 // STL container member functions 25 // 26 // Lazy functions for STL container member functions 27 // 28 // These functions provide a mechanism for the lazy evaluation of the 29 // public member functions of the STL containers. For an overview of 30 // what is meant by 'lazy evaluation', see the comments in operators.hpp 31 // and functions.hpp. 32 // 33 // Lazy functions are provided for all of the member functions of the 34 // following containers: 35 // 36 // deque - list - map - multimap - vector - set - multiset. 37 // 38 // Indeed, should *your* class have member functions with the same names 39 // and signatures as those listed below, then it will automatically be 40 // supported. To summarize, lazy functions are provided for member 41 // functions: 42 // 43 // assign - at - back - begin - capacity - clear - empty - end - 44 // erase - front - get_allocator - insert - key_comp - max_size - 45 // pop_back - pop_front - push_back - push_front - rbegin - rend - 46 // reserve - resize . size - splice - value_comp. 47 // 48 // The lazy functions' names are the same as the corresponding member 49 // function. Sample usage: 50 // 51 // "Normal" version "Lazy" version 52 // ---------------- -------------- 53 // my_vector.at(5) phoenix::at(arg1, 5) 54 // my_list.size() phoenix::size(arg1) 55 // my_vector1.swap(my_vector2) phoenix::swap(arg1, arg2) 56 // 57 // Notice that member functions with names that clash with a 58 // function in stl algorithms are absent. This will be provided 59 // in Phoenix's algorithm module. 60 // 61 // No support is provided here for lazy versions of operator+=, 62 // operator[] etc. Such operators are not specific to STL containers and 63 // lazy versions can therefore be found in operators.hpp. 64 // 65 /////////////////////////////////////////////////////////////////////////////// 66 67 /////////////////////////////////////////////////////////////////////////////// 68 // 69 // Lazy member function implementaions. 70 // 71 // The structs below provide the guts of the implementation. Thereafter, 72 // the corresponding lazy function itself is simply: 73 // 74 // function<stl::assign> const assign = stl::assign(); 75 // 76 // The structs provide a nested "result" class template whose 77 // "type" typedef enables the lazy function to ascertain the type 78 // to be returned when it is invoked. 79 // 80 // They also provide operator() member functions with signatures 81 // corresponding to those of the underlying member function of 82 // the STL container. 83 // 84 /////////////////////////////////////////////////////////////////////////////// 85 namespace stl 86 { 87 struct assign 88 { 89 template <typename Sig> 90 struct result; 91 92 template < 93 typename This 94 , typename C 95 , typename Arg1 96 > 97 struct result<This(C&, Arg1&)> 98 { 99 typedef typename add_reference<C>::type type; 100 }; 101 102 template < 103 typename This 104 , typename C 105 , typename Arg1 106 , typename Arg2 107 > 108 struct result<This(C&, Arg1, Arg2)> 109 { 110 typedef typename add_reference<C>::type type; 111 }; 112 113 template < 114 typename This 115 , typename C 116 , typename Arg1 117 , typename Arg2 118 , typename Arg3 119 > 120 struct result<This(C&, Arg1, Arg2, Arg3)> 121 { 122 typedef typename add_reference<C>::type type; 123 }; 124 125 template <typename C, typename Arg1> operator ()boost::phoenix::stl::assign126 C& operator()(C& c, Arg1 const & arg1) const 127 { 128 c.assign(arg1); 129 return c; 130 } 131 132 template <typename C, typename Arg1, typename Arg2> operator ()boost::phoenix::stl::assign133 C& operator()(C& c, Arg1 arg1, Arg2 arg2) const 134 { 135 c.assign(arg1, arg2); 136 return c; 137 } 138 139 template <typename C, typename Arg1, typename Arg2, typename Arg3> operator ()boost::phoenix::stl::assign140 C& operator()( 141 C& c 142 , Arg1 arg1 143 , Arg2 arg2 144 , Arg3 const & arg3 145 ) const 146 { 147 return c.assign(arg1, arg2, arg3); 148 } 149 }; 150 151 struct at_impl 152 { 153 template <typename Sig> 154 struct result; 155 156 template <typename This, typename C, typename Index> 157 struct result<This(C&, Index)> 158 { 159 //typedef typename const_qualified_reference_of<C>::type type; 160 typedef typename C::value_type & type; 161 }; 162 163 template <typename C, typename Index> 164 typename result<at_impl(C&, Index const&)>::type operator ()boost::phoenix::stl::at_impl165 operator()(C& c, Index const &i) const 166 { 167 return c.at(i); 168 } 169 170 template <typename This, typename C, typename Index> 171 struct result<This(C const&, Index)> 172 { 173 typedef typename C::value_type const & type; 174 }; 175 176 template <typename C, typename Index> 177 typename result<at_impl(C const&, Index const&)>::type operator ()boost::phoenix::stl::at_impl178 operator()(C const& c, Index const &i) const 179 { 180 return c.at(i); 181 } 182 }; 183 184 struct back 185 { 186 template <typename Sig> 187 struct result; 188 189 template <typename This, typename C> 190 struct result<This(C&)> 191 { 192 typedef 193 typename const_qualified_reference_of<C>::type 194 type; 195 }; 196 197 template <typename C> 198 typename result<back(C&)>::type operator ()boost::phoenix::stl::back199 operator()(C& c) const 200 { 201 return c.back(); 202 } 203 }; 204 205 struct begin 206 { 207 template <typename Sig> 208 struct result; 209 210 template <typename This, typename C> 211 struct result<This(C&)> 212 { 213 typedef typename const_qualified_iterator_of<C>::type type; 214 }; 215 216 template <typename C> 217 typename result<begin(C&)>::type operator ()boost::phoenix::stl::begin218 operator()(C& c) const 219 { 220 return c.begin(); 221 } 222 }; 223 224 struct capacity 225 { 226 template <typename Sig> 227 struct result; 228 229 template <typename This, typename C> 230 struct result<This(C&)> 231 { 232 typedef typename size_type_of<C>::type type; 233 }; 234 235 template <typename C> 236 typename result<capacity(C&)>::type operator ()boost::phoenix::stl::capacity237 operator()(C const& c) const 238 { 239 return c.capacity(); 240 } 241 }; 242 243 struct clear 244 { 245 typedef void result_type; 246 247 template <typename C> operator ()boost::phoenix::stl::clear248 void operator()(C& c) const 249 { 250 return c.clear(); 251 } 252 }; 253 254 struct empty 255 { 256 typedef bool result_type; 257 258 template <typename C> operator ()boost::phoenix::stl::empty259 bool operator()(C const& c) const 260 { 261 return c.empty(); 262 } 263 }; 264 265 struct end 266 { 267 template <typename Sig> 268 struct result; 269 270 template <typename This, typename C> 271 struct result<This(C&)> 272 { 273 typedef typename const_qualified_iterator_of<C>::type type; 274 }; 275 276 template <typename C> 277 typename result<end(C&)>::type operator ()boost::phoenix::stl::end278 operator()(C& c) const 279 { 280 return c.end(); 281 } 282 }; 283 284 namespace result_of 285 { 286 template <typename C, typename Arg1, typename Arg2 = mpl::void_> 287 struct erase 288 { 289 // MSVC and libc++ always returns iterator even in C++03 mode. 290 typedef 291 boost::mpl::eval_if< 292 is_key_type_of<C, Arg1> 293 , size_type_of<C> 294 #if defined(BOOST_MSVC) /*&& (BOOST_MSVC <= 1500)*/ \ 295 && (defined(BOOST_LIBSTDCXX11) && 40500 <= BOOST_LIBSTDCXX_VERSION) \ 296 && defined(_LIBCPP_VERSION) 297 , iterator_of<C> 298 #else 299 , boost::mpl::identity<void> 300 #endif 301 > 302 assoc_erase_result; 303 304 typedef typename 305 boost::mpl::eval_if_c< 306 has_key_type<C>::value 307 , assoc_erase_result 308 , iterator_of<C> 309 >::type 310 type; 311 }; 312 } 313 314 struct erase 315 { 316 // This mouthful can differentiate between the generic erase 317 // functions (Container == std::deque, std::list, std::vector) and 318 // that specific to Associative Containers. 319 // 320 // where C is a std::deque, std::list, std::vector: 321 // 322 // 1) iterator C::erase(iterator where); 323 // 2) iterator C::erase(iterator first, iterator last); 324 // 325 // where C is a std::map, std::multimap, std::set, or std::multiset: 326 // 327 // 3) size_type M::erase(const Key& keyval); 328 // 4-a) void M::erase(iterator where); 329 // 4-b) iterator M::erase(iterator where); 330 // 5-a) void M::erase(iterator first, iterator last); 331 // 5-b) iterator M::erase(iterator first, iterator last); 332 333 template <typename Sig> 334 struct result; 335 336 template <typename This, typename C, typename Arg1> 337 struct result<This(C&, Arg1)> 338 : result_of::erase<C, Arg1> 339 {}; 340 341 template <typename This, typename C, typename Arg1, typename Arg2> 342 struct result<This(C&, Arg1, Arg2)> 343 : result_of::erase<C, Arg1, Arg2> 344 {}; 345 346 template <typename C, typename Arg1> 347 typename result_of::erase<C, Arg1>::type operator ()boost::phoenix::stl::erase348 operator()(C& c, Arg1 arg1) const 349 { 350 typedef typename result_of::erase<C, Arg1>::type result_type; 351 return static_cast<result_type>(c.erase(arg1)); 352 } 353 354 template <typename C, typename Arg1, typename Arg2> 355 typename result_of::erase<C, Arg1, Arg2>::type operator ()boost::phoenix::stl::erase356 operator()(C& c, Arg1 arg1, Arg2 arg2) const 357 { 358 typedef typename result_of::erase<C, Arg1, Arg2>::type result_type; 359 return static_cast<result_type>(c.erase(arg1, arg2)); 360 } 361 }; 362 363 struct front 364 { 365 template <typename Sig> 366 struct result; 367 368 template <typename This, typename C> 369 struct result<This(C&)> 370 { 371 typedef typename const_qualified_reference_of<C>::type type; 372 }; 373 374 template <typename C> 375 typename result<front(C&)>::type operator ()boost::phoenix::stl::front376 operator()(C& c) const 377 { 378 return c.front(); 379 } 380 }; 381 382 struct get_allocator 383 { 384 template <typename Sig> 385 struct result; 386 387 template <typename This, typename C> 388 struct result<This(C&)> 389 { 390 typedef typename allocator_type_of<C>::type type; 391 }; 392 393 template <typename C> 394 typename result<get_allocator(C const&)>::type operator ()boost::phoenix::stl::get_allocator395 operator()(C& c) const 396 { 397 return c.get_allocator(); 398 } 399 }; 400 401 namespace result_of 402 { 403 template < 404 typename C 405 , typename Arg1 406 , typename Arg2 = mpl::void_ 407 , typename Arg3 = mpl::void_ 408 > 409 class insert 410 { 411 struct pair_iterator_bool 412 { 413 typedef typename std::pair<typename C::iterator, bool> type; 414 }; 415 416 typedef 417 boost::mpl::eval_if< 418 map_insert_returns_pair<typename remove_const<C>::type> 419 , pair_iterator_bool 420 , iterator_of<C> 421 > 422 choice_1; 423 424 typedef 425 boost::mpl::eval_if_c< 426 boost::mpl::and_< 427 boost::is_same<Arg3, mpl::void_> 428 , boost::mpl::not_<boost::is_same<Arg1, Arg2> > 429 >::value 430 , iterator_of<C> 431 , boost::mpl::identity<void> 432 > 433 choice_2; 434 435 public: 436 437 typedef typename 438 boost::mpl::eval_if_c< 439 boost::is_same<Arg2, mpl::void_>::value 440 , choice_1 441 , choice_2 442 >::type 443 type; 444 }; 445 } 446 447 struct insert 448 { 449 // This mouthful can differentiate between the generic insert 450 // functions (Container == deque, list, vector) and those 451 // specific to the two map-types, std::map and std::multimap. 452 // 453 // where C is a std::deque, std::list, std::vector: 454 // 455 // 1) iterator C::insert(iterator where, value_type value); 456 // 2) void C::insert( 457 // iterator where, size_type count, value_type value); 458 // 3) template <typename Iter> 459 // void C::insert(iterator where, Iter first, Iter last); 460 // 461 // where M is a std::map and MM is a std::multimap: 462 // 463 // 4) pair<iterator, bool> M::insert(value_type const&); 464 // 5) iterator MM::insert(value_type const&); 465 // 466 // where M is a std::map or std::multimap: 467 // 468 // 6) template <typename Iter> 469 // void M::insert(Iter first, Iter last); 470 471 template <typename Sig> 472 struct result; 473 474 template < 475 typename This 476 , typename C 477 , typename Arg1 478 > 479 struct result<This(C &, Arg1)> 480 : result_of::insert<C, Arg1> 481 {}; 482 483 template < 484 typename This 485 , typename C 486 , typename Arg1 487 , typename Arg2 488 > 489 struct result<This(C &, Arg1, Arg2)> 490 : result_of::insert<C, Arg1, Arg2> 491 {}; 492 493 template < 494 typename This 495 , typename C 496 , typename Arg1 497 , typename Arg2 498 , typename Arg3 499 > 500 struct result<This(C &, Arg1, Arg2, Arg3)> 501 : result_of::insert<C, Arg1, Arg2, Arg3> 502 {}; 503 504 template <typename C, typename Arg1> 505 typename result<insert(C&, Arg1)>::type operator ()boost::phoenix::stl::insert506 operator()(C& c, Arg1 arg1) const 507 { 508 return c.insert(arg1); 509 } 510 511 template <typename C, typename Arg1, typename Arg2> 512 typename result<insert(C&, Arg1, Arg2)>::type operator ()boost::phoenix::stl::insert513 operator()(C& c, Arg1 arg1, Arg2 arg2) const 514 { 515 typedef typename result<insert(C&, Arg1, Arg2)>::type result_type; 516 return static_cast<result_type>(c.insert(arg1, arg2)); 517 } 518 519 template <typename C, typename Arg1, typename Arg2, typename Arg3> 520 typename result<insert(C&, Arg1, Arg2, Arg3)>::type operator ()boost::phoenix::stl::insert521 operator()(C& c, Arg1 arg1, Arg2 arg2, Arg3 arg3) const 522 { 523 typedef typename result<insert(C&, Arg1, Arg2, Arg3)>::type result_type; 524 return static_cast<result_type>(c.insert(arg1, arg2, arg3)); 525 } 526 }; 527 528 namespace result_of 529 { 530 template <typename C> 531 struct key_comp 532 { 533 typedef typename key_compare_of<C>::type type; 534 }; 535 } 536 537 struct key_comp 538 { 539 template <typename Sig> 540 struct result; 541 542 template <typename This, typename C> 543 struct result<This(C&)> 544 : result_of::key_comp<C> 545 {}; 546 547 template <typename C> 548 typename result_of::key_comp<C>::type operator ()boost::phoenix::stl::key_comp549 operator()(C& c) const 550 { 551 return c.key_comp(); 552 } 553 }; 554 555 struct max_size 556 { 557 template <typename Sig> 558 struct result; 559 560 template <typename This, typename C> 561 struct result<This(C&)> 562 { 563 typedef typename size_type_of<C>::type type; 564 }; 565 566 template <typename C> 567 typename result<max_size(C const&)>::type operator ()boost::phoenix::stl::max_size568 operator()(C& c) const 569 { 570 return c.max_size(); 571 } 572 }; 573 574 struct pop_back 575 { 576 typedef void result_type; 577 578 template <typename C> operator ()boost::phoenix::stl::pop_back579 void operator()(C& c) const 580 { 581 return c.pop_back(); 582 } 583 }; 584 585 struct pop_front 586 { 587 typedef void result_type; 588 589 template <typename C> operator ()boost::phoenix::stl::pop_front590 void operator()(C& c) const 591 { 592 return c.pop_front(); 593 } 594 }; 595 596 struct push_back 597 { 598 typedef void result_type; 599 600 template <typename C, typename Arg> operator ()boost::phoenix::stl::push_back601 void operator()(C& c, Arg const& data) const 602 { 603 return c.push_back(data); 604 } 605 }; 606 607 struct push_front 608 { 609 typedef void result_type; 610 611 template <typename C, typename Arg> operator ()boost::phoenix::stl::push_front612 void operator()(C& c, Arg const& data) const 613 { 614 return c.push_front(data); 615 } 616 }; 617 618 struct rbegin 619 { 620 template <typename Sig> 621 struct result; 622 623 template <typename This, typename C> 624 struct result<This(C&)> 625 { 626 typedef typename 627 const_qualified_reverse_iterator_of<C>::type 628 type; 629 }; 630 631 template <typename C> 632 typename result<rbegin(C&)>::type operator ()boost::phoenix::stl::rbegin633 operator()(C& c) const 634 { 635 return c.rbegin(); 636 } 637 }; 638 639 struct rend 640 { 641 template <typename Sig> 642 struct result; 643 644 template <typename This, typename C> 645 struct result<This(C&)> 646 { 647 typedef typename 648 const_qualified_reverse_iterator_of<C>::type 649 type; 650 }; 651 652 template <typename C> 653 typename result<rend(C&)>::type operator ()boost::phoenix::stl::rend654 operator()(C& c) const 655 { 656 return c.rend(); 657 } 658 }; 659 660 struct reserve 661 { 662 typedef void result_type; 663 664 template <typename C, typename Arg> operator ()boost::phoenix::stl::reserve665 void operator()(C& c, Arg const& count) const 666 { 667 c.reserve(count); 668 } 669 }; 670 671 struct resize 672 { 673 typedef void result_type; 674 675 template <typename C, typename Arg1> operator ()boost::phoenix::stl::resize676 void operator()(C& c, Arg1 const& arg1) const 677 { 678 c.resize(arg1); 679 } 680 681 template <typename C, typename Arg1, typename Arg2> operator ()boost::phoenix::stl::resize682 void operator()(C& c, Arg1 const& arg1, Arg2 const& arg2) const 683 { 684 c.resize(arg1, arg2); 685 } 686 }; 687 688 struct size 689 { 690 template <typename Sig> 691 struct result; 692 693 template <typename This, typename C> 694 struct result<This(C&)> 695 { 696 typedef typename size_type_of<C>::type type; 697 }; 698 699 template <typename C> 700 typename result<size(C&)>::type operator ()boost::phoenix::stl::size701 operator()(C& c) const 702 { 703 return c.size(); 704 } 705 }; 706 707 struct splice 708 { 709 typedef void result_type; 710 711 template <typename C, typename Arg1, typename Arg2> operator ()boost::phoenix::stl::splice712 void operator()(C& c, Arg1 arg1, Arg2 &arg2) const 713 { 714 c.splice(arg1, arg2); 715 } 716 717 template < 718 typename C 719 , typename Arg1 720 , typename Arg2 721 , typename Arg3 722 > operator ()boost::phoenix::stl::splice723 void operator()( 724 C& c 725 , Arg1 arg1 726 , Arg2 & arg2 727 , Arg3 arg3 728 ) const 729 { 730 c.splice(arg1, arg2, arg3); 731 } 732 733 template < 734 typename C 735 , typename Arg1 736 , typename Arg2 737 , typename Arg3 738 , typename Arg4 739 > operator ()boost::phoenix::stl::splice740 void operator()( 741 C c 742 , Arg1 arg1 743 , Arg2 & arg2 744 , Arg3 arg3 745 , Arg4 arg4 746 ) const 747 { 748 c.splice(arg1, arg2, arg3, arg4); 749 } 750 }; 751 752 753 namespace result_of 754 { 755 template <typename C> 756 struct value_comp 757 { 758 typedef typename value_compare_of<C>::type type; 759 }; 760 } 761 762 struct value_comp 763 { 764 template <typename Sig> 765 struct result; 766 767 template <typename This, typename C> 768 struct result<This(C&)> 769 : result_of::value_comp<C> 770 {}; 771 772 template <typename C> 773 typename result_of::value_comp<C>::type operator ()boost::phoenix::stl::value_comp774 operator()(C& c) const 775 { 776 return c.value_comp(); 777 } 778 }; 779 780 } // namespace stl 781 782 /////////////////////////////////////////////////////////////////////////////// 783 // 784 // The lazy functions themselves. 785 // 786 /////////////////////////////////////////////////////////////////////////////// 787 namespace adl_barrier 788 { 789 BOOST_PHOENIX_ADAPT_CALLABLE(assign, boost::phoenix::stl::assign, 2) 790 BOOST_PHOENIX_ADAPT_CALLABLE(assign, boost::phoenix::stl::assign, 3) 791 BOOST_PHOENIX_ADAPT_CALLABLE(assign, boost::phoenix::stl::assign, 4) 792 BOOST_PHOENIX_ADAPT_CALLABLE(at, ::boost::phoenix::stl::at_impl, 2) 793 BOOST_PHOENIX_ADAPT_CALLABLE(back, stl::back, 1) 794 BOOST_PHOENIX_ADAPT_CALLABLE(begin, stl::begin, 1) 795 BOOST_PHOENIX_ADAPT_CALLABLE(capacity, stl::capacity, 1) 796 BOOST_PHOENIX_ADAPT_CALLABLE(clear, stl::clear, 1) 797 BOOST_PHOENIX_ADAPT_CALLABLE(empty, stl::empty, 1) 798 BOOST_PHOENIX_ADAPT_CALLABLE(end, stl::end, 1) 799 BOOST_PHOENIX_ADAPT_CALLABLE(erase, stl::erase, 2) 800 BOOST_PHOENIX_ADAPT_CALLABLE(erase, stl::erase, 3) 801 BOOST_PHOENIX_ADAPT_CALLABLE(front, stl::front, 1) 802 BOOST_PHOENIX_ADAPT_CALLABLE(get_allocator, stl::get_allocator, 1) 803 BOOST_PHOENIX_ADAPT_CALLABLE(insert, stl::insert, 2) 804 BOOST_PHOENIX_ADAPT_CALLABLE(insert, stl::insert, 3) 805 BOOST_PHOENIX_ADAPT_CALLABLE(insert, stl::insert, 4) 806 BOOST_PHOENIX_ADAPT_CALLABLE(key_comp, stl::key_comp, 1) 807 BOOST_PHOENIX_ADAPT_CALLABLE(max_size, stl::max_size, 1) 808 BOOST_PHOENIX_ADAPT_CALLABLE(pop_back, stl::pop_back, 1) 809 BOOST_PHOENIX_ADAPT_CALLABLE(pop_front, stl::pop_front, 1) 810 BOOST_PHOENIX_ADAPT_CALLABLE(push_back, stl::push_back, 2) 811 BOOST_PHOENIX_ADAPT_CALLABLE(push_front, stl::push_front, 2) 812 BOOST_PHOENIX_ADAPT_CALLABLE(rbegin, stl::rbegin, 1) 813 BOOST_PHOENIX_ADAPT_CALLABLE(rend, stl::rend, 1) 814 BOOST_PHOENIX_ADAPT_CALLABLE(reserve, stl::reserve, 2) 815 BOOST_PHOENIX_ADAPT_CALLABLE(resize, stl::resize, 2) 816 BOOST_PHOENIX_ADAPT_CALLABLE(resize, stl::resize, 3) 817 BOOST_PHOENIX_ADAPT_CALLABLE(size, stl::size, 1) 818 BOOST_PHOENIX_ADAPT_CALLABLE(splice, stl::splice, 2) 819 BOOST_PHOENIX_ADAPT_CALLABLE(splice, stl::splice, 3) 820 BOOST_PHOENIX_ADAPT_CALLABLE(splice, stl::splice, 4) 821 BOOST_PHOENIX_ADAPT_CALLABLE(splice, stl::splice, 5) 822 BOOST_PHOENIX_ADAPT_CALLABLE(value_comp, stl::value_comp, 1) 823 } 824 825 using namespace phoenix::adl_barrier; 826 }} // namespace boost::phoenix 827 828 #endif // BOOST_PHOENIX_STL_CONTAINERS_HPP 829