Nunca he implementado STL-como iteradores y trato de entender cómo implementar una cosa muy básica basada en punteros. Una vez que se tiene esta clase voy a ser capaz de modificarlo para hacer cosas más complicadas. En consecuencia, este es un primer paso, y la necesito para ser roca sólida para entender cómo escribir mi propia iteradores (sin impulso).

He escrito el siguiente código y sé que hay errores en ella. Me pueden ayudar a diseñar correctamente un Iterador de Acceso Aleatorio clase inspirado a partir de que :

template<Type> class Container<Type>::Iterator : public std::iterator<random_access_iterator_tag, Type>
{
//Lifecycle:
public:
Iterator() : _ptr(nullptr) {;}
Iterator(Type* rhs) : _ptr(rhs) {;}
Iterator(const Iterator &rhs) : _ptr(rhs._ptr) {;}
//Operators : misc
public:
inline Iterator& operator=(Type* rhs) {_ptr = rhs; return *this;}
inline Iterator& operator=(const Iterator &rhs) {_ptr = rhs._ptr; return *this;}
inline Iterator& operator+=(const int& rhs) {_ptr += rhs; return *this;}
inline Iterator& operator-=(const int& rhs) {_ptr -= rhs; return *this;}
inline Type& operator*() {return *_ptr;}
inline Type* operator->() {return _ptr;}
inline Type& operator[](const int& rhs) {return _ptr[rhs];}
//Operators : arithmetic
public:
inline Iterator& operator++() {++_ptr; return *this;}
inline Iterator& operator--() { --_ptr; return *this;}
inline Iterator& operator++(int) {Iterator tmp(*this); ++_ptr; return tmp;}
inline Iterator& operator--(int) {Iterator tmp(*this); --_ptr; return tmp;}
inline Iterator operator+(const Iterator& rhs) {return Iterator(_ptr+rhs.ptr);}
inline Iterator operator-(const Iterator& rhs) {return Iterator(_ptr-rhs.ptr);}
inline Iterator operator+(const int& rhs) {return Iterator(_ptr+rhs);}
inline Iterator operator-(const int& rhs) {return Iterator(_ptr-rhs);}
friend inline Iterator operator+(const int& lhs, const Iterator& rhs) {return Iterator(lhs+_ptr);}
friend inline Iterator operator-(const int& lhs, const Iterator& rhs) {return Iterator(lhs-_ptr);}
//Operators : comparison
public:
inline bool operator==(const Iterator& rhs) {return _ptr == rhs._ptr;}
inline bool operator!=(const Iterator& rhs) {return _ptr != rhs._ptr;}
inline bool operator>(const Iterator& rhs) {return _ptr > rhs._ptr;}
inline bool operator<(const Iterator& rhs) {return _ptr < rhs._ptr;}
inline bool operator>=(const Iterator& rhs) {return _ptr >= rhs._ptr;}
inline bool operator<=(const Iterator& rhs) {return _ptr <= rhs._ptr;}
//Data members
protected:
Type* _ptr;
};

Muchas gracias.

¿Qué errores? Errores del compilador? Enlazador de errores? Errores de tiempo de ejecución? Los errores lógicos? Algo más?
«Sé que hay errores» — esto es algún tipo de prueba? Creo que no es el sitio adecuado para que…
Un puntero es un iterador. ¿Cuál es el propósito de envolver con una clase?
El propósito es entender cómo implementar correctamente una clase iterator (en particular, la función de firmas y lo que la función de hacer).
Así que usted realmente no necesita public por todo el lugar, pero como usted no tiene los datos de los miembros en ellos no hace ninguna diferencia. return Iterator(_ptr+rhs); en teoría crea un extra temporales innecesarios, que sólo podría return _ptr+rhs;.

OriginalEl autor Vincent | 2012-08-23

3 Comentarios

  1. 0

    En general, su enfoque es correcto. El postfix incremento/decremento operador debe devolver por valor de, no por referencia. También tengo dudas acerca de:

    Iterator(Type* rhs) : _ptr(rhs) {;}

    Este le dice a todos que esta clase iterator es implementado alrededor de los punteros. Me gustaría tratar de hacer que este método sólo se puede llamar por el contenedor. Mismo para la asignación de un puntero.
    La adición de dos iteradores no tiene sentido para mí (me gustaría dejar «iterador+int»). La resta de dos iteradores señala el mismo contenedor podría tener algún sentido.

    Como decía, esta es una práctica educativa, es por eso que él va todo el cerdo. Me sorprendió sobre operator[] demasiado, pero no para los iteradores de acceso aleatorio! en.cppreference.com/w/cpp/concept/RandomAccessIterator
    gracias. Se corrigió.
    Creo que usted necesita inline difference_type operator-(const Iterator&) en lugar de inline Iterator operator-(const Iterator&). No creo que se necesita el mismo para operator+. Algunos de los algoritmos (como std::sort) no parecen funcionar sin la difference_type operator-. Usted no puede tener ambas, ya que sólo el retorno de tipos diferentes.

    OriginalEl autor Alexander Chertov

  2. 9

    El código tiene los siguientes problemas:

    • No sigue la Regla de Tres/Cinco. La mejor opción en su situación no es declarar cualquier personalizado destructores, copiar/mover los constructores o copiar/mover operadores de asignación. Vamos a seguir así llamada Regla de Cero.
    • Iterator(Type* rhs) podría ser privado y la Container podría ser marcado como Iteratoramigo’s, pero que no es estrictamente necesario.
    • operator=(Type* rhs) es una mala idea. Que no se qué tipo de seguridad se acerca.
    • Post-en(de)crementation debe devolver Iterator, no Iterator &.
    • La adición de dos iteradores no tiene ningún significado.
    • Restar dos iteradores debe devolver una diferencia, no un nuevo iterador.
    • Debe utilizar std::iterator<std::random_access_iterator_tag, Type>::difference_type en lugar de const int &.
    • Si un método no modifica un objeto, que debe estar marcado const.

    Recurso útil: RandomAccessIterator @ cppreference.com

    Aquí es una versión fija de su código:

    template<typename Type>
    class Container<Type>::Iterator : public std::iterator<std::random_access_iterator_tag, Type>
    {
    public:
    using difference_type = typename std::iterator<std::random_access_iterator_tag, Type>::difference_type;
    Iterator() : _ptr(nullptr) {}
    Iterator(Type* rhs) : _ptr(rhs) {}
    Iterator(const Iterator &rhs) : _ptr(rhs._ptr) {}
    /* inline Iterator& operator=(Type* rhs) {_ptr = rhs; return *this;} */
    /* inline Iterator& operator=(const Iterator &rhs) {_ptr = rhs._ptr; return *this;} */
    inline Iterator& operator+=(difference_type rhs) {_ptr += rhs; return *this;}
    inline Iterator& operator-=(difference_type rhs) {_ptr -= rhs; return *this;}
    inline Type& operator*() const {return *_ptr;}
    inline Type* operator->() const {return _ptr;}
    inline Type& operator[](difference_type rhs) const {return _ptr[rhs];}
    inline Iterator& operator++() {++_ptr; return *this;}
    inline Iterator& operator--() { --_ptr; return *this;}
    inline Iterator operator++(int) const {Iterator tmp(*this); ++_ptr; return tmp;}
    inline Iterator operator--(int) const {Iterator tmp(*this); --_ptr; return tmp;}
    /* inline Iterator operator+(const Iterator& rhs) {return Iterator(_ptr+rhs.ptr);} */
    inline difference_type operator-(const Iterator& rhs) const {return Iterator(_ptr-rhs.ptr);}
    inline Iterator operator+(difference_type rhs) const {return Iterator(_ptr+rhs);}
    inline Iterator operator-(difference_type rhs) const {return Iterator(_ptr-rhs);}
    friend inline Iterator operator+(difference_type lhs, const Iterator& rhs) {return Iterator(lhs+rhs._ptr);}
    friend inline Iterator operator-(difference_type lhs, const Iterator& rhs) {return Iterator(lhs-rhs._ptr);}
    inline bool operator==(const Iterator& rhs) const {return _ptr == rhs._ptr;}
    inline bool operator!=(const Iterator& rhs) const {return _ptr != rhs._ptr;}
    inline bool operator>(const Iterator& rhs) const {return _ptr > rhs._ptr;}
    inline bool operator<(const Iterator& rhs) const {return _ptr < rhs._ptr;}
    inline bool operator>=(const Iterator& rhs) const {return _ptr >= rhs._ptr;}
    inline bool operator<=(const Iterator& rhs) const {return _ptr <= rhs._ptr;}
    private:
    Type* _ptr;
    };
    Iterator operator++(int) const – no puede ser const

    OriginalEl autor cubuspl42

  3. 2

    Echar un vistazo a cómo Impulsar hacerlo, los iteradores en impulso/contenedor/vector.chvector_const_iterator y vector_iterator son razonablemente fáciles de entender puntero basado en los iteradores.

    OriginalEl autor Silas Parker

Dejar respuesta

Please enter your comment!
Please enter your name here