2011-11-01 2 views
2

boost :: iterator_facade를 사용하는 방법을 이해하기위한 시도의 일환으로이 질문에 대한 몇 가지 코드를 선택하고 Using boost::iterator_facade<>을 실행했습니다. 내 완성 된 코드는 다음과 같습니다. 내 질문에 대한 std :: for_each 및 std :: find 알고리즘 모두에서 최종 매개 변수가 관련이 있습니다. 원래 질문에서 찾은 관용구를 그대로 유지했습니다. 기본적으로 그것은 end 매개 변수에 대해 일종의 NULL 반복자를 사용합니다. 그것은 equal() 멤버를 그림과 같은 방식으로 정의하는 한 작동합니다.boost :: iterator_facade를 사용하여 레거시 연결된 목록에 액세스하는 방법

제 질문은,이 관용구 (NULL 이터레이터 (?), 아마 잘 모르는이 유형의 이터레이터에 대한 실질적인 용어입니다), 잘 알려진 우수 사례입니까? 그렇지 않은 경우 대체 방법을 권장 할 수 있습니까?

// Element of linked list (legacy code, can't be changed) 
struct SomeLinkedList 
{ 
    const char* bar; 
    int lots_of_interesting_stuff_in_here; 
    long foo; 
    SomeLinkedList* pNext; 

    // actually I cheated and added this to get std::find working 
    bool operator ==(SomeLinkedList const& other) const { return foo == other.foo; } 
}; 

class SomeIterator 
    : public boost::iterator_facade< SomeIterator, 
            const SomeLinkedList, 
            boost::forward_traversal_tag > 
{ 
public: 
    SomeIterator() : node_(NULL) {}; // used to create end iterators in examples 
    explicit SomeIterator(const SomeLinkedList* p) : node_(p) {}; 

private: 
    friend class boost::iterator_core_access; 
    void increment() { node_ = node_->pNext; }; 
    bool equal(SomeIterator const& other) const { return node_ == other.node_; } 
    SomeLinkedList const& dereference() const { return *node_; }; 
    SomeLinkedList const* node_; 
}; // class SomeIterator 

void DoSomething(const SomeLinkedList& node) 
{ 
    std::cout << "DoSomething " << node.foo << "\n"; 
} 

void main() 
{ 
    // Ugly but effective way to create a fake linked list for experiments 
    SomeLinkedList temp[3]; 
    memset(temp,0,sizeof(temp)); 
    temp[0].pNext = &temp[1]; 
    temp[1].pNext = &temp[2]; 
    temp[2].pNext = 0; 
    temp[0].foo = 0; 
    temp[1].foo = 1; 
    temp[2].foo = 2; 
    temp[2].bar = "number 2"; 
    SomeLinkedList* my_list = &temp[0]; 

    // DoSomething() for each element in list 
    std::for_each(SomeIterator(my_list), /*end*/ SomeIterator(), DoSomething); 

    // Find one element in the list 
    SomeLinkedList obj; 
    obj.foo = 2; 
    SomeIterator it = std::find(SomeIterator(my_list), /*end*/ SomeIterator(), obj); 
    std::cout << "found " << it->bar << "\n"; 
    return 0; 
} 
+0

나는 코드를 검사하지는 않았지만, NULL 반복자는 유효한 요소를 가리 키지 않기 때문에'end' 반복자에 대해 매우 좋은 선택 인 것처럼 보입니다. –

+0

이것은 매우 일반적이며 'sentinal iterator'로 알려져 있습니다. – ildjarn

+0

'SomeLinkedList'에서'operator =='를 리뷰 할 수 있습니다 ... 두리스트를 비교하지 않고리스트의 head 요소 만 비교합니다. 주석에서'std :: find_if (it1, it2, functor)'를 사용하고 싶다면'std :: find (it1, it2, value)'함수를 추가 한 것 같습니다. 'functor'는 당신이 찾고있는 값을 저장하는 함수 객체이고'operator()'에있는 수신 노드의 값을 그 기대 값과 비교합니다 ... –

답변

1

일반적인 접근법이므로 변경할 필요가 없습니다. iterator 헤더를 보면 비슷한 접근 방식을 취하는 std::istream_iterator<>을 찾을 수 있습니다. end 반복자는 입력 스트림에 관계없이 반복을 완료 한 반복자와 true을 비교하는 특수 반복자 값 (istream_iterator<T>())입니다. 그것을 초기화했다.

관련 문제