3 // Copyright Thorsten Ottosen & Pavol Droba 2003-2004. Use, modification and
4 // distribution is subject to the Boost Software License, Version
5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 // For more information, see http://www.boost.org/libs/range/
11 #ifndef BOOST_RANGE_ITERATOR_RANGE_HPP
12 #define BOOST_RANGE_ITERATOR_RANGE_HPP
14 #include <boost/config.hpp> // Define __STL_CONFIG_H, if appropriate.
15 #include <boost/detail/workaround.hpp>
17 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
18 #pragma warning( push )
19 #pragma warning( disable : 4996 )
22 // From boost/dynamic_bitset.hpp; thanks to Matthias Troyer for Cray X1 patch.
23 #ifndef BOOST_OLD_IOSTREAMS
24 # if defined(__STL_CONFIG_H) && \
25 !defined (__STL_USE_NEW_IOSTREAMS) && !defined(__crayx1) \
27 # define BOOST_OLD_IOSTREAMS
29 #endif // #ifndef BOOST_OLD_IOSTREAMS
31 #include <boost/assert.hpp>
32 #include <boost/iterator/iterator_traits.hpp>
33 #include <boost/type_traits/is_abstract.hpp>
34 #include <boost/range/functions.hpp>
35 #include <boost/range/iterator.hpp>
36 #include <boost/range/difference_type.hpp>
37 #include <boost/utility/enable_if.hpp>
40 #ifndef _STLP_NO_IOSTREAMS
41 # ifndef BOOST_OLD_IOSTREAMS
46 #endif // _STLP_NO_IOSTREAMS
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.
58 namespace iterator_range_detail
61 // The functions adl_begin and adl_end are implemented in a separate
64 template<typename IteratorT>
65 struct iterator_range_impl {
66 template< class ForwardRange >
67 static IteratorT adl_begin( ForwardRange& r )
69 return IteratorT( boost::begin( r ) );
72 template< class ForwardRange >
73 static IteratorT adl_end( ForwardRange& r )
75 return IteratorT( boost::end( r ) );
79 template< class Left, class Right >
80 inline bool equal( const Left& l, const Right& r )
82 typedef BOOST_DEDUCED_TYPENAME boost::range_difference<Left>::type sz_type;
84 sz_type l_size = boost::distance( l ),
85 r_size = boost::distance( r );
87 if( l_size != r_size )
90 return std::equal( boost::begin(l), boost::end(l),
94 template< class Left, class Right >
95 inline bool less_than( const Left& l, const Right& r )
97 return std::lexicographical_compare( boost::begin(l),
103 struct range_tag { };
104 struct const_range_tag { };
108 // iterator range template class -----------------------------------------//
110 //! iterator_range class
112 An \c iterator_range delimits a range in a sequence by beginning and ending iterators.
113 An iterator_range can be passed to an algorithm which requires a sequence as an input.
114 For example, the \c toupper() function may be used most frequently on strings,
115 but can also be used on iterator_ranges:
118 boost::tolower( find( s, "UPPERCASE STRING" ) );
121 Many algorithms working with sequences take a pair of iterators,
122 delimiting a working range, as an arguments. The \c iterator_range class is an
123 encapsulation of a range identified by a pair of iterators.
124 It provides a collection interface,
125 so it is possible to pass an instance to an algorithm requiring a collection as an input.
127 template<typename IteratorT>
130 protected: // Used by sub_range
131 //! implementation class
132 typedef iterator_range_detail::iterator_range_impl<IteratorT> impl;
136 typedef iterator_range<IteratorT> type;
137 //BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(value_type);
139 //! Encapsulated value type
140 typedef BOOST_DEDUCED_TYPENAME
141 iterator_value<IteratorT>::type value_type;
144 typedef BOOST_DEDUCED_TYPENAME
145 iterator_difference<IteratorT>::type difference_type;
148 typedef std::size_t size_type; // note: must be unsigned
151 typedef iterator_range<IteratorT> this_type;
155 // Needed because value-type is the same for
156 // const and non-const iterators
158 typedef BOOST_DEDUCED_TYPENAME
159 iterator_reference<IteratorT>::type reference;
161 //! const_iterator type
163 There is no distinction between const_iterator and iterator.
164 These typedefs are provides to fulfill container interface
166 typedef IteratorT const_iterator;
168 typedef IteratorT iterator;
170 private: // for return value of operator()()
171 typedef BOOST_DEDUCED_TYPENAME
172 boost::mpl::if_< boost::is_abstract<value_type>,
173 reference, value_type >::type abstract_value_type;
176 iterator_range() : m_Begin( iterator() ), m_End( iterator() )
182 //! Constructor from a pair of iterators
183 template< class Iterator >
184 iterator_range( Iterator Begin, Iterator End ) :
185 m_Begin(Begin), m_End(End)
191 //! Constructor from a Range
192 template< class Range >
193 iterator_range( const Range& r ) :
194 m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
200 //! Constructor from a Range
201 template< class Range >
202 iterator_range( Range& r ) :
203 m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
209 //! Constructor from a Range
210 template< class Range >
211 iterator_range( const Range& r, iterator_range_detail::const_range_tag ) :
212 m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
218 //! Constructor from a Range
219 template< class Range >
220 iterator_range( Range& r, iterator_range_detail::range_tag ) :
221 m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
227 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
228 this_type& operator=( const this_type& r )
234 singular = r.singular;
240 template< class Iterator >
241 iterator_range& operator=( const iterator_range<Iterator>& r )
246 singular = r.is_singular();
251 template< class ForwardRange >
252 iterator_range& operator=( ForwardRange& r )
254 m_Begin = impl::adl_begin( r );
255 m_End = impl::adl_end( r );
262 template< class ForwardRange >
263 iterator_range& operator=( const ForwardRange& r )
265 m_Begin = impl::adl_begin( r );
266 m_End = impl::adl_end( r );
273 IteratorT begin() const
275 BOOST_ASSERT( !is_singular() );
279 IteratorT end() const
281 BOOST_ASSERT( !is_singular() );
285 difference_type size() const
287 BOOST_ASSERT( !is_singular() );
288 return m_End - m_Begin;
293 BOOST_ASSERT( !is_singular() );
294 return m_Begin == m_End;
297 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
298 operator bool() const
303 typedef iterator (iterator_range::*unspecified_bool_type) () const;
304 operator unspecified_bool_type() const
306 return empty() ? 0: &iterator_range::end;
310 bool equal( const iterator_range& r ) const
312 BOOST_ASSERT( !is_singular() );
313 return m_Begin == r.m_Begin && m_End == r.m_End;
317 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
319 bool operator==( const iterator_range& r ) const
321 BOOST_ASSERT( !is_singular() );
322 return iterator_range_detail::equal( *this, r );
325 bool operator!=( const iterator_range& r ) const
327 BOOST_ASSERT( !is_singular() );
328 return !operator==(r);
331 bool operator<( const iterator_range& r ) const
333 BOOST_ASSERT( !is_singular() );
334 return iterator_range_detail::less_than( *this, r );
339 public: // convenience
340 reference front() const
342 BOOST_ASSERT( !empty() );
346 reference back() const
348 BOOST_ASSERT( !empty() );
349 IteratorT last( m_End );
353 reference operator[]( difference_type at ) const
355 BOOST_ASSERT( at >= 0 && at < size() );
360 // When storing transform iterators, operator[]()
361 // fails because it returns by reference. Therefore
362 // operator()() is provided for these cases.
364 abstract_value_type operator()( difference_type at ) const
366 BOOST_ASSERT( at >= 0 && at < size() );
370 iterator_range& advance_begin( difference_type n )
372 BOOST_ASSERT( !is_singular() );
373 std::advance( m_Begin, n );
377 iterator_range& advance_end( difference_type n )
379 BOOST_ASSERT( !is_singular() );
380 std::advance( m_End, n );
385 // begin and end iterators
394 bool is_singular() const
405 // Allow subclasses an easy way to access the
408 typedef iterator_range iterator_range_;
411 // iterator range free-standing operators ---------------------------//
413 #ifndef _STLP_NO_IOSTREAMS
414 # ifndef BOOST_OLD_IOSTREAMS
416 //! iterator_range output operator
418 Output the range to an ostream. Elements are outputed
419 in a sequence without separators.
421 template< typename IteratorT, typename Elem, typename Traits >
422 inline std::basic_ostream<Elem,Traits>& operator<<(
423 std::basic_ostream<Elem, Traits>& Os,
424 const iterator_range<IteratorT>& r )
426 std::copy( r.begin(), r.end(),
427 std::ostream_iterator< BOOST_DEDUCED_TYPENAME
428 iterator_value<IteratorT>::type,
435 //! iterator_range output operator
437 Output the range to an ostream. Elements are outputed
438 in a sequence without separators.
440 template< typename IteratorT >
441 inline std::ostream& operator<<(
443 const iterator_range<IteratorT>& r )
445 std::copy( r.begin(), r.end(), std::ostream_iterator<char>(Os));
450 #endif // _STLP_NO_IOSTREAMS
452 /////////////////////////////////////////////////////////////////////
453 // comparison operators
454 /////////////////////////////////////////////////////////////////////
456 template< class IteratorT, class ForwardRange >
457 inline bool operator==( const ForwardRange& l,
458 const iterator_range<IteratorT>& r )
460 return iterator_range_detail::equal( l, r );
463 template< class IteratorT, class ForwardRange >
464 inline bool operator!=( const ForwardRange& l,
465 const iterator_range<IteratorT>& r )
467 return !iterator_range_detail::equal( l, r );
470 template< class IteratorT, class ForwardRange >
471 inline bool operator<( const ForwardRange& l,
472 const iterator_range<IteratorT>& r )
474 return iterator_range_detail::less_than( l, r );
477 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
479 template< class Iterator1T, class Iterator2T >
480 inline bool operator==( const iterator_range<Iterator1T>& l,
481 const iterator_range<Iterator2T>& r )
483 return iterator_range_detail::equal( l, r );
486 template< class IteratorT, class ForwardRange >
487 inline bool operator==( const iterator_range<IteratorT>& l,
488 const ForwardRange& r )
490 return iterator_range_detail::equal( l, r );
494 template< class Iterator1T, class Iterator2T >
495 inline bool operator!=( const iterator_range<Iterator1T>& l,
496 const iterator_range<Iterator2T>& r )
498 return !iterator_range_detail::equal( l, r );
501 template< class IteratorT, class ForwardRange >
502 inline bool operator!=( const iterator_range<IteratorT>& l,
503 const ForwardRange& r )
505 return !iterator_range_detail::equal( l, r );
509 template< class Iterator1T, class Iterator2T >
510 inline bool operator<( const iterator_range<Iterator1T>& l,
511 const iterator_range<Iterator2T>& r )
513 return iterator_range_detail::less_than( l, r );
516 template< class IteratorT, class ForwardRange >
517 inline bool operator<( const iterator_range<IteratorT>& l,
518 const ForwardRange& r )
520 return iterator_range_detail::less_than( l, r );
523 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
525 // iterator range utilities -----------------------------------------//
527 //! iterator_range construct helper
529 Construct an \c iterator_range from a pair of iterators
531 \param Begin A begin iterator
532 \param End An end iterator
533 \return iterator_range object
535 template< typename IteratorT >
536 inline iterator_range< IteratorT >
537 make_iterator_range( IteratorT Begin, IteratorT End )
539 return iterator_range<IteratorT>( Begin, End );
542 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
544 template< typename Range >
545 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
546 make_iterator_range( Range& r )
548 return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
549 ( boost::begin( r ), boost::end( r ) );
553 //! iterator_range construct helper
555 Construct an \c iterator_range from a \c Range containing the begin
558 template< class ForwardRange >
559 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type >
560 make_iterator_range( ForwardRange& r )
562 return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type >
563 ( r, iterator_range_detail::range_tag() );
566 template< class ForwardRange >
567 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type >
568 make_iterator_range( const ForwardRange& r )
570 return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type >
571 ( r, iterator_range_detail::const_range_tag() );
574 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
576 namespace iterator_range_detail
578 template< class Range >
579 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
580 make_range_impl( Range& r,
581 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
582 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
585 // Not worth the effort
587 //if( advance_begin == 0 && advance_end == 0 )
588 // return make_iterator_range( r );
591 BOOST_DEDUCED_TYPENAME range_iterator<Range>::type
592 new_begin = boost::begin( r ),
593 new_end = boost::end( r );
594 std::advance( new_begin, advance_begin );
595 std::advance( new_end, advance_end );
596 return make_iterator_range( new_begin, new_end );
600 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
602 template< class Range >
603 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
604 make_iterator_range( Range& r,
605 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
606 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
608 //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" );
609 return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
614 template< class Range >
615 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
616 make_iterator_range( Range& r,
617 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
618 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
620 //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" );
621 return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
624 template< class Range >
625 inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const Range>::type >
626 make_iterator_range( const Range& r,
627 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
628 BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
630 //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" );
631 return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
634 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
636 //! copy a range into a sequence
638 Construct a new sequence of the specified type from the elements
641 \param Range An input range
644 template< typename SeqT, typename Range >
645 inline SeqT copy_range( const Range& r )
647 return SeqT( boost::begin( r ), boost::end( r ) );
650 } // namespace 'boost'
652 #undef BOOST_OLD_IOSTREAMS
654 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
655 #pragma warning( pop )