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 #ifndef BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED 11 #define BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED 12 13 #include <boost/config.hpp> // Define __STL_CONFIG_H, if appropriate. 14 #include <boost/detail/workaround.hpp> 15 16 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) 17 #pragma warning( push ) 18 #pragma warning( disable : 4996 ) 19 #endif 20 21 #include <boost/assert.hpp> 22 #include <boost/iterator/iterator_traits.hpp> 23 #include <boost/iterator/iterator_facade.hpp> 24 #include <boost/type_traits/is_abstract.hpp> 25 #include <boost/type_traits/is_pointer.hpp> 26 #include <boost/range/functions.hpp> 27 #include <boost/range/iterator.hpp> 28 #include <boost/range/difference_type.hpp> 29 #include <boost/range/algorithm/equal.hpp> 30 #include <boost/range/detail/safe_bool.hpp> 31 #include <boost/utility/enable_if.hpp> 32 #include <iterator> 33 #include <algorithm> 34 #include <cstddef> 35 36 /*! \file 37 Defines the \c iterator_class and related functions. 38 \c iterator_range is a simple wrapper of iterator pair idiom. It provides 39 a rich subset of Container interface. 40 */ 41 42 43 namespace boost 44 { 45 namespace iterator_range_detail 46 { 47 // 48 // The functions adl_begin and adl_end are implemented in a separate 49 // class for gcc-2.9x 50 // 51 template<class IteratorT> 52 struct iterator_range_impl { 53 template< class ForwardRange > adl_beginboost::iterator_range_detail::iterator_range_impl54 static IteratorT adl_begin( ForwardRange& r ) 55 { 56 return static_cast<IteratorT>( boost::begin( r ) ); 57 } 58 59 template< class ForwardRange > adl_endboost::iterator_range_detail::iterator_range_impl60 static IteratorT adl_end( ForwardRange& r ) 61 { 62 return static_cast<IteratorT>( boost::end( r ) ); 63 } 64 }; 65 66 template< class Left, class Right > less_than(const Left & l,const Right & r)67 inline bool less_than( const Left& l, const Right& r ) 68 { 69 return std::lexicographical_compare( boost::begin(l), 70 boost::end(l), 71 boost::begin(r), 72 boost::end(r) ); 73 } 74 75 template< class Left, class Right > greater_than(const Left & l,const Right & r)76 inline bool greater_than( const Left& l, const Right& r ) 77 { 78 return less_than(r,l); 79 } 80 81 template< class Left, class Right > less_or_equal_than(const Left & l,const Right & r)82 inline bool less_or_equal_than( const Left& l, const Right& r ) 83 { 84 return !iterator_range_detail::less_than(r,l); 85 } 86 87 template< class Left, class Right > greater_or_equal_than(const Left & l,const Right & r)88 inline bool greater_or_equal_than( const Left& l, const Right& r ) 89 { 90 return !iterator_range_detail::less_than(l,r); 91 } 92 93 // This version is maintained since it is used in other boost libraries 94 // such as Boost.Assign 95 template< class Left, class Right > equal(const Left & l,const Right & r)96 inline bool equal(const Left& l, const Right& r) 97 { 98 return boost::equal(l, r); 99 } 100 101 struct range_tag { }; 102 struct const_range_tag { }; 103 } 104 105 // iterator range template class -----------------------------------------// 106 107 //! iterator_range class 108 /*! 109 An \c iterator_range delimits a range in a sequence by beginning and ending iterators. 110 An iterator_range can be passed to an algorithm which requires a sequence as an input. 111 For example, the \c toupper() function may be used most frequently on strings, 112 but can also be used on iterator_ranges: 113 114 \code 115 boost::tolower( find( s, "UPPERCASE STRING" ) ); 116 \endcode 117 118 Many algorithms working with sequences take a pair of iterators, 119 delimiting a working range, as an arguments. The \c iterator_range class is an 120 encapsulation of a range identified by a pair of iterators. 121 It provides a collection interface, 122 so it is possible to pass an instance to an algorithm requiring a collection as an input. 123 */ 124 template<class IteratorT> 125 class iterator_range 126 { 127 typedef range_detail::safe_bool< IteratorT iterator_range<IteratorT>::* > safe_bool_t; 128 protected: // Used by sub_range 129 //! implementation class 130 typedef iterator_range_detail::iterator_range_impl<IteratorT> impl; 131 public: 132 //! this type 133 typedef iterator_range<IteratorT> type; 134 typedef BOOST_DEDUCED_TYPENAME safe_bool_t::unspecified_bool_type unspecified_bool_type; 135 //BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(value_type); 136 137 //! Encapsulated value type 138 typedef BOOST_DEDUCED_TYPENAME 139 iterator_value<IteratorT>::type value_type; 140 141 //! Difference type 142 typedef BOOST_DEDUCED_TYPENAME 143 iterator_difference<IteratorT>::type difference_type; 144 145 //! Size type 146 typedef std::size_t size_type; // note: must be unsigned 147 148 //! This type 149 typedef iterator_range<IteratorT> this_type; 150 151 //! Reference type 152 // 153 // Needed because value-type is the same for 154 // const and non-const iterators 155 // 156 typedef BOOST_DEDUCED_TYPENAME 157 iterator_reference<IteratorT>::type reference; 158 159 //! const_iterator type 160 /*! 161 There is no distinction between const_iterator and iterator. 162 These typedefs are provides to fulfill container interface 163 */ 164 typedef IteratorT const_iterator; 165 //! iterator type 166 typedef IteratorT iterator; 167 168 private: // for return value of operator()() 169 typedef BOOST_DEDUCED_TYPENAME 170 boost::mpl::if_< boost::is_abstract<value_type>, 171 reference, value_type >::type abstract_value_type; 172 173 public: iterator_range()174 iterator_range() : m_Begin( iterator() ), m_End( iterator() ) 175 { } 176 177 //! Constructor from a pair of iterators 178 template< class Iterator > iterator_range(Iterator Begin,Iterator End)179 iterator_range( Iterator Begin, Iterator End ) : 180 m_Begin(Begin), m_End(End) 181 {} 182 183 //! Constructor from a Range 184 template< class Range > iterator_range(const Range & r)185 iterator_range( const Range& r ) : 186 m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) ) 187 {} 188 189 //! Constructor from a Range 190 template< class Range > iterator_range(Range & r)191 iterator_range( Range& r ) : 192 m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) ) 193 {} 194 195 //! Constructor from a Range 196 template< class Range > iterator_range(const Range & r,iterator_range_detail::const_range_tag)197 iterator_range( const Range& r, iterator_range_detail::const_range_tag ) : 198 m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) ) 199 {} 200 201 //! Constructor from a Range 202 template< class Range > iterator_range(Range & r,iterator_range_detail::range_tag)203 iterator_range( Range& r, iterator_range_detail::range_tag ) : 204 m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) ) 205 {} 206 207 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) operator =(const this_type & r)208 this_type& operator=( const this_type& r ) 209 { 210 m_Begin = r.begin(); 211 m_End = r.end(); 212 return *this; 213 } 214 #endif 215 216 template< class Iterator > operator =(const iterator_range<Iterator> & r)217 iterator_range& operator=( const iterator_range<Iterator>& r ) 218 { 219 m_Begin = r.begin(); 220 m_End = r.end(); 221 return *this; 222 } 223 224 template< class ForwardRange > operator =(ForwardRange & r)225 iterator_range& operator=( ForwardRange& r ) 226 { 227 m_Begin = impl::adl_begin( r ); 228 m_End = impl::adl_end( r ); 229 return *this; 230 } 231 232 template< class ForwardRange > operator =(const ForwardRange & r)233 iterator_range& operator=( const ForwardRange& r ) 234 { 235 m_Begin = impl::adl_begin( r ); 236 m_End = impl::adl_end( r ); 237 return *this; 238 } 239 begin() const240 IteratorT begin() const 241 { 242 return m_Begin; 243 } 244 end() const245 IteratorT end() const 246 { 247 return m_End; 248 } 249 size() const250 difference_type size() const 251 { 252 return m_End - m_Begin; 253 } 254 empty() const255 bool empty() const 256 { 257 return m_Begin == m_End; 258 } 259 operator unspecified_bool_type() const260 operator unspecified_bool_type() const 261 { 262 return safe_bool_t::to_unspecified_bool(m_Begin != m_End, &iterator_range::m_Begin); 263 } 264 operator !() const265 bool operator!() const 266 { 267 return empty(); 268 } 269 equal(const iterator_range & r) const270 bool equal( const iterator_range& r ) const 271 { 272 return m_Begin == r.m_Begin && m_End == r.m_End; 273 } 274 275 276 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING 277 operator ==(const iterator_range & r) const278 bool operator==( const iterator_range& r ) const 279 { 280 return boost::equal( *this, r ); 281 } 282 operator !=(const iterator_range & r) const283 bool operator!=( const iterator_range& r ) const 284 { 285 return !operator==(r); 286 } 287 operator <(const iterator_range & r) const288 bool operator<( const iterator_range& r ) const 289 { 290 return iterator_range_detail::less_than( *this, r ); 291 } 292 operator >(const iterator_range & r) const293 bool operator>( const iterator_range& r ) const 294 { 295 return iterator_range_detail::greater_than( *this, r ); 296 } 297 operator <=(const iterator_range & r) const298 bool operator<=( const iterator_range& r ) const 299 { 300 return iterator_range_detail::less_or_equal_than( *this, r ); 301 } 302 operator >=(const iterator_range & r) const303 bool operator>=( const iterator_range& r ) const 304 { 305 return iterator_range_detail::greater_or_equal_than( *this, r ); 306 } 307 308 #endif 309 310 public: // convenience front() const311 reference front() const 312 { 313 BOOST_ASSERT( !empty() ); 314 return *m_Begin; 315 } 316 back() const317 reference back() const 318 { 319 BOOST_ASSERT( !empty() ); 320 IteratorT last( m_End ); 321 return *--last; 322 } 323 324 // pop_front() - added to model the SinglePassRangePrimitiveConcept pop_front()325 void pop_front() 326 { 327 BOOST_ASSERT( !empty() ); 328 ++m_Begin; 329 } 330 331 // pop_back() - added to model the BidirectionalRangePrimitiveConcept pop_back()332 void pop_back() 333 { 334 BOOST_ASSERT( !empty() ); 335 --m_End; 336 } 337 operator [](difference_type at) const338 reference operator[]( difference_type at ) const 339 { 340 BOOST_ASSERT( at >= 0 && at < size() ); 341 return m_Begin[at]; 342 } 343 344 // 345 // When storing transform iterators, operator[]() 346 // fails because it returns by reference. Therefore 347 // operator()() is provided for these cases. 348 // operator ()(difference_type at) const349 abstract_value_type operator()( difference_type at ) const 350 { 351 BOOST_ASSERT( at >= 0 && at < size() ); 352 return m_Begin[at]; 353 } 354 advance_begin(difference_type n)355 iterator_range& advance_begin( difference_type n ) 356 { 357 std::advance( m_Begin, n ); 358 return *this; 359 } 360 advance_end(difference_type n)361 iterator_range& advance_end( difference_type n ) 362 { 363 std::advance( m_End, n ); 364 return *this; 365 } 366 367 private: 368 // begin and end iterators 369 IteratorT m_Begin; 370 IteratorT m_End; 371 372 protected: 373 // 374 // Allow subclasses an easy way to access the 375 // base type 376 // 377 typedef iterator_range iterator_range_; 378 }; 379 380 // iterator range free-standing operators ---------------------------// 381 382 ///////////////////////////////////////////////////////////////////// 383 // comparison operators 384 ///////////////////////////////////////////////////////////////////// 385 386 template< class IteratorT, class ForwardRange > operator ==(const ForwardRange & l,const iterator_range<IteratorT> & r)387 inline bool operator==( const ForwardRange& l, 388 const iterator_range<IteratorT>& r ) 389 { 390 return boost::equal( l, r ); 391 } 392 393 template< class IteratorT, class ForwardRange > operator !=(const ForwardRange & l,const iterator_range<IteratorT> & r)394 inline bool operator!=( const ForwardRange& l, 395 const iterator_range<IteratorT>& r ) 396 { 397 return !boost::equal( l, r ); 398 } 399 400 template< class IteratorT, class ForwardRange > operator <(const ForwardRange & l,const iterator_range<IteratorT> & r)401 inline bool operator<( const ForwardRange& l, 402 const iterator_range<IteratorT>& r ) 403 { 404 return iterator_range_detail::less_than( l, r ); 405 } 406 407 template< class IteratorT, class ForwardRange > operator <=(const ForwardRange & l,const iterator_range<IteratorT> & r)408 inline bool operator<=( const ForwardRange& l, 409 const iterator_range<IteratorT>& r ) 410 { 411 return iterator_range_detail::less_or_equal_than( l, r ); 412 } 413 414 template< class IteratorT, class ForwardRange > operator >(const ForwardRange & l,const iterator_range<IteratorT> & r)415 inline bool operator>( const ForwardRange& l, 416 const iterator_range<IteratorT>& r ) 417 { 418 return iterator_range_detail::greater_than( l, r ); 419 } 420 421 template< class IteratorT, class ForwardRange > operator >=(const ForwardRange & l,const iterator_range<IteratorT> & r)422 inline bool operator>=( const ForwardRange& l, 423 const iterator_range<IteratorT>& r ) 424 { 425 return iterator_range_detail::greater_or_equal_than( l, r ); 426 } 427 428 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING 429 #else 430 template< class Iterator1T, class Iterator2T > operator ==(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)431 inline bool operator==( const iterator_range<Iterator1T>& l, 432 const iterator_range<Iterator2T>& r ) 433 { 434 return boost::equal( l, r ); 435 } 436 437 template< class IteratorT, class ForwardRange > operator ==(const iterator_range<IteratorT> & l,const ForwardRange & r)438 inline bool operator==( const iterator_range<IteratorT>& l, 439 const ForwardRange& r ) 440 { 441 return boost::equal( l, r ); 442 } 443 444 445 template< class Iterator1T, class Iterator2T > operator !=(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)446 inline bool operator!=( const iterator_range<Iterator1T>& l, 447 const iterator_range<Iterator2T>& r ) 448 { 449 return !boost::equal( l, r ); 450 } 451 452 template< class IteratorT, class ForwardRange > operator !=(const iterator_range<IteratorT> & l,const ForwardRange & r)453 inline bool operator!=( const iterator_range<IteratorT>& l, 454 const ForwardRange& r ) 455 { 456 return !boost::equal( l, r ); 457 } 458 459 460 template< class Iterator1T, class Iterator2T > operator <(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)461 inline bool operator<( const iterator_range<Iterator1T>& l, 462 const iterator_range<Iterator2T>& r ) 463 { 464 return iterator_range_detail::less_than( l, r ); 465 } 466 467 template< class IteratorT, class ForwardRange > operator <(const iterator_range<IteratorT> & l,const ForwardRange & r)468 inline bool operator<( const iterator_range<IteratorT>& l, 469 const ForwardRange& r ) 470 { 471 return iterator_range_detail::less_than( l, r ); 472 } 473 474 template< class Iterator1T, class Iterator2T > operator <=(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)475 inline bool operator<=( const iterator_range<Iterator1T>& l, 476 const iterator_range<Iterator2T>& r ) 477 { 478 return iterator_range_detail::less_or_equal_than( l, r ); 479 } 480 481 template< class IteratorT, class ForwardRange > operator <=(const iterator_range<IteratorT> & l,const ForwardRange & r)482 inline bool operator<=( const iterator_range<IteratorT>& l, 483 const ForwardRange& r ) 484 { 485 return iterator_range_detail::less_or_equal_than( l, r ); 486 } 487 488 template< class Iterator1T, class Iterator2T > operator >(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)489 inline bool operator>( const iterator_range<Iterator1T>& l, 490 const iterator_range<Iterator2T>& r ) 491 { 492 return iterator_range_detail::greater_than( l, r ); 493 } 494 495 template< class IteratorT, class ForwardRange > operator >(const iterator_range<IteratorT> & l,const ForwardRange & r)496 inline bool operator>( const iterator_range<IteratorT>& l, 497 const ForwardRange& r ) 498 { 499 return iterator_range_detail::greater_than( l, r ); 500 } 501 502 template< class Iterator1T, class Iterator2T > operator >=(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)503 inline bool operator>=( const iterator_range<Iterator1T>& l, 504 const iterator_range<Iterator2T>& r ) 505 { 506 return iterator_range_detail::greater_or_equal_than( l, r ); 507 } 508 509 template< class IteratorT, class ForwardRange > operator >=(const iterator_range<IteratorT> & l,const ForwardRange & r)510 inline bool operator>=( const iterator_range<IteratorT>& l, 511 const ForwardRange& r ) 512 { 513 return iterator_range_detail::greater_or_equal_than( l, r ); 514 } 515 516 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING 517 518 // iterator range utilities -----------------------------------------// 519 520 //! iterator_range construct helper 521 /*! 522 Construct an \c iterator_range from a pair of iterators 523 524 \param Begin A begin iterator 525 \param End An end iterator 526 \return iterator_range object 527 */ 528 template< typename IteratorT > 529 inline iterator_range< IteratorT > make_iterator_range(IteratorT Begin,IteratorT End)530 make_iterator_range( IteratorT Begin, IteratorT End ) 531 { 532 return iterator_range<IteratorT>( Begin, End ); 533 } 534 535 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING 536 537 template< typename Range > 538 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > make_iterator_range(Range & r)539 make_iterator_range( Range& r ) 540 { 541 return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > 542 ( boost::begin( r ), boost::end( r ) ); 543 } 544 545 #else 546 //! iterator_range construct helper 547 /*! 548 Construct an \c iterator_range from a \c Range containing the begin 549 and end iterators. 550 */ 551 template< class ForwardRange > 552 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type > make_iterator_range(ForwardRange & r)553 make_iterator_range( ForwardRange& r ) 554 { 555 return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type > 556 ( r, iterator_range_detail::range_tag() ); 557 } 558 559 template< class ForwardRange > 560 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type > make_iterator_range(const ForwardRange & r)561 make_iterator_range( const ForwardRange& r ) 562 { 563 return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type > 564 ( r, iterator_range_detail::const_range_tag() ); 565 } 566 567 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING 568 569 namespace iterator_range_detail 570 { 571 template< class Range > 572 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)573 make_range_impl( Range& r, 574 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, 575 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) 576 { 577 // 578 // Not worth the effort 579 // 580 //if( advance_begin == 0 && advance_end == 0 ) 581 // return make_iterator_range( r ); 582 // 583 584 BOOST_DEDUCED_TYPENAME range_iterator<Range>::type 585 new_begin = boost::begin( r ), 586 new_end = boost::end( r ); 587 std::advance( new_begin, advance_begin ); 588 std::advance( new_end, advance_end ); 589 return make_iterator_range( new_begin, new_end ); 590 } 591 } 592 593 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING 594 595 template< class Range > 596 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)597 make_iterator_range( Range& r, 598 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, 599 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) 600 { 601 //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" ); 602 return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); 603 } 604 605 #else 606 607 template< class Range > 608 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)609 make_iterator_range( Range& r, 610 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, 611 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) 612 { 613 //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" ); 614 return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); 615 } 616 617 template< class Range > 618 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)619 make_iterator_range( const Range& r, 620 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, 621 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) 622 { 623 //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" ); 624 return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); 625 } 626 627 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING 628 629 //! copy a range into a sequence 630 /*! 631 Construct a new sequence of the specified type from the elements 632 in the given range 633 634 \param Range An input range 635 \return New sequence 636 */ 637 template< typename SeqT, typename Range > copy_range(const Range & r)638 inline SeqT copy_range( const Range& r ) 639 { 640 return SeqT( boost::begin( r ), boost::end( r ) ); 641 } 642 643 } // namespace 'boost' 644 645 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) 646 #pragma warning( pop ) 647 #endif 648 649 #endif 650 651