Iterator Adaptor

Author: David Abrahams, Jeremy Siek, Thomas Witt
Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization: Boost Consulting, Indiana University Open Systems Lab, University of Hanover Institute for Transport Railway Operation and Construction
Date: 2003-08-05
Copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
abstract:

The iterator_adaptor is a base class template derived from an instantiation of iterator_facade. The core interface functions expected by iterator_facade are implemented in terms of the iterator_adaptor's Base template parameter. A class derived from iterator_adaptor typically redefines some of the core interface functions to adapt the behavior of the Base type. Whether the derived class models any of the standard iterator concepts depends on the operations supported by the Base type and which core interface functions of iterator_facade are redefined in the Derived class.

Table of Contents

Introduction

The iterator_adaptor class template adapts some Base 1 type to create a new iterator. Instantiations of iterator_adaptor are derived from a corresponding instantiation of iterator_facade and implement the core behaviors in terms of the Base type. In essence, iterator_adaptor merely forwards all operations to an instance of the Base type, which it stores as a member.

[1]The term "Base" here does not refer to a base class and is not meant to imply the use of derivation. We have followed the lead of the standard library, which provides a base() function to access the underlying iterator object of a reverse_iterator adaptor.

The user of iterator_adaptor creates a class derived from an instantiation of iterator_adaptor and then selectively redefines some of the core member functions described in the table above. The Base type need not meet the full requirements for an iterator. It need only support the operations used by the core interface functions of iterator_adaptor that have not been redefined in the user's derived class.

Several of the template parameters of iterator_adaptor default to use_default. This allows the user to make use of a default parameter even when the user wants to specify a parameter later in the parameter list. Also, the defaults for the corresponding associated types are fairly complicated, so metaprogramming is required to compute them, and use_default can help to simplify the implementation. Finally, use_default is not left unspecified because specification helps to highlight that the Reference template parameter may not always be identical to the iterator's reference type, and will keep users making mistakes based on that assumption.

Reference

template <
    class Derived
  , class Base
  , class Value      = use_default
  , class Category   = use_default
  , class Reference  = use_default
  , class Difference = use_default
>
class iterator_adaptor 
  : public iterator_facade<Derived, /* see details ...*/>
{
    friend class iterator_core_access;
 public:
    iterator_adaptor();
    explicit iterator_adaptor(Base iter);
    Base base() const;
 protected:
    Base const& base_reference() const;
    Base& base_reference();
 private: // Core iterator interface for iterator_facade.  
    typename iterator_adaptor::reference dereference() const;

    template <
    class OtherDerived, class OtherIterator, class V, class C, class R, class D
    >   
    bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;

    void advance(typename iterator_adaptor::difference_type n);
    void increment();
    void decrement();

    template <
        class OtherDerived, class OtherIterator, class V, class C, class R, class D
    >   
    typename iterator_adaptor::difference_type distance_to(
        iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;

 private:
    Base m_iterator;
};

iterator_adaptor requirements

The Derived template parameter must be a derived class of iterator_adaptor. The Base type must implement the expressions involving m_iterator in the specifications of those private member functions of iterator_adaptor that are not redefined by the Derived class and that are needed to model the concept corresponding to the iterator_adaptor's category typedef according to the requirements of iterator_facade. The rest of the template parameters specify the types for the member typedefs in iterator_facade. The following pseudo-code specifies the traits types for iterator_adaptor.

if (Value == use_default)
    value_type = iterator_traits<Base>::value_type;
else 
    value_type = remove_cv<Value>::type;

if (Reference == use_default) {
    if (Value == use_default)
        reference = iterator_traits<Base>::reference;
    else 
        reference = Value&;
} else
    reference = Reference;

if (Distance == use_default)
    difference_type = iterator_traits<Base>::difference_type;
else
    difference_type = Distance;

if (Category == use_default)
    iterator_category = iterator_tag< 
        access_category< Base >,
        traversal_category< Base >
    >
else if (Category is an access tag)
    iterator_category = iterator_tag<
        Category
    ...

else if (Category is a traversal tag)
    ...
else
    iterator_category = Category;
    // Actually the above is wrong.  See the use of
    // access_category_tag and
    // new_category_to_access/iter_category_to_access.

iterator_adaptor public operations

iterator_adaptor();

Requires:The Base type must be Default Constructible.
Returns:An instance of iterator_adaptor with m_iterator default constructed.

explicit iterator_adaptor(Base iter);

Returns:An instance of iterator_adaptor with m_iterator copy constructed from iter.

Base base() const;

Returns:m_iterator

iterator_adaptor protected member functions

Base const& base_reference() const;

Returns:A const reference to m_iterator.

Base& base_reference();

Returns:A non-const reference to m_iterator.

iterator_adaptor private member functions

typename iterator_adaptor::reference dereference() const;

Returns:*m_iterator
template <
class OtherDerived, class OtherIterator, class V, class C, class R, class D
>   
bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
Returns:m_iterator == x.base()

void advance(typename iterator_adaptor::difference_type n);

Effects:m_iterator += n;

void increment();

Effects:++m_iterator;

void decrement();

Effects:--m_iterator;
template <
    class OtherDerived, class OtherIterator, class V, class C, class R, class D
>   
typename iterator_adaptor::difference_type distance_to(
    iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
Returns:y.base() - m_iterator