text: // Copyright (c) 2007 
  // GeometryFactory (France),
  // Utrecht University (The Netherlands),
  // ETH Zurich (Switzerland),
  // INRIA Sophia-Antipolis (France),
  // Max-Planck-Institute Saarbruecken (Germany),
  // and Tel-Aviv University (Israel). All rights reserved.
  //
  // This file is part of CGAL (www.cgal.org)
  //
  // $URL: https://github.com/CGAL/cgal/blob/releases/CGAL-5.0.2/STL_Extension/include/CGAL/Iterator_transform.h $
  // $Id: Iterator_transform.h 52164b1 2019-10-19T15:34:59+02:00 Sébastien Loriot
  // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
  // 
  //
  // Author(s)     : Michael Hoffmann <hoffmann@inf.ethz.ch>
  //                 Lutz Kettner <kettner@mpi-sb.mpg.de>
  //                 Sylvain Pion
  //                 Fernando Cacciola <fernando.cacciola@geometryfactory.com> 
  
  #ifndef CGAL_ITERATOR_TRANSFORM_H
  #define CGAL_ITERATOR_TRANSFORM_H 1
  
  #include <CGAL/Iterator_project.h>
  
  namespace CGAL {
  
  template < class I, class Fct>
  class Iterator_transform {
  protected:
    I        nt;    // The internal iterator.
  public:
    typedef Iterator_transform<I,Fct> Self;
    typedef I                                   Iterator; // base iterator
    typedef std::iterator_traits<I>             traits;
    typedef typename traits::difference_type    difference_type;
    typedef typename traits::iterator_category  iterator_category;
    typedef typename traits::value_type         base_value_type;
    typedef typename traits::pointer            base_pointer;
    typedef typename traits::reference          base_reference;
  
    typedef typename Fct::argument_type         argument_type;
    typedef typename Fct::result_type           value_type;
  
  
    // This iterator returns rvalues by design (allowing the conversion function to return new objects)
    typedef value_type reference;
  
    // Use I_TYPE_MATCH_IF to find correct pointer type.
    typedef I_TYPE_MATCH_IF< base_pointer, const base_value_type *,
      const value_type *, value_type *> Match2;
    typedef typename Match2::Result             pointer;
  
    // CREATION
    // --------
  
    Iterator_transform() {}
    Iterator_transform( I j) : nt(j) {}
  
    // make two iterators assignable if the underlying iterators are
    template <class I2>
    Iterator_transform( const Iterator_transform<I2,Fct>& i2)
    : nt( i2.current_iterator()) {}
  
    template <class I2>
    Self& operator= ( const Iterator_transform<I2,Fct>& i2) {
      nt = i2.current_iterator();
      return *this;
    }
  
    // OPERATIONS Forward Category
    // ---------------------------
  
    Iterator  current_iterator() const { return nt;}
    bool      operator==( const Self& i) const { return ( nt == i.nt); }
    bool      operator!=( const Self& i) const { return !(*this == i); }
    
    struct Proxy
    {
        Proxy(const reference r) : ref(r) {}
        reference ref;
        pointer operator->() { return &ref; }
    };
  
    Proxy operator->() const
    {
        return Proxy(Fct()(*nt));
    }
    
    reference operator* () const 
    {
      Fct fct;
      return fct(*nt);
    }
    
    Self&     operator++() {
      ++nt;
      return *this;
    }
    Self      operator++(int) {
      Self tmp = *this;
      ++*this;
      return tmp;
    }
  
    // OPERATIONS Bidirectional Category
    // ---------------------------------
  
    Self& operator--() {
      --nt;
      return *this;
    }
    Self  operator--(int) {
      Self tmp = *this;
      --*this;
      return tmp;
    }
  
    // OPERATIONS Random Access Category
    // ---------------------------------
  
    Self& operator+=( difference_type n) {
      nt += n;
      return *this;
    }
    Self  operator+( difference_type n) const {
      Self tmp = *this;
      return tmp += n;
    }
    Self& operator-=( difference_type n) {
      return operator+=( -n);
    }
    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 Dist, class Fct, class I>
  inline
  Iterator_transform<I,Fct>
  operator+( Dist n, Iterator_transform<I,Fct> i) {
    return i += n;
  }
  
  } //namespace CGAL
  #endif // CGAL_Iterator_transform_H //
  // EOF //
  