2010-05-27 3 views
1

std::list<Foo>을 포함하는 클래스가 있고 공용 메서드 begin()end()이 해당 목록의 반복자를 반환하는 경우 반복기를 사용하지 않고 std::list<Foo*>에 반환하는 추가 메서드를 어떻게 구현할 수 있습니까?Foo 벡터에 반복자를 사용할 수 있습니까?

필자는 포인터의 병렬 컨테이너를 유지 관리하지 않으려합니다.

편집 :

은 내가 향상시키고 자하는 큰 코드베이스가 있습니다. 이 객체의 자식을 반환하는 메소드가 기본 클래스와 나무 같은 데이터 구조를 가지고

template <class T> 
class FooCollection: public FooBase 
{ 
public: 
    typedef typename std::list<T> ContainerType; 
    typedef typename ContainerType::iterator iterator; 
    typedef typename ContainerType::const_iterator const_iterator; 
private: 
    ContainerType _items; 
public: 
    // ... 
    const_iterator begin() const { return itemsM.begin(); }; 
    const_iterator end() const { return itemsM.end(); }; 
    iterator begin() { return itemsM.begin(); }; 
    iterator end() { return itemsM.end(); }; 

    virtual bool getChildren(std::vector<FooBase *>& children) 
    { 
     for (iterator it = itemsM.begin(); it != itemsM.end(); ++it) 
      children.push_back(&(*it)); 
     return (itemsM.size() != 0); 
    }; 
    // ... 
}; 

: 자식 개체의 컬렉션을 구현하는 템플릿 클래스가 있습니다

class FooBase 
{ 
    // ... 
    virtual bool getChildren(std::vector<FooBase *>& children); 
    virtual size_t getChildrenCount() const { return 0; }; 
    // ... 
} 

이 코드는 클래스가 다른 클래스 인 FooCollection<>이 제공하는 반복기와 트리를 반복 할 때 FooBase::getChildren()을 사용합니다. FooBase::getChildren()이 반복자로 대체 될 수 있다고 생각했지만 어쩌면 틀렸어?

+1

사용에 대한 그것'표준 : : 목록 '또는'표준 : : 벡터 '얼마나. 당신의 제목은 한 가지, 질문은 다른 것을 말합니다. –

+0

@ 에반 : 고마워, 내가 생각하기에 침대 시간. 컨테이너의 유형은 실제로 중요하지 않습니다. 동일한 컨테이너에 대해 두 가지 유형의 반복자를 모두 가질 수 있습니까? – mghie

+1

왜 표준이 필요합니까 :: list :: iterator? can not 당신은 std :: list :: iterator를 캡슐화하고, dereferenced 될 때 Foo의 인스턴스의 주소를 제공하는 간단한 iterator를 작성할 수 없습니까? –

답변

1

Foo 요소에 대한 포인터 컬렉션을 얻으려면 std::list<Foo>을 만들 수 있지만 신뢰할 수는 없습니다. 문제는 목록에 Foo 항목 (사본을 만들었 음)을 소유하고 승인없이 해당 항목의 위치를 ​​변경할 수 있다는 것입니다. 따라서 목록의 세 번째 요소에 대한 포인터가 있으면 목록에서 요소를 이동할 수 있으며 포인터는 무의미하게됩니다 (사용자 모르게).

Foo 항목을 동적으로 할당하고 스마트 포인터를 다른 목록에 저장하는 것이 더 좋은 해결책입니다. 이렇게하면 항목을 다른 키로 정렬 할 수 있습니다. 예를 들어 list1의 첫 번째 필드는 Foo, 다른 필드는 Foo의 세 번째 필드로 정렬 할 수 있습니다.

기본 조작은 아무도 원하지 않는 스마트 포인터의 값으로 정렬하는 것이므로 사용자 지정 정렬 펑크이 필요합니다.

+0

목록은 모든 작업에서 요소의 메모리 위치를 이동하는 것이 허용되지 않습니다 (물론 제거하는 동안 제외). 표준은 iterators와 * reference 또는 pointer * into list 요소가 참조 된 요소 요소의 제거를 암시하지 않는 모든 연산에서 유효한 상태를 유지하도록 요구한다. –

2

std::list<Foo>::iterator의 역 참조 연산자 오버로드는 해당 Foo 개체에 대한 참조를 반환합니다. 따라서 Foo 개체의 주소를 std::list<Foo>::iterator 개체 it으로 지정하려면 &*it을 사용할 수 있습니다. 형식은 Foo*입니다.

포인터에 대해 증분이 가능한 반복자가 필요한 경우 std::list<Foo>::iterator 멤버 (예 : it)를 저장하고 반복 참조시 &*it을 반환하는 반복기 클래스를 작성할 수 있습니다. 이러한 반복자 클래스는 &*it이 r 값인 이유 때문에 const 반복기 개념 만 만족할 수 있습니다.

2

이 구조체가 도움이 될 것입니다.

for(PointerInstead i = l.begin(); i != l.end(); i++) { 
    cout << i->first << '\t' << i->second << endl; 
    printf("%p\n", (*i)); 
    } 

그런 다음 당신이 뭔가를 반환하는 pointerBegin() 메소드를 작성할 수 있습니다 여기에

struct PointerInstead : public list<Foo>::iterator { 
    PointerInstead(const list<Foo>::iterator &x) : list<Foo>::iterator(x) { } 
    Foo * operator *() const { 
    Foo &f = *(*((list<Foo>::iterator *) (this))); 
    return &f; 
    } 
}; 

는 그 사용의 예 : 그것은 역 참조가 대신 참조 포인터를 반환하도록 반복자를 수정 PointerInstead (this-> begin()).

+0

@Daniel Trebbien : 나는 몇 분 후에 비슷한 대답으로 나를 이길 것으로 나타났습니다. 나는 아직 보지 못했다. –

+1

꽤 좋지만 표준 반복기에서 파생되는 것은 안전하지 않습니다. 예를 들어'++ '연산자는 자유 함수'T & operator ++ (std :: list :: iterator &)'로 구현 될 수있다. T & std :: list :: iterator :: operator ++() '. – Potatoswatter

+0

@Potatoswatter : 자유 기능의 동일한 문제가 @Maciej Hehl의 대답에도 적용된다는 의미입니까? 무료 기능을 포함하여 모든면에서 다른 유형과 비슷하게 동작하지만 작게 수정 된 유형을 생성하는 최소한의 방법이 있습니까? 전환 연산자는 어떻습니까? 전환 운영자가 무료 기능을 사용할 수 있습니까? ' :: iterator' 목록에서'private' 상속을하고 연산자 목록 :: iterator &()'변환기를 포함할까요? –

3

같은 아래에 간단한 반복자 클래스를 작성하고 그것을

class myIterator : std::iterator<std::list<Foo>::iterator::iterator_category 
           , Foo*, std::list<Foo>::iterator::distance_type 
           , Foo**, Foo*&> 
{ 
public: 
    myIterator(const std::list<Foo>::iterator& lIt) : it(lIt) {} 
    myIterator(const myIterator& myIt) : it(myIt.it) {} 
    myIterator& operator++() {++it;return *this;} 
    myIterator operator++(int) 
    { 
     myIterator copy(*this); 
     ++it; 
     return copy; 
    } 
    myIterator& operator--() {--it;return *this;} 
    myIterator operator--(int) 
    { 
     myIterator copy(*this); 
     --it; 
     return copy; 
    } 
    bool operator==(const myIterator& rhs) {return it==rhs.it;} 
    bool operator!=(const myIterator& rhs) {return it!=rhs.it;} 
    Foo* operator*() {return &(*it);} 
private: 
    std::list<Foo>::iterator it; 
}; 
관련 문제