Boost.Range

Utilities

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:

The 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.


Class 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.

Synopsis

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).

Details member functions

operator unspecified_bool_type() const;
Returns !empty().

Details functions

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.

Class sub_range

The sub_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.

Synopsis

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