#
Boost.Range

## Synopsis and Reference

- Overview
- Synopsis
- Semantics
- Extending the library

### Overview

Three types of objects are currently supported by the library:

- standard-like containers
- `std::pair<iterator,iterator>`
- built-in arrays

Even though the behavior of the primary templates are exactly such that standard containers will be supported by default, the requirements are much lower than the standard container requirements. For example, the utility class `iterator_range` implements the minimal interface required to make the class a Forward Range .

Please also see Range concepts for more details.

### Synopsis

    namespace boost
    {
        //
        // Single Pass Range metafunctions
        //

        template< class T >
        struct range_iterator;

        template< class T >
        struct range_value;

        template< class T >
        struct range_reference;

        template< class T >
        struct range_pointer;

        template< class T >
        struct range_category;

        //
        // Forward Range metafunctions
        //

        template< class T >
        struct range_difference;

        //
        // Bidirectional Range metafunctions
        //

        template< class T >
        struct range_reverse_iterator;

        //
        // Single Pass Range functions
        //

        template< class T >
        typename range_iterator<T>::type
        begin( T& r );

        template< class T >
        typename range_iterator<const T>::type
        begin( const T& r );

        template< class T >
        typename range_iterator<T>::type
        end( T& r );

        template< class T >
        typename range_iterator<const T>::type
        end( const T& r );

        template< class T >
        bool
        empty( const T& r );

        //
        // Forward Range functions
        //

        template< class T >
        typename range_difference<T>::type
        distance( const T& r );

        //
        // Bidirectional Range functions
        //

        template< class T >
        typename range_reverse_iterator<T>::type
        rbegin( T& r );

        template< class T >
        typename range_reverse_iterator<const T>::type
        rbegin( const T& r );

        template< class T >
        typename range_reverse_iterator<T>::type
        rend( T& r );

        template< class T >
        typename range_reverse_iterator<const T>::type
        rend( const T& r );

        //
        // Random Access Range functions
        //

        template< class T >
        typename range_difference<T>::type
        size( const T& r );

        //
        // Special const Range functions
        //

        template< class T >
        typename range_iterator<const T>::type
        const_begin( const T& r );

        template< class T >
        typename range_iterator<const T>::type
        const_end( const T& r );

        template< class T >
        typename range_reverse_iterator<const T>::type
        const_rbegin( const T& r );

        template< class T >
        typename range_reverse_iterator<const T>::type
        const_rend( const T& r );

        //
        // String utilities
        //

        template< class T >
        iterator_range<...see below...>
        as_literal( T& r );

        template< class T >
        iterator_range<...see below...>
        as_literal( const T& r );

        template< class T >
        iterator_range< typename range_iterator<T>::type >
        as_array( T& r );

        template< class T >
        iterator_range< typename range_iterator<const T>::type >
        as_array( const T& r );

    } // namespace 'boost'

### Semantics

#### notation

Type | Object | Describes
--- | --- | ---
`X` | `x` | any type
`T` | `t` | denotes behavior of the primary templates
`P` | `p` | denotes `std::pair<iterator,iterator>`
`A[sz]` | `a` | denotes an array of type `A` of size `sz`
`Char*` | `s` | denotes either `char*` or `wchar_t*`

Please notice in tables below that when four lines appear in a cell, the first line will describe the primary template, the second line pairs of iterators, the third line arrays and the last line null-terminated strings.

#### Metafunctions

Expression | Return type | Complexity
--- | --- | ---
`range_iterator<X>::type` | `T::iterator` `P::first_type` `A*` | compile time
`range_iterator<const X>::type` | `T::const_iterator` `P::first_type` `const A*` | compile time
`range_value<X>::type` | `boost::iterator_value<range_iterator<X>::type>::type` | compile time
`range_reference<X>::type` | `boost::iterator_reference<range_iterator<X>::type>::type` | compile time
`range_pointer<X>::type` | `boost::iterator_pointer<range_iterator<X>::type>::type` | compile time
`range_category<X>::type` | `boost::iterator_category<range_iterator<X>::type>::type` | compile time
`range_difference<X>::type` | `boost::iterator_difference<range_iterator<X>::type>::type` | compile time
`range_reverse_iterator<X>::type` | `boost::reverse_iterator<range_iterator<X>::type>` | compile time
`range_reverse_iterator<const X>::type` | `boost::reverse_iterator<range_iterator<const X>::type>` | compile time

#### Functions

Expression | Return type | Returns | Complexity
--- | --- | --- | ---
`begin(x)` | `range_iterator<X>::type` | `p.first` if `p` is of type `std::pair<T>``a` if `a` is an array `range_begin(x)` if that expression would invoke a function found by ADL `t.begin()` otherwise`` | constant time
`end(x)` | `range_iterator<X>::type` | `p.second` if `p` is of type `std::pair<T>``a + sz` if `a` is an array of size `sz` `range_end(x)` if that expression would invoke a function found by ADL `t.end()` otherwise`` | constant time
`empty(x)` | `bool` | `boost::begin(x) == boost::end(x)` | constant time
`distance(x)` | `range_difference<X>::type` | `std::distance(boost::begin(x),boost::end(x))` | -
`size(x)` | `range_difference<X>::type` | `boost::end(x) - boost::begin(x)` | constant time
`rbegin(x)` | `range_reverse_iterator<X>::type` | `range_reverse_iterator<X>::type( boost::end(x) )` | constant time
`rend(x)` | `range_reverse_iterator<X>::type` | `range_reverse_iterator<X>::type( boost::begin(x) )` | constant time
`const_begin(x)` | `range_iterator<const X>::type` | `range_iterator<const X>::type( boost::begin(x) )` | constant time
`const_end(x)` | `range_iterator<const X>::type` | `range_iterator<const X>::type( boost::end(x) )` | constant time
`const_rbegin(x)` | `range_reverse_iterator<const X>::type` | `range_reverse_iterator<const X>::type( boost::rbegin(x) )` | constant time
`const_rend(x)` | `range_reverse_iterator<const X>::type` | `range_reverse_iterator<const X>::type( boost::rend(x) )` | constant time
`as_literal(x)` | `iterator_range<U>` where `U` is `Char*` if `x` is a pointer to a string and `U` is `range_iterator<X>::type` otherwise | `[s,s + std::char_traits<X>::length(s))` if `s` is a `Char*` or an array of `Char` `[boost::begin(x),boost::end(x))` otherwise | linear time for pointers to a string or arrays of `Char`, constant time otherwise
`as_array(x)` | `iterator_range<X>` | `[boost::begin(x),boost::end(x))` | constant time otherwise

The special `const_`-named functions are useful when you want to document clearly that your code is read-only.

`as_literal()` can be used internally in string algorithm librararies such that arrays of characters are handled correctly.

`as_array()` can be used with string algorithm libraries to make it clear that arrays of characters are handled like an array and not like a string.

Notice that the above functions should always be called with qualification (`boost::`) to prevent unintended Argument Dependent Lookup (ADL).

### Extending the library

- Method 1: provide member functions and nested types
- Method 2: provide free-standing functions and specialize metafunctions

#### Method 1: provide member functions and nested types

This procedure assumes that you have control over the types that should be made conformant to a Range concept. If not, see method 2.

The primary templates in this library are implemented such that standard containers will work automatically and so will `boost::array`. Below is given an overview of which member functions and member types a class must specify to be useable as a certain Range concept.

Member function | Related concept
--- | ---
`begin()` | Single Pass Range
`end()` | Single Pass Range

Notice that `rbegin()` and `rend()` member functions are not needed even though the container can support bidirectional iteration.

The required member types are:

Member type | Related concept
--- | ---
`iterator` | Single Pass Range
`const_iterator` | Single Pass Range

Again one should notice that member types `reverse_iterator` and `const_reverse_iterator` are not needed.

#### Method 2: provide free-standing functions and specialize metafunctions

This procedure assumes that you cannot (or do not wish to) change the types that should be made conformant to a Range concept. If this is not true, see method 1.

The primary templates in this library are implemented such that certain functions are found via argument-dependent-lookup (ADL). Below is given an overview of which free-standing functions a class must specify to be useable as a certain Range concept. Let `x` be a variable (`const` or mutable) of the class in question.

Function | Related concept
--- | ---
`range_begin(x)` | Single Pass Range
`range_end(x)` | Single Pass Range

`range_begin()` and `range_end()` must be overloaded for both `const` and mutable reference arguments.

You must also specialize two metafunctions for your type `X`:

Metafunction | Related concept
--- | ---
`boost::range_mutable_iterator` | Single Pass Range
`boost::range_const_iterator` | Single Pass Range

A complete example is given here:

>     #include <boost/range.hpp>
>     #include <iterator>         // for std::iterator_traits, std::distance()

>     namespace Foo
>     {
>         //
>         // Our sample UDT. A 'Pair'
>         // will work as a range when the stored
>         // elements are iterators.
>         //
>         template< class T >
>         struct Pair
>         {
>             T first, last;
>         };

>     } // namespace 'Foo'

>     namespace boost
>     {
>         //
>         // Specialize metafunctions. We must include the range.hpp header.
>         // We must open the 'boost' namespace.
>         //

>         template< class T >
>         struct range_mutable_iterator< Foo::Pair<T> >
>         {
>             typedef T type;
>         };

>         template< class T >
>         struct range_const_iterator< Foo::Pair<T> >
>         {
>             //
>             // Remark: this is defined similar to 'range_mutable_iterator'
>             //         because the 'Pair' type does not distinguish
>             //         between an iterator and a const_iterator.
>             //
>             typedef T type;
>         };

>     } // namespace 'boost'

>     namespace Foo
>     {
>         //
>         // The required functions. These should be defined in
>         // the same namespace as 'Pair', in this case
>         // in namespace 'Foo'.
>         //

>         template< class T >
>         inline T range_begin( Pair<T>& x )
>         {
>             return x.first;
>         }

>         template< class T >
>         inline T range_begin( const Pair<T>& x )
>         {
>             return x.first;
>         }

>         template< class T >
>         inline T range_end( Pair<T>& x )
>         {
>             return x.last;
>         }

>         template< class T >
>         inline T range_end( const Pair<T>& x )
>         {
>             return x.last;
>         }

>     } // namespace 'Foo'

>     #include <vector>

>     int main()
>     {
>         typedef std::vector<int>::iterator  iter;
>         std::vector<int>                    vec;
>         Foo::Pair<iter>                     pair  = { vec.begin(), vec.end() };
>         const Foo::Pair<iter>&              cpair = pair;
>         //
>         // Notice that we call 'begin' etc with qualification.
>         //
>         iter i = boost::begin( pair );
>         iter e = boost::end( pair );
>         i      = boost::begin( cpair );
>         e      = boost::end( cpair );
>         boost::range_difference< Foo::Pair<iter> >::type s = boost::size( pair );
>         s      = boost::size( cpair );
>         boost::range_reverse_iterator< const Foo::Pair<iter> >::type
>         ri     = boost::rbegin( cpair ),
>         re     = boost::rend( cpair );
>     }

© Copyright Thorsten Ottosen 2008.

Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at www.boost.org/LICENSE_1_0.txt)