2010-08-18 89 views
3

我有一個鏈表結構:使用boost :: iterator_facade <>

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

這是現有的API的一部分,我不能改變它。

我想添加迭代器支持。該庫似乎是理想的目的。

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:

我已經試過修改提領型:

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

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

,但我得到的原始錯誤:

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

Re:編輯。你仍然在說'value_type'將會是'SomeLinkedList'。你可能根本不需要最後一個參數,因爲默認值應該可以工作。另外,你是否改變了'dereference'成員的返回類型? - 但是,因爲你的代碼庫看起來並不是特別的stdlib風格,所以編寫你自己的foreach到這個特定的鏈表是不是更簡單(因爲我懷疑其他的stdlib算法是否能夠很好地工作一個奇怪的迭代器無論如何沒有嚴重的額外工作)? – UncleBens 2010-08-18 17:30:19

+0

@UncleBens - 見編輯2.另外,我不認爲這將是很多額外的工作。只是重載比較運算符或二元謂詞。 – PaulH 2010-08-18 17:40:12

+1

似乎你可能需要'const SomeLinkedList *'這兩個'value_type'和'reference'參數。在引用指針時可能會有些不可思議。 - 關於額外的工作:適合你。對我來說,使用C風格的字符串與stdlib是太多的工作,因爲它從來沒有被設計來支持那些開箱即用的。 – UncleBens 2010-08-18 17:49:03

回答

1

當你的迭代器廢棄時,它會返回一個const SomeLinkedList&但您的DoSomething功能期望const SomeLinkedList*。當解除引用或改變DoSomething函數時,改變迭代器以某種方式返回指針。


編輯迴應進一步討論:

我還沒有實際使用的boost :: iterator_facade自己,但看着額外的代碼你張貼看起來你可能沒有改變所有必要的零件與此同時。

你有沒有真的試圖

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

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

在一起嗎?

或者,如果還是不行,那麼怎麼樣:

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

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

另外,作爲davka在評論建議,怎麼樣通過使周圍的DoSomething的包裝解決指針VS參考問題?如:

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

事實上,你很可能連保持包裝相同的名稱,因爲它封裝了功能,只是讓重載規則照顧,當指針或引用版本被調用的。

+0

'DoSomething'也是固定的,不能更改。我想知道如何修改'boost :: iterator_facade <>'對象來工作。理想情況下,它的行爲就像'std :: vector :: const_iterator'(但只是前向遍歷) – PaulH 2010-08-18 17:16:18

+0

@PaulH:你至少試圖改變迭代器的引用(也不要忘記模板參數)?國際海事組織,這個東西看起來不像普通的stdlib迭代器,除非解除引用DWORD成員。例如,如果我想使用'std :: find'來查找具有特定值的節點,爲什麼這不起作用?爲什麼迭代細節(它是入侵鏈接列表中的一個節點)阻礙了它? – UncleBens 2010-08-18 17:19:20

+0

@UncleBens - 這裏的想法是我**可以使用像'std :: find'這樣的算法。是的,我已經嘗試了幾件事來改變迭代器解引用的內容。到目前爲止,我在boost :: iterator_facade <>'的框架內一直沒有做到這一點。也就是說,基本上,我在這個問題上提出的問題。 – PaulH 2010-08-18 17:30:01

1

我一直在嘗試理解boost :: iterator_facade。尋找一個簡單的例子,我發現這個(舊)問題和單一的,被接受的答案。我想我會張貼我需要的代碼來讓這個例子在這裏工作,因爲現有的問題和答案從來沒有真正解決這個問題。

在第一種情況下請注意,for_each()的第二個參數是結束迭代器。我發現原始問題代碼中使用的NULL迭代器(不確定這是否是正確的術語)效果不錯,但前提是您完成了.equal()的不完整定義,如下所示;

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

除此之外簡單地從PTR改變DoSomething的()的參數的定義引用,作爲公認的答案提到的,關鍵是得到這個編譯和運行。我已經在下面放了一些原始測試代碼來說明。

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; 
} 
相關問題