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)
8
// For more information, see http://www.boost.org/libs/range/
10
#ifndef BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED
11
#define BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED
13
#include <boost/config.hpp> // Define __STL_CONFIG_H, if appropriate.
14
#include <boost/detail/workaround.hpp>
16
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
17
#pragma warning( push )
18
#pragma warning( disable : 4996 )
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/utility/enable_if.hpp>
36
Defines the \c iterator_class and related functions.
37
\c iterator_range is a simple wrapper of iterator pair idiom. It provides
38
a rich subset of Container interface.
44
namespace iterator_range_detail
47
// The functions adl_begin and adl_end are implemented in a separate
50
template<class IteratorT>
51
struct iterator_range_impl {
52
template< class ForwardRange >
53
static IteratorT adl_begin( ForwardRange& r )
55
return IteratorT( boost::begin( r ) );
58
template< class ForwardRange >
59
static IteratorT adl_end( ForwardRange& r )
61
return IteratorT( boost::end( r ) );
65
template< class Left, class Right >
66
inline bool less_than( const Left& l, const Right& r )
68
return std::lexicographical_compare( boost::begin(l),
74
// This version is maintained since it is used in other boost libraries
75
// such as Boost.Assign
76
template< class Left, class Right >
77
inline bool equal(const Left& l, const Right& r)
79
return boost::equal(l, r);
83
struct const_range_tag { };
87
// iterator range template class -----------------------------------------//
89
//! iterator_range class
91
An \c iterator_range delimits a range in a sequence by beginning and ending iterators.
92
An iterator_range can be passed to an algorithm which requires a sequence as an input.
93
For example, the \c toupper() function may be used most frequently on strings,
94
but can also be used on iterator_ranges:
97
boost::tolower( find( s, "UPPERCASE STRING" ) );
100
Many algorithms working with sequences take a pair of iterators,
101
delimiting a working range, as an arguments. The \c iterator_range class is an
102
encapsulation of a range identified by a pair of iterators.
103
It provides a collection interface,
104
so it is possible to pass an instance to an algorithm requiring a collection as an input.
106
template<class IteratorT>
109
protected: // Used by sub_range
110
//! implementation class
111
typedef iterator_range_detail::iterator_range_impl<IteratorT> impl;
115
typedef iterator_range<IteratorT> type;
116
//BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(value_type);
118
//! Encapsulated value type
119
typedef BOOST_DEDUCED_TYPENAME
120
iterator_value<IteratorT>::type value_type;
123
typedef BOOST_DEDUCED_TYPENAME
124
iterator_difference<IteratorT>::type difference_type;
127
typedef std::size_t size_type; // note: must be unsigned
130
typedef iterator_range<IteratorT> this_type;
134
// Needed because value-type is the same for
135
// const and non-const iterators
137
typedef BOOST_DEDUCED_TYPENAME
138
iterator_reference<IteratorT>::type reference;
140
//! const_iterator type
142
There is no distinction between const_iterator and iterator.
143
These typedefs are provides to fulfill container interface
145
typedef IteratorT const_iterator;
147
typedef IteratorT iterator;
149
private: // for return value of operator()()
150
typedef BOOST_DEDUCED_TYPENAME
151
boost::mpl::if_< boost::is_abstract<value_type>,
152
reference, value_type >::type abstract_value_type;
155
iterator_range() : m_Begin( iterator() ), m_End( iterator() )
158
//! Constructor from a pair of iterators
159
template< class Iterator >
160
iterator_range( Iterator Begin, Iterator End ) :
161
m_Begin(Begin), m_End(End)
164
//! Constructor from a Range
165
template< class Range >
166
iterator_range( const Range& r ) :
167
m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
170
//! Constructor from a Range
171
template< class Range >
172
iterator_range( Range& r ) :
173
m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
176
//! Constructor from a Range
177
template< class Range >
178
iterator_range( const Range& r, iterator_range_detail::const_range_tag ) :
179
m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
182
//! Constructor from a Range
183
template< class Range >
184
iterator_range( Range& r, iterator_range_detail::range_tag ) :
185
m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
188
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
189
this_type& operator=( const this_type& r )
197
template< class Iterator >
198
iterator_range& operator=( const iterator_range<Iterator>& r )
205
template< class ForwardRange >
206
iterator_range& operator=( ForwardRange& r )
208
m_Begin = impl::adl_begin( r );
209
m_End = impl::adl_end( r );
213
template< class ForwardRange >
214
iterator_range& operator=( const ForwardRange& r )
216
m_Begin = impl::adl_begin( r );
217
m_End = impl::adl_end( r );
221
IteratorT begin() const
226
IteratorT end() const
231
difference_type size() const
233
return m_End - m_Begin;
238
return m_Begin == m_End;
241
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
242
operator bool() const
247
typedef iterator (iterator_range::*unspecified_bool_type) () const;
248
operator unspecified_bool_type() const
250
return empty() ? 0: &iterator_range::end;
254
bool equal( const iterator_range& r ) const
256
return m_Begin == r.m_Begin && m_End == r.m_End;
260
#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
262
bool operator==( const iterator_range& r ) const
264
return boost::equal( *this, r );
267
bool operator!=( const iterator_range& r ) const
269
return !operator==(r);
272
bool operator<( const iterator_range& r ) const
274
return iterator_range_detail::less_than( *this, r );
279
public: // convenience
280
reference front() const
282
BOOST_ASSERT( !empty() );
286
reference back() const
288
BOOST_ASSERT( !empty() );
289
IteratorT last( m_End );
293
reference operator[]( difference_type at ) const
295
BOOST_ASSERT( at >= 0 && at < size() );
300
// When storing transform iterators, operator[]()
301
// fails because it returns by reference. Therefore
302
// operator()() is provided for these cases.
304
abstract_value_type operator()( difference_type at ) const
306
BOOST_ASSERT( at >= 0 && at < size() );
310
iterator_range& advance_begin( difference_type n )
312
std::advance( m_Begin, n );
316
iterator_range& advance_end( difference_type n )
318
std::advance( m_End, n );
323
// begin and end iterators
329
// Allow subclasses an easy way to access the
332
typedef iterator_range iterator_range_;
335
// iterator range free-standing operators ---------------------------//
337
/////////////////////////////////////////////////////////////////////
338
// comparison operators
339
/////////////////////////////////////////////////////////////////////
341
template< class IteratorT, class ForwardRange >
342
inline bool operator==( const ForwardRange& l,
343
const iterator_range<IteratorT>& r )
345
return boost::equal( l, r );
348
template< class IteratorT, class ForwardRange >
349
inline bool operator!=( const ForwardRange& l,
350
const iterator_range<IteratorT>& r )
352
return !boost::equal( l, r );
355
template< class IteratorT, class ForwardRange >
356
inline bool operator<( const ForwardRange& l,
357
const iterator_range<IteratorT>& r )
359
return iterator_range_detail::less_than( l, r );
362
#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
364
template< class Iterator1T, class Iterator2T >
365
inline bool operator==( const iterator_range<Iterator1T>& l,
366
const iterator_range<Iterator2T>& r )
368
return boost::equal( l, r );
371
template< class IteratorT, class ForwardRange >
372
inline bool operator==( const iterator_range<IteratorT>& l,
373
const ForwardRange& r )
375
return boost::equal( l, r );
379
template< class Iterator1T, class Iterator2T >
380
inline bool operator!=( const iterator_range<Iterator1T>& l,
381
const iterator_range<Iterator2T>& r )
383
return !boost::equal( l, r );
386
template< class IteratorT, class ForwardRange >
387
inline bool operator!=( const iterator_range<IteratorT>& l,
388
const ForwardRange& r )
390
return !boost::equal( l, r );
394
template< class Iterator1T, class Iterator2T >
395
inline bool operator<( const iterator_range<Iterator1T>& l,
396
const iterator_range<Iterator2T>& r )
398
return iterator_range_detail::less_than( l, r );
401
template< class IteratorT, class ForwardRange >
402
inline bool operator<( const iterator_range<IteratorT>& l,
403
const ForwardRange& r )
405
return iterator_range_detail::less_than( l, r );
408
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
410
// iterator range utilities -----------------------------------------//
412
//! iterator_range construct helper
414
Construct an \c iterator_range from a pair of iterators
416
\param Begin A begin iterator
417
\param End An end iterator
418
\return iterator_range object
420
template< typename IteratorT >
421
inline iterator_range< IteratorT >
422
make_iterator_range( IteratorT Begin, IteratorT End )
424
return iterator_range<IteratorT>( Begin, End );
427
#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
429
template< typename Range >
430
inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
431
make_iterator_range( Range& r )
433
return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
434
( boost::begin( r ), boost::end( r ) );
438
//! iterator_range construct helper
440
Construct an \c iterator_range from a \c Range containing the begin
443
template< class ForwardRange >
444
inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type >
445
make_iterator_range( ForwardRange& r )
447
return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type >
448
( r, iterator_range_detail::range_tag() );
451
template< class ForwardRange >
452
inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type >
453
make_iterator_range( const ForwardRange& r )
455
return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type >
456
( r, iterator_range_detail::const_range_tag() );
459
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
461
namespace iterator_range_detail
463
template< class Range >
464
inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
465
make_range_impl( Range& r,
466
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
467
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
470
// Not worth the effort
472
//if( advance_begin == 0 && advance_end == 0 )
473
// return make_iterator_range( r );
476
BOOST_DEDUCED_TYPENAME range_iterator<Range>::type
477
new_begin = boost::begin( r ),
478
new_end = boost::end( r );
479
std::advance( new_begin, advance_begin );
480
std::advance( new_end, advance_end );
481
return make_iterator_range( new_begin, new_end );
485
#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
487
template< class Range >
488
inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
489
make_iterator_range( Range& r,
490
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
491
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
493
//BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" );
494
return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
499
template< class Range >
500
inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
501
make_iterator_range( Range& r,
502
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
503
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
505
//BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" );
506
return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
509
template< class Range >
510
inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const Range>::type >
511
make_iterator_range( const Range& r,
512
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
513
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
515
//BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" );
516
return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
519
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
521
//! copy a range into a sequence
523
Construct a new sequence of the specified type from the elements
526
\param Range An input range
529
template< typename SeqT, typename Range >
530
inline SeqT copy_range( const Range& r )
532
return SeqT( boost::begin( r ), boost::end( r ) );
535
} // namespace 'boost'
537
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
538
#pragma warning( pop )