2010-08-18 4 views
3

나는 연결리스트 구조를 가지고 :사용 부스트 :: iterator_facade <>

struct SomeLinkedList 
{ 
    const char* bar; 
    int lots_of_interesting_stuff_in_here; 
    DWORD foo; 
    SomeLinkedList* pNext; 
}; 

그것은 기존의 API의 일부이며 나는 그것을 변경할 수 없습니다.

이터레이터 지원을 추가하고 싶습니다. boost::iterator_facade<> 라이브러리가 이상적이었습니다.

class SomeIterator 
    : public boost::iterator_facade< SomeIterator, 
            const SomeLinkedList, 
            boost::forward_traversal_tag > 
{ 
public: 
    SomeIterator() : node_(NULL) {}; 

    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 { /*some comparison*/; }; 

    SomeLinkedList const& dereference() const { return *node_; }; 

    SomeLinkedList const* node_; 
}; // class SomeIterator 

목표는 불행하게도 std::for_each

void DoSomething(const SomeLinkedList* node); 

SomeLinkedList* my_list = CreateLinkedList(); 
std::for_each(SomeIterator(my_list), SomeIterator(), DoSomething); 

같은 표준 라이브러리 함수에서 사용할 수있을 것입니다, 나는 값이 아닌 포인터 목록을 통과하려고 없다는 오류를 받고 있어요 .

error C2664: 'void (const SomeLinkedList *)' : cannot convert parameter 1 from 'const SomeLinkedList' to 'const SomeLinkedList *' 

SomeIterator을 올바르게 변경하려면 어떻게해야합니까?

감사합니다, PaulH


편집 : 나는이 시도했다 :

class SomeIterator 
    : public boost::iterator_facade< SomeIterator, 
            SomeLinkedList, 
            boost::forward_traversal_tag, 
            SomeLinkedList* > 
{ 
    // ... 

을하지만 난이 컴파일러 오류가 발생합니다 :

error C2664: 'boost::implicit_cast' : cannot convert parameter 1 from 'SomeLinkedList **' to 'boost::detail::operator_arrow_proxy<T> 

에드 그것은 2 : 당신의 반복자가 역 참조하면

error C2664: 'void (const SomeLinkedList *)' : cannot convert parameter 1 from 'const SomeLinkedList' to 'const SomeLinkedList *' 
+0

Re : 편집 : 당신은 여전히'value_type'이'SomeLinkedList'가 될 것이라고 말하고 있습니다. 마지막 매개 변수는 전혀 필요하지 않습니다. 기본값이이를 위해 작동해야하기 때문입니다. 또한 '역 참조'멤버의 반환 유형을 변경 했습니까? -하지만 여전히 코드베이스가 stdlib 스타일로 보이지 않기 때문에 (다른 어떤 stdlib 알고리즘도 이와 같이 잘 작동하지 않을 것이므로이 특정 링크 된 목록에 대한 자신 만의 foreach를 작성하는 것이 더 간단하지 않겠는가?) 어쨌든 심각한 추가 작업없이 기괴한 반복자)? – UncleBens

+0

@UncleBens - 편집 2 참조. 또한 추가 작업이 많지 않을 것이라고 생각합니다. 비교 연산자 또는 2 진 술어에 과부하 만하십시오. – PaulH

+1

'value_type'과'reference' 매개 변수 모두에'const SomeLinkedList *'가 필요할 것 같습니다. 아마도 포인터에 대한 참조를 취할 때 어떤 이상한 점이있을 것입니다. - 추가 작업에 관하여 : 당신에게 어울립니다. stdlib에서 C 스타일의 문자열을 사용하는 것은 나에게 너무 많은 작업이다. – UncleBens

답변

1

, 그것은 그러나 const SomeLinkedList&을 반환 : 나는 원래 오류,

class SomeIterator 
    : public boost::iterator_facade< SomeIterator, 
            const SomeLinkedList, 
            boost::forward_traversal_tag > 
{ 
    // ... 

    const SomeLinkedList* dereference() const { return node_; }; 

하지만 :

나는 역 참조 유형을 수정하려고했습니다 DoSomething 함수에 const SomeLinkedList*이 필요합니다. 중첩 될 때 포인터를 반환하거나 DoSomething 함수를 변경하도록 반복기를 변경하십시오. 자세한 설명에 응답


편집 :

는 사실 iterator_facade에게 :: 자신을 부스트를 사용하지 않은,하지만 추가적인 코드를 찾고 당신은 당신이 모든 필요한 부분을 을 변경하지 않을 수 있습니다 나타납니다 게시 동시에.

당신은 실제로 함께

const SomeLinkedList* dereference() const { return node_; }; 

class SomeIterator 
    : public boost::iterator_facade< SomeIterator, 
            SomeLinkedList, 
            boost::forward_traversal_tag, 
            SomeLinkedList* > 
{ 

를 시도?다음 방법을 대한

또는 문제가 해결되지 않으면

: davka로

또는
class SomeIterator 
    : public boost::iterator_facade< SomeIterator, 
            SomeLinkedList*, 
            boost::forward_traversal_tag> 
{ 

const SomeLinkedList* dereference() const { return node_; }; 

이 댓글에 제안, 어떻게 해봐요 래퍼를 만들어 참조 문제에 대 포인터 해결에 대한? 예를 들면 :

void DoSomethingWrapper(const SomeLinkedList& node) 
{ 
    DoSomething(&node); 
} 

는 사실, 당신은 아마 그것을 감싸는 함수로 래퍼 동일한 이름을 유지하고 단지 규칙이 포인터 또는 참조 버전이 호출 될 때 알아서 오버로드 할 수 있습니다.

+0

'DoSomething' 또한 고정되어 있으며 변경할 수 없습니다. 'boost :: iterator_facade <>'객체를 수정하는 법을 알고 싶습니다. 이상적으로, 그것은'std :: vector :: const_iterator'와 똑같이 동작 할 것입니다. (그러나 순회 만 가능합니다.) – PaulH

+0

@PaulH : 그래서 iterator가 역 참조하는 것을 변경하려고 시도 했습니까? 템플릿 매개 변수)? IMO,이 것은 DWORD 멤버에 대해 어쨌든 역 참조가되지 않는 한 일반 stdlib 반복자와 많이 달라 보이지 않습니다. 예를 들어, 특정 값을 가진 노드를 찾기 위해'std :: find'를 사용하고 싶다면 왜 이것이 작동하지 않아야합니까? 반복되는 세부 사항 (방해받는 링크 된 목록의 노드)이 방해가되는 이유는 무엇입니까? – UncleBens

+0

@UncleBens - 아이디어는 ** std :: find와 같은 알고리즘을 ** 사용할 수 있다는 것입니다. 예, iterator가 역 참조하는 것을 변경하기 위해 몇 가지 시도를했습니다. 아직, 나는 boost :: iterator_facade <>'프레임 워크 내에서 그렇게하지 못했습니다. 그것은 본질적으로 내가이 질문에서 무엇을 요구하고 있는지입니다. – PaulH

1

나는 boost :: iterator_facade를 이해하려고 노력 해왔다. 간단한 예를 찾고 나는이 (오래된) 질문과 단 하나의 대답을 발견했다. 나는 기존의 질의 응답으로 결코 그 문제를 진정시키지 않으므로이 예제를 얻기 위해 필요한 코드를 게시 할 것이라고 생각했습니다.

첫 번째 인스턴스에서 for_each()의 두 번째 매개 변수는 끝 반복자입니다. 나는 원래의 질문 코드에서 사용되는 NULL 이터레이터 (올바른 용어인지 확실하지 않음)가 잘 작동한다는 것을 발견했다. 그러나 다음과 같이 .equal()의 불완전한 정의를 마무리해야한다.

bool equal(SomeIterator const& other) const { return node_ == other.node_; } 

별도로 허용 대답에 언급 한 바와 같이 그 단순히 참고로 PTR에서 해봐요()의 매개 변수의 정의를 변경에서 컴파일하고 실행하려면이지고의 핵심입니다. 아래에 몇 가지 기본 테스트 코드를 설명했습니다.

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

int main() 
{ 
    SomeLinkedList temp[5]; 
    memset(temp,0,sizeof(temp)); 
    temp[0].pNext = &temp[1]; 
    temp[1].pNext = &temp[2]; 
    temp[2].pNext = &temp[3]; 
    temp[3].pNext = &temp[4]; 
    temp[4].pNext = 0; 
    temp[0].foo = 0; 
    temp[1].foo = 1; 
    temp[2].foo = 2; 
    temp[3].foo = 3; 
    temp[4].foo = 4; 
    SomeLinkedList* my_list = &temp[0]; 
    std::for_each(SomeIterator(my_list), SomeIterator(), DoSomething); 
    return 0; 
} 
관련 문제