나만의 반복자 만들기


141

C ++을 배우려고 노력 중이므로이 질문에 기본 지식이 부족하다는 사실이 있으면 용서하십시오. 사실 기본 지식이 부족하다는 것을 알 수 있습니다.

내가 만든 클래스의 반복자를 만드는 방법에 대한 도움이 필요합니다.

Points 컨테이너가있는 'Shape'클래스가 있습니다. Shape를 참조하고 Shape의 위치를 ​​정의하는 'Piece'클래스가 있습니다. Piece에는 Shape가 없으며 단지 Shape를 참조합니다.

Piece가 참조하는 Shape의 컨테이너와 동일하지만 Piece의 위치 오프셋이 추가 된 Points의 컨테이너처럼 보입니다.

마치 Piece가 컨테이너 자체 인 것처럼 Piece의 Point를 반복 할 수 있기를 원합니다. 나는 약간의 독서를하고 나에게 도움이되는 것을 찾지 못했습니다. 나는 어떤 포인터에 대해서도 매우 감사 할 것입니다.


6
샘플 코드를 게시하면 평범한 영어 텍스트보다 더 잘하는 일을 설명하는 데 도움이됩니다.
Greg Rogers

3
커스텀 이터레이터를 만드는 것은 적어도 중간의 기본이 아닙니다 .
ldog

답변:


41

Boost.Iterators를 사용해야합니다. 여기에는 기존 반복기에 대한 새 반복기와 어댑터를 구현하기위한 많은 템플릿과 개념이 포함되어 있습니다. 나는이 주제에 관한 기사를 썼다 . 2008 년 12 월 ACCU 잡지에 있습니다. Boost.Iterators를 사용하여 객체에서 멤버 컬렉션을 노출시키는 정확한 문제에 대한 (IMO) 우아한 솔루션에 대해 설명합니다.

stl 만 사용하려면 Josuttis 책 에는 자체 STL 반복기 구현에 대한 장이 있습니다.


3
단지 사소한 말 :이 책은 STL이 아닌 C ++ 표준 라이브러리에 대해 이야기합니다. 이것들은 다르지만 많이 혼란스러워합니다 (저도 유죄였습니다)
CppChris

62

/ 편집 : 여기에 실제로 자체 반복자가 필요하다는 것을 알았습니다 (먼저 질문을 잘못 읽었습니다). 여전히 비슷한 상황에서 유용 할 수 있기 때문에 아래 코드를 그대로 두었습니다.


여기에 자체 반복자가 실제로 필요합니까? 아마도 필요한 모든 정의를 실제 포인트를 보유한 컨테이너에 전달하는 것으로 충분할 것입니다.

// 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(); }
}

이것은 vector내부적으로 사용한다고 가정 하지만 유형을 쉽게 조정할 수 있습니다.


아마도 그는 자신의 클래스에 대해 STL 알고리즘이나 기능적 특징을 사용하고 싶을 것이다.
gbjbaanb

2
원래 질문은 실제로 조각 컨테이너의 반복자가 값을 반환 할 때 값을 수정해야한다고 말합니다. 그것은 아마도 원래의 것을 상속 받거나 그렇지 않으면 얻어야하지만 별도의 반복자가 필요합니다.
workmad3

@ gbjbaanb : 내 코드의 장점은 STL 알고리즘에서 사용할 있다는 것 입니다.
Konrad Rudolph

1
몇 년 후 이것은 여전히 ​​구글의 최고 결과 중 하나입니다 ... 이제 다음과 같이함으로써 이것을 일반화 할 수 있습니다 :auto begin() -> decltype(m_shape.container.begin()) { return m_shape.container.begin(); }
user2962533


15

기사를 읽을 수 있습니다

기본적으로 std :: iterator에서 상속하여 대부분의 작업을 수행합니다.


2
참고 std::iterator됨으로 표시 되지 않는 C ++ 17에서.
mandrake 10

2

C ++로 커스텀 반복자를 작성하는 것은 이해하기에 장황하고 복잡 할 수 있습니다.

사용자 정의 반복자를 작성하는 최소한의 방법을 찾을 수 없으므로 도움이 될 수있는 이 템플릿 헤더 를 작성 했습니다 . 예를 들어 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);
};

그런 다음 일반 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;
}

또한 같은 반복자 다른 종류의 추가 할 수 있습니다 const_iterator또는 reverse_const_iterator.

도움이 되길 바랍니다.


1

문제에 대한 해결책은 자체 반복자를 작성하는 것이 아니라 기존 STL 컨테이너 및 반복자를 사용하는 것입니다. 벡터와 같은 컨테이너에 각 모양의 점을 저장하십시오.

class Shape {
    private:
    vector <Point> points;

그때부터하는 일은 디자인에 달려 있습니다. 가장 좋은 방법은 Shape 내부의 메서드에서 점을 반복하는 것입니다.

for (vector <Point>::iterator i = points.begin(); i != points.end(); ++i)
    /* ... */

셰이프 외부의 포인트에 액세스해야하는 경우 (이것은 결함있는 디자인의 표시 일 수 있음) 셰이프 메서드에서 포인트에 대한 반복자 액세스 함수를 반환하는 포인트 메서드를 만들 수 있습니다 (이 경우 포인트 컨테이너에 대한 public typedef도 생성). 이 접근 방식에 대한 자세한 내용은 Konrad Rudolph의 답변을 참조하십시오.


3
그는 여전히 요청을 해당 조각에있는 모양으로 전달하는 자체 반복자를 만들어야합니다. 커스텀 이터레이터는 여기서 훌륭한 도구이며 매우 우아합니다.
Roel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.