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