cgal/HalfedgeDS/include/CGAL/HalfedgeDS_iterator_adaptor.h

170 lines
6.5 KiB
C++

// Copyright (c) 1997 Utrecht University (The Netherlands),
// ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany),
// INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg
// (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Lutz Kettner <kettner@mpi-sb.mpg.de>
#ifndef CGAL_HALFEDGEDS_ITERATOR_ADAPTOR_H
#define CGAL_HALFEDGEDS_ITERATOR_ADAPTOR_H 1
#include <iterator>
CGAL_BEGIN_NAMESPACE
// The iterator identity adaptor will be used for the HDS implementations
// that are based on STL (or other) container classes which do not
// guarantee that the default construction of its iterator gives always
// the same singular value (i.e. something like NULL). This adaptor
// assumes that iterator traits are fully supported. It works for all
// kinds of iterators, from input iterators to random access iterators.
// It does no longer require that these iterators have a constructor
// accepting zero as an argument (e.g. a pointer). This approach has
// failed with the KCC compiler (Kai's C++).
// Instead, we rely now on a static local variable. Static variables are
// first of all zero-initialized (Section 3.6.2), which guarantees that
// pointers and such are set to zero even if the construtor does not
// initialize them (Section 8.5). With static variables, the order of
// initialization could be critical, if the initialization of one
// requires another one to be initialized already (I have not seen such a
// design for iterator yet, but who knows, maybe if reference counting
// come into play). If global static variables are in different
// compilation units, there order of initialization is unspecified.
// However, if the static variable is a local variable, the
// initialization happens before the surrounding function is called if
// the type is a POD, otherwise the initialization happens when the
// control flow passes through the declaration of the static variable the
// first time (Section 6.7), which costs performance but makes it safe
// for weird static initialization situations. Usually the std::vector
// class uses a plain C-pointer as iterator, which would be a POD and
// thus efficient. However, the std::list iterators might not be POD's if
// they define their own copy contructor. This is the case for
// std::list::iterator of the current SGI STL, but not for the
// std::list::const_iterator, which is a funny side-effect of having
// only a single class for both and a constructor that allows iterator to
// const_iterator conversions. The bottom line is, std::vector is fine,
// std::list could cost a bit performance and In_place_list might be
// preferable.
template < class I>
class HalfedgeDS_iterator_adaptor {
private:
I nt; // The internal iterator.
// keep the local static variable for the null iterator
// in a small inline function, optimizers might like that
// better than a static function.
const I& null_iterator() const {
static I it = I(); // zero-initialized and a default constructor
return it;
}
public:
typedef I Iterator;
typedef HalfedgeDS_iterator_adaptor<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;
// CREATION
// --------
// explicitly set to 0
HalfedgeDS_iterator_adaptor() : nt( null_iterator()) {}
HalfedgeDS_iterator_adaptor( Iterator j) : nt(j) {} // down cast
template < class J>
HalfedgeDS_iterator_adaptor( const HalfedgeDS_iterator_adaptor<J>& j)
: nt(j.iterator()) {}
// OPERATIONS Forward Category
// ---------------------------
Iterator iterator() const { return nt;}
bool operator==( const Self& i) const { return ( nt == i.nt); }
bool operator!=( const Self& i) const { return !(*this == i); }
reference operator*() const { return *nt; }
pointer operator->() const { return &*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); }
};
CGAL_END_NAMESPACE
// we don't need Koenig lookup here
template < class D, class I>
inline
CGAL::HalfedgeDS_iterator_adaptor<I>
operator+( D n, CGAL::HalfedgeDS_iterator_adaptor<I> i) {
return i += Dist(n);
}
#endif // CGAL_HALFEDGEDS_ITERATOR_ADAPTOR_H //
// EOF //