1 // Boost.Range library 2 // 3 // Copyright Neil Groves & Thorsten Ottosen & Pavol Droba 2003-2004. 4 // Use, modification and distribution is subject to the Boost Software 5 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt) 7 // 8 // For more information, see http://www.boost.org/libs/range/ 9 // 10 // Credits: 11 // 'michel' reported Trac 9072 which included a patch for allowing references 12 // to function types. 13 // 14 #ifndef BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED 15 #define BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED 16 17 #include <boost/config.hpp> // Define __STL_CONFIG_H, if appropriate. 18 #include <boost/detail/workaround.hpp> 19 20 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) 21 #pragma warning( push ) 22 #pragma warning( disable : 4996 ) 23 #endif 24 25 #include <boost/assert.hpp> 26 #include <boost/iterator/iterator_traits.hpp> 27 #include <boost/iterator/iterator_facade.hpp> 28 #include <boost/mpl/if.hpp> 29 #include <boost/mpl/not.hpp> 30 #include <boost/mpl/or.hpp> 31 #include <boost/type_traits/is_abstract.hpp> 32 #include <boost/type_traits/is_array.hpp> 33 #include <boost/type_traits/is_base_and_derived.hpp> 34 #include <boost/type_traits/is_convertible.hpp> 35 #include <boost/type_traits/is_function.hpp> 36 #include <boost/type_traits/is_pointer.hpp> 37 #include <boost/type_traits/is_same.hpp> 38 #include <boost/range/functions.hpp> 39 #include <boost/range/iterator.hpp> 40 #include <boost/range/difference_type.hpp> 41 #include <boost/range/has_range_iterator.hpp> 42 #include <boost/range/algorithm/equal.hpp> 43 #include <boost/range/detail/safe_bool.hpp> 44 #include <boost/utility/enable_if.hpp> 45 #include <boost/next_prior.hpp> 46 #include <iterator> 47 #include <algorithm> 48 #include <cstddef> 49 50 /*! \file 51 Defines the \c iterator_class and related functions. 52 \c iterator_range is a simple wrapper of iterator pair idiom. It provides 53 a rich subset of Container interface. 54 */ 55 56 57 namespace boost 58 { 59 namespace iterator_range_detail 60 { 61 // 62 // The functions adl_begin and adl_end are implemented in a separate 63 // class for gcc-2.9x 64 // 65 template<class IteratorT> 66 struct iterator_range_impl { 67 template< class ForwardRange > adl_beginboost::iterator_range_detail::iterator_range_impl68 static IteratorT adl_begin( ForwardRange& r ) 69 { 70 return IteratorT( boost::begin( r ) ); 71 } 72 73 template< class ForwardRange > adl_endboost::iterator_range_detail::iterator_range_impl74 static IteratorT adl_end( ForwardRange& r ) 75 { 76 return IteratorT( boost::end( r ) ); 77 } 78 }; 79 80 template< class Left, class Right > less_than(const Left & l,const Right & r)81 inline bool less_than( const Left& l, const Right& r ) 82 { 83 return std::lexicographical_compare( boost::begin(l), 84 boost::end(l), 85 boost::begin(r), 86 boost::end(r) ); 87 } 88 89 template< class Left, class Right > greater_than(const Left & l,const Right & r)90 inline bool greater_than( const Left& l, const Right& r ) 91 { 92 return iterator_range_detail::less_than(r,l); 93 } 94 95 template< class Left, class Right > less_or_equal_than(const Left & l,const Right & r)96 inline bool less_or_equal_than( const Left& l, const Right& r ) 97 { 98 return !iterator_range_detail::less_than(r,l); 99 } 100 101 template< class Left, class Right > greater_or_equal_than(const Left & l,const Right & r)102 inline bool greater_or_equal_than( const Left& l, const Right& r ) 103 { 104 return !iterator_range_detail::less_than(l,r); 105 } 106 107 // This version is maintained since it is used in other boost libraries 108 // such as Boost.Assign 109 template< class Left, class Right > equal(const Left & l,const Right & r)110 inline bool equal(const Left& l, const Right& r) 111 { 112 return boost::equal(l, r); 113 } 114 115 struct range_tag 116 { 117 }; 118 119 struct const_range_tag 120 { 121 }; 122 123 struct iterator_range_tag 124 { 125 }; 126 127 typedef char (&incrementable_t)[1]; 128 typedef char (&bidirectional_t)[2]; 129 typedef char (&random_access_t)[3]; 130 131 incrementable_t test_traversal_tag(boost::incrementable_traversal_tag); 132 bidirectional_t test_traversal_tag(boost::bidirectional_traversal_tag); 133 random_access_t test_traversal_tag(boost::random_access_traversal_tag); 134 135 template<std::size_t S> 136 struct pure_iterator_traversal_impl 137 { 138 typedef boost::incrementable_traversal_tag type; 139 }; 140 141 template<> 142 struct pure_iterator_traversal_impl<sizeof(bidirectional_t)> 143 { 144 typedef boost::bidirectional_traversal_tag type; 145 }; 146 147 template<> 148 struct pure_iterator_traversal_impl<sizeof(random_access_t)> 149 { 150 typedef boost::random_access_traversal_tag type; 151 }; 152 153 template<typename IteratorT> 154 struct pure_iterator_traversal 155 { 156 typedef 157 BOOST_DEDUCED_TYPENAME iterator_traversal<IteratorT>::type 158 traversal_t; 159 BOOST_STATIC_CONSTANT( 160 std::size_t, 161 traversal_i = sizeof(iterator_range_detail::test_traversal_tag((traversal_t()))) 162 ); 163 typedef 164 BOOST_DEDUCED_TYPENAME pure_iterator_traversal_impl<traversal_i>::type 165 type; 166 }; 167 168 template<class IteratorT, class TraversalTag> 169 class iterator_range_base 170 : public iterator_range_tag 171 { 172 typedef range_detail::safe_bool< 173 IteratorT iterator_range_base<IteratorT, TraversalTag>::* 174 > safe_bool_t; 175 176 typedef iterator_range_base<IteratorT, TraversalTag> type; 177 178 protected: 179 typedef iterator_range_impl<IteratorT> impl; 180 181 public: 182 typedef BOOST_DEDUCED_TYPENAME 183 safe_bool_t::unspecified_bool_type unspecified_bool_type; 184 185 typedef BOOST_DEDUCED_TYPENAME 186 iterator_value<IteratorT>::type value_type; 187 188 typedef BOOST_DEDUCED_TYPENAME 189 iterator_difference<IteratorT>::type difference_type; 190 191 typedef std::size_t size_type; // note: must be unsigned 192 193 // Needed because value-type is the same for 194 // const and non-const iterators 195 typedef BOOST_DEDUCED_TYPENAME 196 iterator_reference<IteratorT>::type reference; 197 198 //! const_iterator type 199 /*! 200 There is no distinction between const_iterator and iterator. 201 These typedefs are provides to fulfill container interface 202 */ 203 typedef IteratorT const_iterator; 204 //! iterator type 205 typedef IteratorT iterator; 206 207 protected: iterator_range_base()208 iterator_range_base() 209 : m_Begin() 210 , m_End() 211 { 212 } 213 214 template<class Iterator> iterator_range_base(Iterator Begin,Iterator End)215 iterator_range_base(Iterator Begin, Iterator End) 216 : m_Begin(Begin) 217 , m_End(End) 218 { 219 } 220 221 public: begin() const222 IteratorT begin() const 223 { 224 return m_Begin; 225 } 226 end() const227 IteratorT end() const 228 { 229 return m_End; 230 } 231 empty() const232 bool empty() const 233 { 234 return m_Begin == m_End; 235 } 236 operator unspecified_bool_type() const237 operator unspecified_bool_type() const 238 { 239 return safe_bool_t::to_unspecified_bool( 240 m_Begin != m_End, &iterator_range_base::m_Begin); 241 } 242 operator !() const243 bool operator!() const 244 { 245 return empty(); 246 } 247 equal(const iterator_range_base & r) const248 bool equal(const iterator_range_base& r) const 249 { 250 return m_Begin == r.m_Begin && m_End == r.m_End; 251 } 252 front() const253 reference front() const 254 { 255 BOOST_ASSERT(!empty()); 256 return *m_Begin; 257 } 258 drop_front()259 void drop_front() 260 { 261 BOOST_ASSERT(!empty()); 262 ++m_Begin; 263 } 264 drop_front(difference_type n)265 void drop_front(difference_type n) 266 { 267 BOOST_ASSERT(n >= difference_type()); 268 std::advance(this->m_Begin, n); 269 } 270 271 // Deprecated pop_front()272 void pop_front() { drop_front(); } 273 274 protected: 275 template<class Iterator> assign(Iterator first,Iterator last)276 void assign(Iterator first, Iterator last) 277 { 278 m_Begin = first; 279 m_End = last; 280 } 281 282 template<class SinglePassRange> assign(const SinglePassRange & r)283 void assign(const SinglePassRange& r) 284 { 285 m_Begin = impl::adl_begin(r); 286 m_End = impl::adl_end(r); 287 } 288 289 template<class SinglePassRange> assign(SinglePassRange & r)290 void assign(SinglePassRange& r) 291 { 292 m_Begin = impl::adl_begin(r); 293 m_End = impl::adl_end(r); 294 } 295 296 IteratorT m_Begin; 297 IteratorT m_End; 298 }; 299 300 template<class IteratorT> 301 class iterator_range_base<IteratorT, bidirectional_traversal_tag> 302 : public iterator_range_base<IteratorT, incrementable_traversal_tag> 303 { 304 typedef iterator_range_base<IteratorT, incrementable_traversal_tag> base_type; 305 306 protected: iterator_range_base()307 iterator_range_base() 308 { 309 } 310 311 template<class Iterator> iterator_range_base(Iterator first,Iterator last)312 iterator_range_base(Iterator first, Iterator last) 313 : base_type(first, last) 314 { 315 } 316 317 public: 318 typedef BOOST_DEDUCED_TYPENAME base_type::difference_type difference_type; 319 typedef BOOST_DEDUCED_TYPENAME base_type::reference reference; 320 back() const321 reference back() const 322 { 323 BOOST_ASSERT(!this->empty()); 324 return *boost::prior(this->m_End); 325 } 326 drop_back()327 void drop_back() 328 { 329 BOOST_ASSERT(!this->empty()); 330 --this->m_End; 331 } 332 drop_back(difference_type n)333 void drop_back(difference_type n) 334 { 335 BOOST_ASSERT(n >= difference_type()); 336 std::advance(this->m_End, -n); 337 } 338 339 // Deprecated pop_back()340 void pop_back() { drop_back(); } 341 }; 342 343 template<class IteratorT> 344 class iterator_range_base<IteratorT, random_access_traversal_tag> 345 : public iterator_range_base<IteratorT, bidirectional_traversal_tag> 346 { 347 typedef iterator_range_base< 348 IteratorT, bidirectional_traversal_tag> base_type; 349 350 public: 351 typedef BOOST_DEDUCED_TYPENAME 352 boost::mpl::if_< 353 boost::mpl::or_< 354 boost::is_abstract< 355 BOOST_DEDUCED_TYPENAME base_type::value_type 356 >, 357 boost::is_array< 358 BOOST_DEDUCED_TYPENAME base_type::value_type 359 >, 360 boost::is_function< 361 BOOST_DEDUCED_TYPENAME base_type::value_type 362 > 363 >, 364 BOOST_DEDUCED_TYPENAME base_type::reference, 365 BOOST_DEDUCED_TYPENAME base_type::value_type 366 >::type abstract_value_type; 367 368 // Rationale: 369 // typedef these here to reduce verbiage in the implementation of this 370 // type. 371 typedef BOOST_DEDUCED_TYPENAME base_type::difference_type difference_type; 372 typedef BOOST_DEDUCED_TYPENAME base_type::size_type size_type; 373 typedef BOOST_DEDUCED_TYPENAME base_type::reference reference; 374 375 protected: iterator_range_base()376 iterator_range_base() 377 { 378 } 379 380 template<class Iterator> iterator_range_base(Iterator first,Iterator last)381 iterator_range_base(Iterator first, Iterator last) 382 : base_type(first, last) 383 { 384 } 385 386 public: operator [](difference_type at) const387 reference operator[](difference_type at) const 388 { 389 BOOST_ASSERT(at >= 0); 390 BOOST_ASSERT(static_cast<typename base_type::size_type>(at) < size()); 391 return this->m_Begin[at]; 392 } 393 394 // 395 // When storing transform iterators, operator[]() 396 // fails because it returns by reference. Therefore 397 // operator()() is provided for these cases. 398 // operator ()(difference_type at) const399 abstract_value_type operator()(difference_type at) const 400 { 401 BOOST_ASSERT(at >= 0); 402 BOOST_ASSERT(static_cast<typename base_type::size_type>(at) < size()); 403 return this->m_Begin[at]; 404 } 405 size() const406 BOOST_DEDUCED_TYPENAME base_type::size_type size() const 407 { 408 return this->m_End - this->m_Begin; 409 } 410 }; 411 412 } 413 414 // iterator range template class -----------------------------------------// 415 416 //! iterator_range class 417 /*! 418 An \c iterator_range delimits a range in a sequence by beginning and ending iterators. 419 An iterator_range can be passed to an algorithm which requires a sequence as an input. 420 For example, the \c toupper() function may be used most frequently on strings, 421 but can also be used on iterator_ranges: 422 423 \code 424 boost::tolower( find( s, "UPPERCASE STRING" ) ); 425 \endcode 426 427 Many algorithms working with sequences take a pair of iterators, 428 delimiting a working range, as an arguments. The \c iterator_range class is an 429 encapsulation of a range identified by a pair of iterators. 430 It provides a collection interface, 431 so it is possible to pass an instance to an algorithm requiring a collection as an input. 432 */ 433 template<class IteratorT> 434 class iterator_range 435 : public iterator_range_detail::iterator_range_base< 436 IteratorT, 437 BOOST_DEDUCED_TYPENAME iterator_range_detail::pure_iterator_traversal<IteratorT>::type 438 > 439 { 440 typedef iterator_range_detail::iterator_range_base< 441 IteratorT, 442 BOOST_DEDUCED_TYPENAME iterator_range_detail::pure_iterator_traversal<IteratorT>::type 443 > base_type; 444 445 template<class Source> 446 struct is_compatible_range_ 447 : is_convertible< 448 BOOST_DEDUCED_TYPENAME mpl::eval_if< 449 has_range_iterator<Source>, 450 range_iterator<Source>, 451 mpl::identity<void> 452 >::type, 453 BOOST_DEDUCED_TYPENAME base_type::iterator 454 > 455 { 456 }; 457 458 template<class Source> 459 struct is_compatible_range 460 : mpl::and_< 461 mpl::not_< 462 is_convertible< 463 Source, 464 BOOST_DEDUCED_TYPENAME base_type::iterator 465 > 466 >, 467 is_compatible_range_<Source> 468 > 469 { 470 }; 471 472 protected: 473 typedef iterator_range_detail::iterator_range_impl<IteratorT> impl; 474 475 public: 476 typedef iterator_range<IteratorT> type; 477 iterator_range()478 iterator_range() 479 { 480 } 481 482 template<class Iterator> iterator_range(Iterator first,Iterator last)483 iterator_range(Iterator first, Iterator last) 484 : base_type(first, last) 485 { 486 } 487 488 template<class SinglePassRange> iterator_range(const SinglePassRange & r,BOOST_DEDUCED_TYPENAME::boost::enable_if<is_compatible_range<const SinglePassRange>>::type * =0)489 iterator_range( 490 const SinglePassRange& r, 491 BOOST_DEDUCED_TYPENAME ::boost::enable_if< 492 is_compatible_range<const SinglePassRange> 493 >::type* = 0 494 ) 495 : base_type(impl::adl_begin(r), impl::adl_end(r)) 496 { 497 } 498 499 template<class SinglePassRange> iterator_range(SinglePassRange & r,BOOST_DEDUCED_TYPENAME::boost::enable_if<is_compatible_range<SinglePassRange>>::type * =0)500 iterator_range( 501 SinglePassRange& r, 502 BOOST_DEDUCED_TYPENAME ::boost::enable_if< 503 is_compatible_range<SinglePassRange> 504 >::type* = 0 505 ) 506 : base_type(impl::adl_begin(r), impl::adl_end(r)) 507 { 508 } 509 510 template<class SinglePassRange> iterator_range(const SinglePassRange & r,iterator_range_detail::const_range_tag)511 iterator_range(const SinglePassRange& r, 512 iterator_range_detail::const_range_tag) 513 : base_type(impl::adl_begin(r), impl::adl_end(r)) 514 { 515 } 516 517 template<class SinglePassRange> iterator_range(SinglePassRange & r,iterator_range_detail::range_tag)518 iterator_range(SinglePassRange& r, 519 iterator_range_detail::range_tag) 520 : base_type(impl::adl_begin(r), impl::adl_end(r)) 521 { 522 } 523 524 template<class Iterator> operator =(const iterator_range<Iterator> & other)525 iterator_range& operator=(const iterator_range<Iterator>& other) 526 { 527 this->assign(other.begin(), other.end()); 528 return *this; 529 } 530 531 template<class Iterator> operator =(iterator_range<Iterator> & other)532 iterator_range& operator=(iterator_range<Iterator>& other) 533 { 534 this->assign(other.begin(), other.end()); 535 return *this; 536 } 537 538 template<class SinglePassRange> operator =(SinglePassRange & r)539 iterator_range& operator=(SinglePassRange& r) 540 { 541 this->assign(r); 542 return *this; 543 } 544 545 template<class SinglePassRange> operator =(const SinglePassRange & r)546 iterator_range& operator=(const SinglePassRange& r) 547 { 548 this->assign(r); 549 return *this; 550 } 551 advance_begin(BOOST_DEDUCED_TYPENAME base_type::difference_type n)552 iterator_range& advance_begin( 553 BOOST_DEDUCED_TYPENAME base_type::difference_type n) 554 { 555 std::advance(this->m_Begin, n); 556 return *this; 557 } 558 advance_end(BOOST_DEDUCED_TYPENAME base_type::difference_type n)559 iterator_range& advance_end( 560 BOOST_DEDUCED_TYPENAME base_type::difference_type n) 561 { 562 std::advance(this->m_End, n); 563 return *this; 564 } 565 566 protected: 567 // 568 // Allow subclasses an easy way to access the 569 // base type 570 // 571 typedef iterator_range iterator_range_; 572 }; 573 574 // iterator range free-standing operators ---------------------------// 575 576 ///////////////////////////////////////////////////////////////////// 577 // comparison operators 578 ///////////////////////////////////////////////////////////////////// 579 580 template< class IteratorT, class ForwardRange > 581 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 582 mpl::not_<is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 583 bool 584 >::type operator ==(const ForwardRange & l,const iterator_range<IteratorT> & r)585 operator==( const ForwardRange& l, const iterator_range<IteratorT>& r ) 586 { 587 return boost::equal( l, r ); 588 } 589 590 template< class IteratorT, class ForwardRange > 591 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 592 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 593 bool 594 >::type operator !=(const ForwardRange & l,const iterator_range<IteratorT> & r)595 operator!=( const ForwardRange& l, const iterator_range<IteratorT>& r ) 596 { 597 return !boost::equal( l, r ); 598 } 599 600 template< class IteratorT, class ForwardRange > 601 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 602 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 603 bool 604 >::type operator <(const ForwardRange & l,const iterator_range<IteratorT> & r)605 operator<( const ForwardRange& l, const iterator_range<IteratorT>& r ) 606 { 607 return iterator_range_detail::less_than( l, r ); 608 } 609 610 template< class IteratorT, class ForwardRange > 611 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 612 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 613 bool 614 >::type operator <=(const ForwardRange & l,const iterator_range<IteratorT> & r)615 operator<=( const ForwardRange& l, const iterator_range<IteratorT>& r ) 616 { 617 return iterator_range_detail::less_or_equal_than( l, r ); 618 } 619 620 template< class IteratorT, class ForwardRange > 621 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 622 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 623 bool 624 >::type operator >(const ForwardRange & l,const iterator_range<IteratorT> & r)625 operator>( const ForwardRange& l, const iterator_range<IteratorT>& r ) 626 { 627 return iterator_range_detail::greater_than( l, r ); 628 } 629 630 template< class IteratorT, class ForwardRange > 631 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 632 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 633 bool 634 >::type operator >=(const ForwardRange & l,const iterator_range<IteratorT> & r)635 operator>=( const ForwardRange& l, const iterator_range<IteratorT>& r ) 636 { 637 return iterator_range_detail::greater_or_equal_than( l, r ); 638 } 639 640 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING 641 #else 642 template< class Iterator1T, class Iterator2T > 643 inline bool operator ==(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)644 operator==( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) 645 { 646 return boost::equal( l, r ); 647 } 648 649 template< class IteratorT, class ForwardRange > 650 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 651 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 652 bool 653 >::type operator ==(const iterator_range<IteratorT> & l,const ForwardRange & r)654 operator==( const iterator_range<IteratorT>& l, const ForwardRange& r ) 655 { 656 return boost::equal( l, r ); 657 } 658 659 660 template< class Iterator1T, class Iterator2T > 661 inline bool operator !=(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)662 operator!=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) 663 { 664 return !boost::equal( l, r ); 665 } 666 667 template< class IteratorT, class ForwardRange > 668 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 669 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 670 bool 671 >::type operator !=(const iterator_range<IteratorT> & l,const ForwardRange & r)672 operator!=( const iterator_range<IteratorT>& l, const ForwardRange& r ) 673 { 674 return !boost::equal( l, r ); 675 } 676 677 678 template< class Iterator1T, class Iterator2T > 679 inline bool operator <(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)680 operator<( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) 681 { 682 return iterator_range_detail::less_than( l, r ); 683 } 684 685 template< class IteratorT, class ForwardRange > 686 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 687 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 688 bool 689 >::type operator <(const iterator_range<IteratorT> & l,const ForwardRange & r)690 operator<( const iterator_range<IteratorT>& l, const ForwardRange& r ) 691 { 692 return iterator_range_detail::less_than( l, r ); 693 } 694 695 template< class Iterator1T, class Iterator2T > 696 inline bool operator <=(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)697 operator<=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) 698 { 699 return iterator_range_detail::less_or_equal_than( l, r ); 700 } 701 702 template< class IteratorT, class ForwardRange > 703 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 704 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 705 bool 706 >::type operator <=(const iterator_range<IteratorT> & l,const ForwardRange & r)707 operator<=( const iterator_range<IteratorT>& l, const ForwardRange& r ) 708 { 709 return iterator_range_detail::less_or_equal_than( l, r ); 710 } 711 712 template< class Iterator1T, class Iterator2T > 713 inline bool operator >(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)714 operator>( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) 715 { 716 return iterator_range_detail::greater_than( l, r ); 717 } 718 719 template< class IteratorT, class ForwardRange > 720 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 721 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 722 bool 723 >::type operator >(const iterator_range<IteratorT> & l,const ForwardRange & r)724 operator>( const iterator_range<IteratorT>& l, const ForwardRange& r ) 725 { 726 return iterator_range_detail::greater_than( l, r ); 727 } 728 729 template< class Iterator1T, class Iterator2T > 730 inline bool operator >=(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)731 operator>=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) 732 { 733 return iterator_range_detail::greater_or_equal_than( l, r ); 734 } 735 736 template< class IteratorT, class ForwardRange > 737 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 738 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 739 bool 740 >::type operator >=(const iterator_range<IteratorT> & l,const ForwardRange & r)741 operator>=( const iterator_range<IteratorT>& l, const ForwardRange& r ) 742 { 743 return iterator_range_detail::greater_or_equal_than( l, r ); 744 } 745 746 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING 747 748 // iterator range utilities -----------------------------------------// 749 750 //! iterator_range construct helper 751 /*! 752 Construct an \c iterator_range from a pair of iterators 753 754 \param Begin A begin iterator 755 \param End An end iterator 756 \return iterator_range object 757 */ 758 template< typename IteratorT > 759 inline iterator_range< IteratorT > make_iterator_range(IteratorT Begin,IteratorT End)760 make_iterator_range( IteratorT Begin, IteratorT End ) 761 { 762 return iterator_range<IteratorT>( Begin, End ); 763 } 764 765 template<typename IteratorT, typename IntegerT> 766 inline iterator_range<IteratorT> make_iterator_range_n(IteratorT first,IntegerT n)767 make_iterator_range_n(IteratorT first, IntegerT n) 768 { 769 return iterator_range<IteratorT>(first, boost::next(first, n)); 770 } 771 772 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING 773 774 template< typename Range > 775 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > make_iterator_range(Range & r)776 make_iterator_range( Range& r ) 777 { 778 return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > 779 ( boost::begin( r ), boost::end( r ) ); 780 } 781 782 #else 783 //! iterator_range construct helper 784 /*! 785 Construct an \c iterator_range from a \c Range containing the begin 786 and end iterators. 787 */ 788 template< class ForwardRange > 789 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type > make_iterator_range(ForwardRange & r)790 make_iterator_range( ForwardRange& r ) 791 { 792 return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type > 793 ( r, iterator_range_detail::range_tag() ); 794 } 795 796 template< class ForwardRange > 797 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type > make_iterator_range(const ForwardRange & r)798 make_iterator_range( const ForwardRange& r ) 799 { 800 return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type > 801 ( r, iterator_range_detail::const_range_tag() ); 802 } 803 804 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING 805 806 namespace iterator_range_detail 807 { 808 template< class Range > 809 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > make_range_impl(Range & r,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end)810 make_range_impl( Range& r, 811 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, 812 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) 813 { 814 // 815 // Not worth the effort 816 // 817 //if( advance_begin == 0 && advance_end == 0 ) 818 // return make_iterator_range( r ); 819 // 820 821 BOOST_DEDUCED_TYPENAME range_iterator<Range>::type 822 new_begin = boost::begin( r ), 823 new_end = boost::end( r ); 824 std::advance( new_begin, advance_begin ); 825 std::advance( new_end, advance_end ); 826 return make_iterator_range( new_begin, new_end ); 827 } 828 } 829 830 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING 831 832 template< class Range > 833 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > make_iterator_range(Range & r,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end)834 make_iterator_range( Range& r, 835 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, 836 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) 837 { 838 return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); 839 } 840 841 #else 842 843 template< class Range > 844 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > make_iterator_range(Range & r,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end)845 make_iterator_range( Range& r, 846 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, 847 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) 848 { 849 return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); 850 } 851 852 template< class Range > 853 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const Range>::type > make_iterator_range(const Range & r,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end)854 make_iterator_range( const Range& r, 855 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, 856 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) 857 { 858 return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); 859 } 860 861 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING 862 863 //! copy a range into a sequence 864 /*! 865 Construct a new sequence of the specified type from the elements 866 in the given range 867 868 \param Range An input range 869 \return New sequence 870 */ 871 template< typename SeqT, typename Range > copy_range(const Range & r)872 inline SeqT copy_range( const Range& r ) 873 { 874 return SeqT( boost::begin( r ), boost::end( r ) ); 875 } 876 877 } // namespace 'boost' 878 879 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) 880 #pragma warning( pop ) 881 #endif 882 883 #endif 884 885