C++-Programmierung/ Eine Matrix-Bibliothek – mitrax/ proxy iterator.hpp

Aus Wikibooks
#ifndef _mitrax_mitrax_detail_proxy_iterator_hpp_INCLUDED_
#define _mitrax_mitrax_detail_proxy_iterator_hpp_INCLUDED_
/// \file proxy_iterator.hpp
///
/// \brief Proxyiteratorklassen
///
/// Diese Datei stellt allgemeine Basisklassen für Forward-, Bidirectional- und
/// Random-Access-Iteratoren bereit. Von dieses sind die vier Proxyiteratorklassen abgleitet.
/// Ein Nutzer von mitrax sollte keinen direkten Kontakt mit diesen Klassen haben, daher stehen
/// alle im Namensraum <code>detail</code>.

#include <iterator>
#include <memory>

namespace mitrax { namespace detail {

/// \brief Basisklasse für alle Forward-Iteratoren
template < typename Derived >
class forward_iterator_base{
protected:
    /// \brief Standardkonstruktor nur für abgeleitete Klassen
    forward_iterator_base(){}
    /// \brief Kopierkonstruktor nur für abgeleitete Klassen
    forward_iterator_base(forward_iterator_base const&){}

public:
    /// \brief Postfix-Inkrement-Operator
    friend Derived const operator++(Derived& self, int){Derived tmp(self); ++self; return tmp;}
    /// \brief Vergleichsoperator auf Ungleichheit
    friend bool operator!=(Derived const& lhs, Derived const& rhs){return !(lhs == rhs);}
};


/// \brief Basisklasse für alle Bidirectional-Iteratoren
template < typename Derived >
class bidirectional_iterator_base:
    public forward_iterator_base< Derived >{
protected:
    /// \brief Standardkonstruktor nur für abgeleitete Klassen
    bidirectional_iterator_base(){}
    /// \brief Kopierkonstruktor nur für abgeleitete Klassen
    ///
    /// Expliziter Basisklassen-Konstruktoraufruf vermeidet beim Kopierkonstruktor Compilerwarnung
    bidirectional_iterator_base(bidirectional_iterator_base const&):
        forward_iterator_base< Derived >(){}

public:
    /// \brief Postfix-Dekrement-Operator
    friend Derived const operator--(Derived& self, int){Derived tmp(self); --self; return tmp;}
};


/// \brief Basisklasse für alle Random-Access-Iteratoren
template < typename Derived, typename DifferenceType >
class random_access_iterator_base:
    public bidirectional_iterator_base< Derived >{
protected:
    /// \brief Standardkonstruktor nur für abgeleitete Klassen
    random_access_iterator_base(){}
    /// \brief Kopierkonstruktor nur für abgeleitete Klassen
    ///
    /// Expliziter Basisklassen-Konstruktoraufruf vermeidet beim Kopierkonstruktor Compilerwarnung
    random_access_iterator_base(random_access_iterator_base const&):
        bidirectional_iterator_base< Derived >(){}

public:
    /// \brief Vergleichsoperator kleiner
    friend bool operator<(Derived const& lhs, Derived const& rhs){
        return rhs - lhs > DifferenceType();
    }
    /// \brief Vergleichsoperator größer
    friend bool operator>(Derived const& lhs, Derived const& rhs){return rhs < lhs;}
    /// \brief Vergleichsoperator kleiner-gleich
    friend bool operator<=(Derived const& lhs, Derived const& rhs){return !(lhs > rhs);}
    /// \brief Vergleichsoperator größer-gleich
    friend bool operator>=(Derived const& lhs, Derived const& rhs){return !(lhs < rhs);}

    /// \brief Negative Positionsverschiebung
    Derived& operator-=(DifferenceType const& difference){
        return static_cast< Derived& >(*this) += -difference;
    }

    /// \brief Positive Positionsverschiebung als neues Objekt
    friend Derived const operator+(Derived lhs, DifferenceType const& rhs){return lhs += rhs;}
    /// \brief Positive Positionsverschiebung als neues Objekt
    friend Derived const operator+(DifferenceType const& rhs, Derived lhs){return lhs += rhs;}
    /// \brief Negative Positionsverschiebung als neues Objekt
    friend Derived const operator-(Derived lhs, DifferenceType const& rhs){return lhs -= rhs;}
};



template < typename Matrix >
class row_const_iterator;

template < typename Matrix >
class row_iterator;

template < typename Matrix >
class column_const_iterator;

template < typename Matrix >
class column_iterator;



/// \brief Basisklasse für alle Zeilen-Iteratoren
template < typename Derived, typename MatrixIterator >
class row_iterator_base:
    public random_access_iterator_base< Derived, typename MatrixIterator::difference_type >
{
public:
    // types
    /// \brief Iterator-Trait <code>value_type</code>
    typedef typename MatrixIterator::value_type      value_type;
    /// \brief Iterator-Trait <code>difference_type</code>
    typedef typename MatrixIterator::difference_type difference_type;
    /// \brief Iterator-Trait <code>pointer</code>
    typedef typename MatrixIterator::pointer         pointer;
    /// \brief Iterator-Trait <code>reference</code>
    typedef typename MatrixIterator::reference       reference;
    /// \brief Iterator-Trait <code>iterator_category</code> ist
    ///        <code>std::random_access_iterator_tag</code>
    typedef std::random_access_iterator_tag          iterator_category;

    // operators
    /// \brief Dereferenzierungsoperator
    reference operator*()const{return *pos_;}
    /// \brief Member-Zugriffsoperator
    pointer operator->()const{return pos_;}

    /// \brief Präfix-Inkrement-Operator
    Derived& operator++(){++pos_; return static_cast< Derived& >(*this);}
    /// \brief Präfix-Dekrement-Operator
    Derived& operator--(){--pos_; return static_cast< Derived& >(*this);}

    /// \brief Vergleichsoperator auf Gleichheit
    friend bool operator==(Derived const& lhs, Derived const& rhs){return lhs.pos_ == rhs.pos_;}

    /// \brief Positive Positionsverschiebung
    Derived& operator+=(difference_type const& difference){
        pos_ += difference; return static_cast< Derived& >(*this);
    }

    /// \brief Differenzoperator
    friend difference_type const operator-(Derived const& lhs, Derived const& rhs){
        return lhs.pos_ - rhs.pos_;
    }

    /// \brief Indexoperator
    reference operator[](difference_type const& index)const{return *(pos_ + index);}

protected:
    // construct/copy/destroy:
    /// \brief Standardkonstruktor nur für abgeleitete Klassen
    row_iterator_base(): pos_(MatrixIterator()){}
    /// \brief Konstruktor zur Erstellung eines gültigen Iterators nur für abgeleitete Klassen
    row_iterator_base(MatrixIterator const& pos): pos_(pos){}
    /// \brief Kopierkonstruktor nur für abgeleitete Klassen
    ///
    /// Expliziter Basisklassen-Konstruktoraufruf vermeidet beim Kopierkonstruktor Compilerwarnung
    row_iterator_base(row_iterator_base const& iter): base(), pos_(iter.pos_) {}

    // data
    /// \brief Matrixiterator an den Operatoraktionen durchgereicht werden
    MatrixIterator pos_;

private:
    /// \brief Abkürzung für direkte Basisklasse
    typedef random_access_iterator_base< Derived, typename MatrixIterator::difference_type > base;
};


/// \brief Klasse für Zeilen-Iteratoren auf konstanten Matrizen
template < typename Matrix >
class row_const_iterator:
    public row_iterator_base< row_const_iterator< Matrix >, typename Matrix::const_iterator >
{
private:
    /// \brief Kürzel für die Basisklasse
    typedef
    row_iterator_base< row_const_iterator< Matrix >, typename Matrix::const_iterator > base;

public:
    /// \brief Standardkonstruktor
    row_const_iterator(){}
    /// \brief Konstruktor zur Erstellung eines gültigen Iterators
    row_const_iterator(typename Matrix::const_iterator const& pos): base(pos){}
};



/// \brief Klasse für Zeilen-Iteratoren auf Matrizen
template < typename Matrix >
class row_iterator:
    public row_iterator_base< row_iterator< Matrix >, typename Matrix::iterator >
{
private:
    /// \brief Kürzel für die Basisklasse
    typedef row_iterator_base< row_iterator< Matrix >, typename Matrix::iterator > base;

public:
    /// \brief Standardkonstruktor
    row_iterator(){}
    /// \brief Konstruktor zur Erstellung eines gültigen Iterators
    row_iterator(typename Matrix::iterator const& pos): base(pos){}

    /// \brief Typumwandlung nach <code>row_const_iterator< Matrix ></code>
    operator row_const_iterator< Matrix >()const{
        return row_const_iterator< Matrix >(this->pos_);
    }
};



/// \brief Basisklasse für alle Spalten-Iteratoren
template < typename Derived, typename Matrix, typename MatrixIterator >
class column_iterator_base:
    public random_access_iterator_base< Derived, typename MatrixIterator::difference_type >
{
public:
    // types
    /// \brief Iterator-Trait <code>value_type</code>
    typedef typename MatrixIterator::value_type      value_type;
    /// \brief Iterator-Trait <code>difference_type</code>
    typedef typename MatrixIterator::difference_type difference_type;
    /// \brief Iterator-Trait <code>pointer</code>
    typedef typename MatrixIterator::pointer         pointer;
    /// \brief Iterator-Trait <code>reference</code>
    typedef typename MatrixIterator::reference       reference;
    /// \brief Iterator-Trait <code>iterator_category</code> ist
    ///        <code>std::random_access_iterator_tag</code>
    typedef std::random_access_iterator_tag          iterator_category;

    // operators
    /// \brief Dereferenzierungsoperator
    reference operator*()const{ return *(matrix_->begin() + pos_); }
    /// \brief Member-Zugriffsoperator
    pointer operator->()const{ return matrix_->begin() + pos_; }

    /// \brief Präfix-Inkrement-Operator
    Derived& operator++(){
        pos_ += step_width();
        return static_cast< Derived& >(*this);
    }
    /// \brief Präfix-Dekrement-Operator
    Derived& operator--(){
        pos_ -= step_width();
        return static_cast< Derived& >(*this);
    }

    /// \brief Vergleichsoperator auf Gleichheit
    friend bool operator==(Derived const& lhs, Derived const& rhs){
        return lhs.pos_ == rhs.pos_ && lhs.matrix_ == rhs.matrix_;
    }

    /// \brief Positive Positionsverschiebung
    Derived& operator+=(difference_type const& difference){
        pos_ += difference * step_width();
        return static_cast< Derived& >(*this);
    }

    /// \brief Differenzoperator
    friend difference_type const operator-(Derived const& lhs, Derived const& rhs){
        return (rhs.pos_ - lhs.pos_) / lhs.step_width();
    }

    /// \brief Indexoperator
    reference operator[](difference_type const& index)const{
        return *(static_cast< Derived const& >(*this) + index);
    }

protected:
    // construct/copy/destroy:
    /// \brief Standardkonstruktor nur für abgeleitete Klassen
    column_iterator_base():
        matrix_(0), pos_(difference_type()){}

    /// \brief Konstruktor zur Erstellung eines gültigen Iterators nur für abgeleitete Klassen
    column_iterator_base(Matrix& matrix, difference_type const& pos):
        matrix_(&matrix), pos_(pos){}

    /// \brief Kopierkonstruktor nur für abgeleitete Klassen
    ///
    /// Expliziter Basisklassen-Konstruktoraufruf vermeidet beim Kopierkonstruktor Compilerwarnung
    column_iterator_base(column_iterator_base const& iter):
        base(), matrix_(iter.matrix_), pos_(iter.pos_){}

    // data
    /// \brief Verweis auf ein <code>matrix</code>-Objekt
    Matrix*         matrix_;
    /// \brief Position des Iterators gemessen von <code>matrix_.begin()</code> in
    ///        Matrixiterator-Einheiten
    difference_type pos_;

private:
    // helper
    /// \brief Gibt die Zeilenlänge zurück
    difference_type const step_width(){ return matrix_->columns(); }

    /// \brief Abkürzung für direkte Basisklasse
    typedef random_access_iterator_base< Derived, typename MatrixIterator::difference_type > base;
};

/// \brief Klasse für Spalten-Iteratoren auf konstanten Matrizen
template < typename Matrix >
class column_const_iterator:
    public column_iterator_base<
        column_const_iterator< Matrix >, Matrix const, typename Matrix::const_iterator
    >
{
private:
    /// \brief Kürzel für die Basisklasse
    typedef column_iterator_base<
        column_const_iterator< Matrix >, Matrix const, typename Matrix::const_iterator
    > base;

public:
    /// \brief Standardkonstruktor
    column_const_iterator(){}
    /// \brief Konstruktor zur Erstellung eines gültigen Iterators
    column_const_iterator(Matrix const& matrix, typename base::difference_type const& pos):
        base(matrix, pos){}
};



/// \brief Klasse für Spalten-Iteratoren auf Matrizen
template < typename Matrix >
class column_iterator:
    public column_iterator_base< column_iterator< Matrix >, Matrix, typename Matrix::iterator >
{
private:
    /// \brief Kürzel für die Basisklasse
    typedef
    column_iterator_base< column_iterator< Matrix >, Matrix, typename Matrix::iterator > base;

public:
    /// \brief Standardkonstruktor
    column_iterator(){}
    /// \brief Konstruktor zur Erstellung eines gültigen Iterators
    column_iterator(Matrix& matrix, typename base::difference_type const& pos): base(matrix, pos){}

    /// \brief Typumwandlung nach <code>column_const_iterator< Matrix ></code>
    operator column_const_iterator< Matrix >()const{
        return column_const_iterator< Matrix >(*this->matrix_, this->pos_);
    }
};


} }

#endif