#ifndef _MAPITL_ITERATOR_H
#define _MAPITL_ITERATOR_H

namespace MAPITL 
{
  /// Wrapper around a MuPAD DOM_LIST to make it an iterator

  // GCC 3.4 requires the friend template functions to be predeclared!
  // Yeah, even more redundancy in C++ ...
  template<class T> class Iterator;
  template<class T> bool operator == (const Iterator<T> &, const Iterator<T> &);
  template<class T> bool operator != (const Iterator<T> &, const Iterator<T> &);
  template<class T> bool operator <  (const Iterator<T> &, const Iterator<T> &);
  template<class T> bool operator >  (const Iterator<T> &, const Iterator<T> &);
  template<class T> bool operator <= (const Iterator<T> &, const Iterator<T> &);
  template<class T> bool operator >= (const Iterator<T> &, const Iterator<T> &);
  template<class T> typename Iterator<T>::difference_type operator - (const Iterator<T> &, const Iterator<T> &);

  template<class T>
  class Iterator {
  private:
    MTcell c;
    size_t i;
  public:
    // Standard iterator typedefs
    
    typedef T	      			value_type;
    typedef size_t      		difference_type;
    typedef random_access_iterator_tag	iterator_category;
    typedef value_type *		pointer;
    typedef const value_type *		const_pointer;
    typedef MAPITL::Reference<T>	reference;

    Iterator(MTcell c_, size_t i_) : c(c_), i(i_) {}
    value_type operator *  () const;
    reference  operator *  ();

    const_pointer operator -> () const;
    
    Iterator&  operator ++ ();
    Iterator&  operator -- ();

    Iterator   operator ++ (int);
    Iterator   operator -- (int);

    Iterator&  operator += (difference_type);
    Iterator&  operator -= (difference_type);

    friend bool operator ==<> (const Iterator &, const Iterator &);
    friend bool operator !=<> (const Iterator &, const Iterator &);
    friend bool operator < <> (const Iterator &, const Iterator &);
    friend bool operator > <> (const Iterator &, const Iterator &);
    friend bool operator <=<> (const Iterator &, const Iterator &);
    friend bool operator >=<> (const Iterator &, const Iterator &);
    
    friend difference_type operator -<> (const Iterator &, const Iterator &);
  };
  
  template<class T>
  bool operator ==  (const Iterator<T> &, const Iterator<T> &);
  template<class T>
  bool operator != (const Iterator<T> &, const Iterator<T> &);
  template<class T>
  bool operator <  (const Iterator<T> &, const Iterator<T> &);
  template<class T>
  bool operator >  (const Iterator<T> &, const Iterator<T> &);
  template<class T>
  bool operator <= (const Iterator<T> &, const Iterator<T> &);
  template<class T>
  bool operator >= (const Iterator<T> &, const Iterator<T> &);
    
  template<class T>
  typename Iterator<T>::difference_type
  operator - (const Iterator<T> &, const Iterator<T> &);
}

#endif	/* _MAPITL_ITERATOR_H */
