Tworzenie własnych iteratorów

Próbuję nauczyć się C++, więc wybacz mi, jeśli to pytanie pokazuje brak podstawowej wiedzy, widzisz, faktem jest, że nie mam podstawowej wiedzy.

Potrzebuję pomocy, jak stworzyć iterator dla stworzonej przeze mnie klasy.

Mam klasę "Shape", która ma pojemnik punktów. Mam klasę "Piece", która odwołuje się do kształtu i określa pozycję dla kształtu. Element nie ma kształtu, tylko nawiązuje do kształtu.

I want it to seem like Element jest zbiorem punktów, które są takie same jak te o kształcie, do którego się odnosi, ale z dodanym przesunięciem pozycji elementu.

Chcę być w stanie iterować przez punkty kawałka tak, jakby kawałek był samym kontenerem. Trochę poczytałem i nie znalazłem nic, co mi pomogło. Byłbym bardzo wdzięczny za wszelkie wskazówki.

 136
Author: Lightness Races in Orbit, 2008-09-29

6 answers

Powinieneś użyć Boost.Iteratory. Zawiera szereg szablonów i koncepcji do implementacji nowych iteratorów i adapterów do istniejących iteratorów. Napisałem artykuł na ten właśnie temat; jest w magazynie ACCU Z grudnia 2008 roku. Omawia (IMO) eleganckie rozwiązanie dokładnie Twojego problemu: odsłanianie kolekcji prętów z obiektu, za pomocą Boost.Iteratory.

Jeśli chcesz używać tylko stl, Josuttis book zawiera rozdział na temat implementacji własnego STL Iteratory.

 41
Author: Roel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-08 06:56:25

/EDIT: widzę, że własny iterator jest tutaj rzeczywiście potrzebny(źle odczytałem pytanie jako pierwszy). Mimo to pozwalam poniższemu kodowi stać, ponieważ może być przydatny w podobnych okolicznościach.


Czy własny iterator jest tu potrzebny? Być może wystarczy przesłać wszystkie wymagane definicje do pojemnika zawierającego rzeczywiste punkty:
// 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(); }
}

Zakłada się, że używasz vector wewnętrznie, ale Typ można łatwo dostosować.

 60
Author: Konrad Rudolph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-29 13:22:28

Tutaj Projektowanie niestandardowego kontenera podobnego do stl jest doskonałym artykułem, który wyjaśnia niektóre z podstawowych pojęć, w jaki sposób Klasa kontenera podobnego do stl może być zaprojektowana wraz z klasą iteratora dla niej. Reverse iterator (trochę trudniejszy) jest jednak pozostawiony jako ćwiczenie: -)

HTH,

 20
Author: Abhay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-08 14:37:05

Możesz przeczytać ten ddj Artykuł

Zasadniczo, Dziedzicz z STD:: iterator, aby uzyskać większość pracy wykonanej za Ciebie.

 14
Author: gbjbaanb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-28 11:43:35

Rozwiązaniem problemu nie jest tworzenie własnych iteratorów, ale wykorzystanie istniejących kontenerów STL i iteratorów. Przechowuj punkty w każdym kształcie w pojemniku takim jak wektor.

class Shape {
    private:
    vector <Point> points;
To, co zrobisz, zależy od Twojego projektu. Najlepszym podejściem jest iteracja punktów w metodach wewnątrz kształtu.
for (vector <Point>::iterator i = points.begin(); i != points.end(); ++i)
    /* ... */

Jeśli potrzebujesz dostępu do punktów poza kształtem (może to być znak wadliwego projektu), możesz utworzyć metody w kształcie, które zwrócą iterator udostępnia funkcje dla punktów (w tym przypadku tworzy również publiczny typedef dla kontenera punktów). Szczegóły tego podejścia można znaleźć w odpowiedzi Konrada Rudolfa.

 1
Author: Diomidis Spinellis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-29 13:06:05

Pisanie niestandardowych iteratorów w C++ może być dość zwięzłe i złożone do zrozumienia.

Ponieważ nie mogłem znaleźć minimalnego sposobu na napisanie niestandardowego iteratora, napisałem ten nagłówek szablonu , który może pomóc. Na przykład, aby Klasa Piece Była iterowalna:

#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);
};

Wtedy będziesz mógł używać go jako zwykłego kontenera STL:

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;
}

Pozwala również na dodawanie innych typów iteratorów, takich jak const_iterator Czy reverse_const_iterator.

Mam nadzieję, że to pomoże.
 1
Author: VinGarcia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-02 22:56:47