// Iterator_identity.h
// ----------------------------------------------------------------
// COMP 290-001: Algorithm Library Design, Lutz Kettner, 01/11/2000
// The identity iterator adaptor.

// //###// marks the places that need adaption for other iterator 
// functionality. The class is structured according to increasing 
// requirements (the refinement relationship among concepts).

#ifndef CBP_ITERATOR_IDENTITY_H
#define CBP_ITERATOR_IDENTITY_H 1

#include <iterator>

template < class I >
class Iterator_identity {
private:
    I        nt;    // The internal iterator.
public:
    typedef I                                  Iterator;
    typedef Iterator_identity<I>               Self;

    typedef std::iterator_traits<I>            traits;
    typedef typename traits::reference         reference;
    typedef typename traits::pointer           pointer;
    typedef typename traits::value_type        value_type;
    typedef typename traits::difference_type   difference_type;
    typedef typename traits::iterator_category iterator_category;

    // Default Constructible !
    Iterator_identity() {}
    Iterator_identity( Iterator j) : nt(j) {}

    // Assignable by default, but templated constructor implements
    // autamtic conversion between Iterator_identity's whose underlying
    // iterator types are assignable.
    template <class II>
    Iterator_identity( const Iterator_identity<II>& ii) 
	: nt( ii.current_iterator()) {}

    // Additional member functions (typically accessors):
    Iterator  current_iterator() const { return nt;}

    // Equality Comparable:
    bool operator==( const Self& i) const { return ( nt == i.nt); }     //###//
    bool operator!=( const Self& i) const { return !(*this == i); }

    // Trivial Iterator:
    reference operator*()  const { return *nt; }                        //###//
    pointer   operator->() const { return & operator*(); }

    // Input Iterator, Forward Iterator
    Self& operator++() {
        ++nt;                                                           //###//
        return *this;
    }
    const Self  operator++(int) {
        Self tmp = *this;
        ++*this;
        return tmp;
    }

    // Bidirectional Iterator
    Self& operator--() {
        --nt;                                                           //###//
        return *this;
    }
    const Self  operator--(int) {
        Self tmp = *this;
        --*this;
        return tmp;
    }

    // Random Access Iterator
    Self& operator+=( difference_type n) {
        nt += n;                                                        //###//
        return *this;
    }
    const Self  operator+( difference_type n) const {
        Self tmp = *this;
        return tmp += n;
    }
    Self& operator-=( difference_type n) { return operator+=( -n); }
    const Self  operator-( difference_type n) const {
        Self tmp = *this;
        return tmp += -n;
    }
    difference_type  operator-( const Self& i) const {
        return nt - i.nt;                                               //###//
    }
    reference  operator[]( difference_type n) const {
        Self tmp = *this;
        tmp += n;
        return tmp.operator*();
    }
    bool operator< ( const Self& i) const { return ( nt < i.nt); }      //###//
    bool operator> ( const Self& i) const { return i < *this; }
    bool operator<=( const Self& i) const { return !(i < *this); }
    bool operator>=( const Self& i) const { return !(*this < i); }
};

template < class D, class I>
inline
Iterator_identity<I> operator+( D n, Iterator_identity<I> i) {
    typedef typename Iterator_identity<I>::difference_type difference_type;
    return i += difference_type(n);
}
 
#endif // ITERATOR_IDENTITY_H //
// EOF //

