![]() |
Boost.Range |
Having an abstraction that encapsulates a pair of iterators is very useful. The
standard library uses std::pair in some circumstances, but that
class is cumbersome to use because we need to specify two template arguments,
and for all range algorithm purposes we must enforce the two template arguments
to be the same. Moreover, std::pair<iterator,iterator> is hardly
self-documenting whereas more domain specific class names are. Therefore these
two classes are provided:
iterator_range
sub_range
iterator_range class is templated on an Forward
Traversal Iterator and should be used whenever fairly general code is needed.
The sub_range class is templated on an Forward
Range and it is less general, but a bit easier to use since its template
argument is easier to specify.
iterator_range
The intention of the iterator_range class is to encapsulate two
iterators so they fulfill the Forward Range concept. A few other functions
are also provided for convenience.
If the template argument is not a model of Forward Traversal Iterator, one
can still use a subset of the interface. In particular, size()
requires Forward Traversal Iterators whereas empty() only
requires Single Pass Iterators.
namespace boost
{
template< class ForwardTraversalIterator >
class iterator_range
{
iterator_range(); // not implemented
public: // Forward Range types
typedef ... value_type;
typedef ... difference_type;
typedef ... size_type;
typedef ForwardTraversalIterator iterator;
typedef ForwardTraversalIterator const_iterator;
public: // construction, assignment
template< class ForwardTraversalIterator2 >
iterator_range( ForwardTraversalIterator2 Begin, ForwardTraversalIterator2 End );
template< class ForwardRange >
iterator_range( ForwardRange& r );
template< class ForwardRange >
iterator_range( const ForwardRange& r );
template< class ForwardRange >
iterator_range& operator=( ForwardRange& r );
template< class ForwardRange >
iterator_range& operator=( const ForwardRange& r );
public: // Forward Range functions
iterator begin() const;
iterator end() const;
size_type size() const;
bool empty() const;
public: // convenience
operator unspecified_bool_type() const;
};
// stream output
template< class ForwardTraversalIterator, class T, class Traits >
std::basic_ostream<T,Traits>& operator<<( std::basic_ostream<T,Traits>& Os,
const iterator_range<ForwardTraversalIterator>& r );
// comparison
template< class ForwardTraversalIterator >
bool operator==( const iterator_range<ForwardTraversalIterator>& l, const iterator_range<ForwardTraversalIterator>& r );
template< class ForwardTraversalIterator >
bool operator!=( const iterator_range<ForwardTraversalIterator>& l, const iterator_range<ForwardTraversalIterator>& r );
// external construction
template< class ForwardTraversalIterator >
iterator_range< ForwardTraversalIterator >
make_iterator_range( ForwardTraversalIterator Begin, ForwardTraversalIterator End );
template< class ForwardRange >
iterator_range< typename iterator_of<ForwardRange>::type >
make_iterator_range( ForwardRange& r );
template< class ForwardRange >
iterator_range< typename const_iterator_of<ForwardRange>::type >
make_iterator_range( const ForwardRange& r );
// convenience
template< class Sequence, class ForwardRange >
Sequence copy_range( const ForwardRange& r );
template< class Sequence, class ForwardRange, class Func >
Sequence transform_range( const ForwardRange& r, Func func );
} // namespace 'boost'
It is worth noticing that the templated constructors and assignment operators
allow conversion from iterator_range<iterator> to
iterator_range<const_iterator>. If an instance of
iterator_range is constructed by a client with two iterators, the
client must ensure that the two iterators delimit a valid closed-open range
[begin,end).
operator unspecified_bool_type() const;
Returns !empty().
Sequence copy_range( const ForwardRange& r );
Constructs a new sequence of the specified type from the elements in the given range.
Sequence transform_range( const ForwardRange& r, Func func );
Constructs a new sequence from the elements in the range, transformed by a function.
sub_rangesub_range class inherits all its functionality
from the iterator_range class.
The sub_range class is often easier to use because
one must specify the Forward Range
template argument instead of an iterator.
namespace boost
{
template< class ForwardRange >
class sub_range : public iterator_range< typename result_iterator_of<ForwardRange>::type >
{
public: // construction, assignment
template< class ForwardTraversalIterator >
sub_range( ForwardTraversalIterator Begin, ForwardTraversalIterator End );
template< class ForwardRange2 >
sub_range( ForwardRange2& r );
template< class ForwardRange2 >
sub_range( const Range2& r );
template< class ForwardRange2 >
sub_range& operator=( ForwardRange2& r );
template< class ForwardRange2 >
sub_range& operator=( const ForwardRange2& r );
public:
// rest of interface inherited from iterator_range
};
} // namespace 'boost'
The class should be trivial to use, an example with strings is shown below.
typedef sub_range sub_string;
std::string s = "something";
sub_string ss( s );
sub_string ss2( begin( s ), begin( s ) + 2 );
(C) Copyright Thorsten Ottosen 2003-2004