libreria - list iterator c++
Creando mis propios iteradores (6)
/ EDITAR: Ya veo, un iterador propio es realmente necesario aquí (he leído mal la pregunta primero). Aún así, dejo que el código a continuación permanezca porque puede ser útil en circunstancias similares.
¿Es un iterador propio realmente necesario aquí? Quizás sea suficiente enviar todas las definiciones requeridas al contenedor que contiene los puntos reales:
// Your class `Piece`
class Piece {
private:
Shape m_shape;
public:
typedef std::vector<Point>::iterator iterator;
typedef std::vector<Point>::const_iterator const_iterator;
iterator begin() { return m_shape.container.begin(); }
const_iterator begin() const { return m_shape.container.begin(); }
iterator end() { return m_shape.container.end(); }
const_iterator end() const { return m_shape.const_container.end(); }
}
Esto supone que estás usando un vector
internamente, pero el tipo puede adaptarse fácilmente.
Estoy tratando de aprender C ++, así que perdónenme si esta pregunta demuestra una falta de conocimiento básico, ya ven, el hecho es que tengo una falta de conocimiento básico.
Quiero ayuda para encontrar un iterador para una clase que he creado.
Tengo una clase ''Shape'' que tiene un contenedor de puntos. Tengo una clase ''Pieza'' que hace referencia a una Forma y define una posición para la Forma. La pieza no tiene forma, solo hace referencia a una forma.
Quiero que parezca que Piece es un contenedor de puntos que son los mismos que los de la figura a la que hace referencia pero con el desplazamiento de la posición de la pieza añadida.
Quiero poder iterar a través de los puntos de la pieza como si Piece fuera un contenedor. He leído un poco y no he encontrado nada que me haya ayudado. Estaría muy agradecido por cualquier punteros.
Aquí Diseñar un STL como Custom Container es un excelente artículo que explica algunos de los conceptos básicos de cómo se puede diseñar una clase de contenedor tipo STL junto con la clase de iterador para él. Sin embargo, el iterador inverso (un poco más difícil) se deja como un ejercicio :-)
HTH,
Deberías usar Boost.Iterators. Contiene una serie de plantillas y conceptos para implementar nuevos iteradores y adaptadores para iteradores existentes. He escrito un artículo sobre este mismo tema ; está en la revista ACCU de diciembre de 2008. Discute una solución elegante (IMO) para su problema exactamente: exponer colecciones de miembros de un objeto, usando Boost.Iterators.
Si desea usar stl solamente, el libro de Josuttis tiene un capítulo sobre la implementación de sus propios iteradores de STL.
Escribir iteradores personalizados en C ++ puede ser muy detallado y complejo de entender.
Como no pude encontrar una forma mínima de escribir un iterador personalizado, escribí este encabezado de plantilla que podría ser útil. Por ejemplo, para hacer iterable la clase Piece
:
#include <iostream>
#include <vector>
#include "iterator_tpl.h"
struct Point {
int x;
int y;
Point() {}
Point(int x, int y) : x(x), y(y) {}
Point operator+(Point other) const {
other.x += x;
other.y += y;
return other;
}
};
struct Shape {
std::vector<Point> vec;
};
struct Piece {
Shape& shape;
Point offset;
Piece(Shape& shape, int x, int y) : shape(shape), offset(x,y) {}
struct it_state {
int pos;
inline void next(const Piece* ref) { ++pos; }
inline void begin(const Piece* ref) { pos = 0; }
inline void end(const Piece* ref) { pos = ref->shape.vec.size(); }
inline Point get(Piece* ref) { return ref->offset + ref->shape.vec[pos]; }
inline bool cmp(const it_state& s) const { return pos != s.pos; }
};
SETUP_ITERATORS(Piece, Point, it_state);
};
Entonces usted podría usarlo como un Contenedor STL normal:
int main() {
Shape shape;
shape.vec.emplace_back(1,2);
shape.vec.emplace_back(2,3);
shape.vec.emplace_back(3,4);
Piece piece(shape, 1, 1);
for (Point p : piece) {
std::cout << p.x << " " << p.y << std::endl;
// Output:
// 2 3
// 3 4
// 4 5
}
return 0;
}
También permite agregar otros tipos de iteradores como const_iterator
o reverse_const_iterator
.
Espero que ayude.
La solución a su problema no es la creación de sus propios iteradores, sino el uso de contenedores e iteradores existentes de STL. Almacene los puntos en cada forma en un contenedor como vector.
class Shape {
private:
vector <Point> points;
Lo que hagas a partir de entonces depende de tu diseño. El mejor enfoque es repetir los puntos en los métodos dentro de Shape.
for (vector <Point>::iterator i = points.begin(); i != points.end(); ++i)
/* ... */
Si necesita acceder a puntos fuera de Shape (esto podría ser una marca de un diseño deficiente) puede crear en Shape métodos que devolverán las funciones de acceso del iterador para los puntos (en ese caso, también cree un typedef público para el contenedor de puntos). Mire la respuesta de Konrad Rudolph para detalles de este enfoque.
Puedes leer este artículo ddj
Básicamente, herede de std :: iterator para hacer la mayor parte del trabajo por usted.