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 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 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 template<class Source> 458 struct is_compatible_range 459 : mpl::and_< 460 mpl::not_< 461 is_convertible< 462 Source, 463 BOOST_DEDUCED_TYPENAME base_type::iterator 464 > 465 >, 466 is_compatible_range_<Source> 467 > 468 { 469 }; 470 471 protected: 472 typedef iterator_range_detail::iterator_range_impl<IteratorT> impl; 473 474 public: 475 typedef iterator_range<IteratorT> type; 476 iterator_range()477 iterator_range() 478 { 479 } 480 481 template<class Iterator> iterator_range(Iterator first,Iterator last)482 iterator_range(Iterator first, Iterator last) 483 : base_type(first, last) 484 { 485 } 486 487 template<class SinglePassRange> iterator_range(const SinglePassRange & r,BOOST_DEDUCED_TYPENAME::boost::enable_if<is_compatible_range<const SinglePassRange>>::type * =0)488 iterator_range( 489 const SinglePassRange& r, 490 BOOST_DEDUCED_TYPENAME ::boost::enable_if< 491 is_compatible_range<const SinglePassRange> 492 >::type* = 0 493 ) 494 : base_type(impl::adl_begin(r), impl::adl_end(r)) 495 { 496 } 497 498 template<class SinglePassRange> iterator_range(SinglePassRange & r,BOOST_DEDUCED_TYPENAME::boost::enable_if<is_compatible_range<SinglePassRange>>::type * =0)499 iterator_range( 500 SinglePassRange& r, 501 BOOST_DEDUCED_TYPENAME ::boost::enable_if< 502 is_compatible_range<SinglePassRange> 503 >::type* = 0 504 ) 505 : base_type(impl::adl_begin(r), impl::adl_end(r)) 506 { 507 } 508 509 template<class SinglePassRange> iterator_range(const SinglePassRange & r,iterator_range_detail::const_range_tag)510 iterator_range(const SinglePassRange& r, 511 iterator_range_detail::const_range_tag) 512 : base_type(impl::adl_begin(r), impl::adl_end(r)) 513 { 514 } 515 516 template<class SinglePassRange> iterator_range(SinglePassRange & r,iterator_range_detail::range_tag)517 iterator_range(SinglePassRange& r, 518 iterator_range_detail::range_tag) 519 : base_type(impl::adl_begin(r), impl::adl_end(r)) 520 { 521 } 522 523 template<class Iterator> operator =(const iterator_range<Iterator> & other)524 iterator_range& operator=(const iterator_range<Iterator>& other) 525 { 526 this->assign(other.begin(), other.end()); 527 return *this; 528 } 529 530 template<class Iterator> operator =(iterator_range<Iterator> & other)531 iterator_range& operator=(iterator_range<Iterator>& other) 532 { 533 this->assign(other.begin(), other.end()); 534 return *this; 535 } 536 537 template<class SinglePassRange> operator =(SinglePassRange & r)538 iterator_range& operator=(SinglePassRange& r) 539 { 540 this->assign(r); 541 return *this; 542 } 543 544 template<class SinglePassRange> operator =(const SinglePassRange & r)545 iterator_range& operator=(const SinglePassRange& r) 546 { 547 this->assign(r); 548 return *this; 549 } 550 advance_begin(BOOST_DEDUCED_TYPENAME base_type::difference_type n)551 iterator_range& advance_begin( 552 BOOST_DEDUCED_TYPENAME base_type::difference_type n) 553 { 554 std::advance(this->m_Begin, n); 555 return *this; 556 } 557 advance_end(BOOST_DEDUCED_TYPENAME base_type::difference_type n)558 iterator_range& advance_end( 559 BOOST_DEDUCED_TYPENAME base_type::difference_type n) 560 { 561 std::advance(this->m_End, n); 562 return *this; 563 } 564 565 protected: 566 // 567 // Allow subclasses an easy way to access the 568 // base type 569 // 570 typedef iterator_range iterator_range_; 571 }; 572 573 // iterator range free-standing operators ---------------------------// 574 575 ///////////////////////////////////////////////////////////////////// 576 // comparison operators 577 ///////////////////////////////////////////////////////////////////// 578 579 template< class IteratorT, class ForwardRange > 580 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 581 mpl::not_<is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 582 bool 583 >::type operator ==(const ForwardRange & l,const iterator_range<IteratorT> & r)584 operator==( const ForwardRange& l, const iterator_range<IteratorT>& r ) 585 { 586 return boost::equal( l, r ); 587 } 588 589 template< class IteratorT, class ForwardRange > 590 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 591 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 592 bool 593 >::type operator !=(const ForwardRange & l,const iterator_range<IteratorT> & r)594 operator!=( const ForwardRange& l, const iterator_range<IteratorT>& r ) 595 { 596 return !boost::equal( l, r ); 597 } 598 599 template< class IteratorT, class ForwardRange > 600 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 601 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 602 bool 603 >::type operator <(const ForwardRange & l,const iterator_range<IteratorT> & r)604 operator<( const ForwardRange& l, const iterator_range<IteratorT>& r ) 605 { 606 return iterator_range_detail::less_than( l, r ); 607 } 608 609 template< class IteratorT, class ForwardRange > 610 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 611 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 612 bool 613 >::type operator <=(const ForwardRange & l,const iterator_range<IteratorT> & r)614 operator<=( const ForwardRange& l, const iterator_range<IteratorT>& r ) 615 { 616 return iterator_range_detail::less_or_equal_than( l, r ); 617 } 618 619 template< class IteratorT, class ForwardRange > 620 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 621 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 622 bool 623 >::type operator >(const ForwardRange & l,const iterator_range<IteratorT> & r)624 operator>( const ForwardRange& l, const iterator_range<IteratorT>& r ) 625 { 626 return iterator_range_detail::greater_than( l, r ); 627 } 628 629 template< class IteratorT, class ForwardRange > 630 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 631 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 632 bool 633 >::type operator >=(const ForwardRange & l,const iterator_range<IteratorT> & r)634 operator>=( const ForwardRange& l, const iterator_range<IteratorT>& r ) 635 { 636 return iterator_range_detail::greater_or_equal_than( l, r ); 637 } 638 639 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING 640 #else 641 template< class Iterator1T, class Iterator2T > 642 inline bool operator ==(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)643 operator==( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) 644 { 645 return boost::equal( l, r ); 646 } 647 648 template< class IteratorT, class ForwardRange > 649 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 650 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 651 bool 652 >::type operator ==(const iterator_range<IteratorT> & l,const ForwardRange & r)653 operator==( const iterator_range<IteratorT>& l, const ForwardRange& r ) 654 { 655 return boost::equal( l, r ); 656 } 657 658 659 template< class Iterator1T, class Iterator2T > 660 inline bool operator !=(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)661 operator!=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) 662 { 663 return !boost::equal( l, r ); 664 } 665 666 template< class IteratorT, class ForwardRange > 667 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 668 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 669 bool 670 >::type operator !=(const iterator_range<IteratorT> & l,const ForwardRange & r)671 operator!=( const iterator_range<IteratorT>& l, const ForwardRange& r ) 672 { 673 return !boost::equal( l, r ); 674 } 675 676 677 template< class Iterator1T, class Iterator2T > 678 inline bool operator <(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)679 operator<( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) 680 { 681 return iterator_range_detail::less_than( l, r ); 682 } 683 684 template< class IteratorT, class ForwardRange > 685 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 686 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 687 bool 688 >::type operator <(const iterator_range<IteratorT> & l,const ForwardRange & r)689 operator<( const iterator_range<IteratorT>& l, const ForwardRange& r ) 690 { 691 return iterator_range_detail::less_than( l, r ); 692 } 693 694 template< class Iterator1T, class Iterator2T > 695 inline bool operator <=(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)696 operator<=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) 697 { 698 return iterator_range_detail::less_or_equal_than( l, r ); 699 } 700 701 template< class IteratorT, class ForwardRange > 702 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 703 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 704 bool 705 >::type operator <=(const iterator_range<IteratorT> & l,const ForwardRange & r)706 operator<=( const iterator_range<IteratorT>& l, const ForwardRange& r ) 707 { 708 return iterator_range_detail::less_or_equal_than( l, r ); 709 } 710 711 template< class Iterator1T, class Iterator2T > 712 inline bool operator >(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)713 operator>( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) 714 { 715 return iterator_range_detail::greater_than( l, r ); 716 } 717 718 template< class IteratorT, class ForwardRange > 719 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 720 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 721 bool 722 >::type operator >(const iterator_range<IteratorT> & l,const ForwardRange & r)723 operator>( const iterator_range<IteratorT>& l, const ForwardRange& r ) 724 { 725 return iterator_range_detail::greater_than( l, r ); 726 } 727 728 template< class Iterator1T, class Iterator2T > 729 inline bool operator >=(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)730 operator>=( const iterator_range<Iterator1T>& l, const iterator_range<Iterator2T>& r ) 731 { 732 return iterator_range_detail::greater_or_equal_than( l, r ); 733 } 734 735 template< class IteratorT, class ForwardRange > 736 inline BOOST_DEDUCED_TYPENAME boost::enable_if< 737 mpl::not_<boost::is_base_and_derived<iterator_range_detail::iterator_range_tag, ForwardRange> >, 738 bool 739 >::type operator >=(const iterator_range<IteratorT> & l,const ForwardRange & r)740 operator>=( const iterator_range<IteratorT>& l, const ForwardRange& r ) 741 { 742 return iterator_range_detail::greater_or_equal_than( l, r ); 743 } 744 745 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING 746 747 // iterator range utilities -----------------------------------------// 748 749 //! iterator_range construct helper 750 /*! 751 Construct an \c iterator_range from a pair of iterators 752 753 \param Begin A begin iterator 754 \param End An end iterator 755 \return iterator_range object 756 */ 757 template< typename IteratorT > 758 inline iterator_range< IteratorT > make_iterator_range(IteratorT Begin,IteratorT End)759 make_iterator_range( IteratorT Begin, IteratorT End ) 760 { 761 return iterator_range<IteratorT>( Begin, End ); 762 } 763 764 template<typename IteratorT, typename IntegerT> 765 inline iterator_range<IteratorT> make_iterator_range_n(IteratorT first,IntegerT n)766 make_iterator_range_n(IteratorT first, IntegerT n) 767 { 768 return iterator_range<IteratorT>(first, boost::next(first, n)); 769 } 770 771 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING 772 773 template< typename Range > 774 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > make_iterator_range(Range & r)775 make_iterator_range( Range& r ) 776 { 777 return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > 778 ( boost::begin( r ), boost::end( r ) ); 779 } 780 781 #else 782 //! iterator_range construct helper 783 /*! 784 Construct an \c iterator_range from a \c Range containing the begin 785 and end iterators. 786 */ 787 template< class ForwardRange > 788 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type > make_iterator_range(ForwardRange & r)789 make_iterator_range( ForwardRange& r ) 790 { 791 return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type > 792 ( r, iterator_range_detail::range_tag() ); 793 } 794 795 template< class ForwardRange > 796 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type > make_iterator_range(const ForwardRange & r)797 make_iterator_range( const ForwardRange& r ) 798 { 799 return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type > 800 ( r, iterator_range_detail::const_range_tag() ); 801 } 802 803 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING 804 805 namespace iterator_range_detail 806 { 807 template< class Range > 808 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)809 make_range_impl( Range& r, 810 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, 811 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) 812 { 813 // 814 // Not worth the effort 815 // 816 //if( advance_begin == 0 && advance_end == 0 ) 817 // return make_iterator_range( r ); 818 // 819 820 BOOST_DEDUCED_TYPENAME range_iterator<Range>::type 821 new_begin = boost::begin( r ), 822 new_end = boost::end( r ); 823 std::advance( new_begin, advance_begin ); 824 std::advance( new_end, advance_end ); 825 return make_iterator_range( new_begin, new_end ); 826 } 827 } 828 829 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING 830 831 template< class Range > 832 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)833 make_iterator_range( Range& r, 834 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, 835 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) 836 { 837 return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); 838 } 839 840 #else 841 842 template< class Range > 843 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)844 make_iterator_range( Range& r, 845 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, 846 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) 847 { 848 return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); 849 } 850 851 template< class Range > 852 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)853 make_iterator_range( const Range& r, 854 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, 855 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) 856 { 857 return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); 858 } 859 860 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING 861 862 //! copy a range into a sequence 863 /*! 864 Construct a new sequence of the specified type from the elements 865 in the given range 866 867 \param Range An input range 868 \return New sequence 869 */ 870 template< typename SeqT, typename Range > copy_range(const Range & r)871 inline SeqT copy_range( const Range& r ) 872 { 873 return SeqT( boost::begin( r ), boost::end( r ) ); 874 } 875 876 } // namespace 'boost' 877 878 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) 879 #pragma warning( pop ) 880 #endif 881 882 #endif 883 884