2011-11-01 69 views
2

作爲嘗試瞭解如何使用boost :: iterator_facade的一部分,我從這個問題Using boost::iterator_facade<>中挑選了一些代碼並使其運行。我完成的代碼如下。我的問題涉及std :: for_each和std :: find算法中的結束參數。我保留了原始問題的原始代碼中找到的成語。基本上它使用一種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

我還沒有檢查過你的代碼,但是對於'end'迭代器來說,NULL迭代器看起來是一個非常好的選擇,因爲它沒有指向一個有效的元素。 –

+0

這是非常常見的,被稱爲「最終迭代器」。 – ildjarn

+0

您可能想要在'SomeLinkedList'中查看您的'operator =='...它不會比較兩個列表,而只是列表的頭元素。從註釋看來,你添加它來獲得'std :: find(it1,it2,value)'工作,如果是這種情況,你可能需要使用'std :: find_if(it1,it2,functor)其中'functor'是一個函數對象,用於存儲您正在搜索的值,並將'operator()'中接收到的節點中的值與該期望值進行比較... –

回答

1

這是一種常見的方法,不需要改變它。例如,如果您查看iterator標題,則會發現std::istream_iterator<>,例如,採用類似的方法,end迭代器是一個特殊的迭代器值(istream_iterator<T>()),它將true與已完成迭代的任何迭代器進行比較,而不管輸入流從它被初始化。