2009-10-20 64 views
11

我有一個類,我想公開一個結構體列表(它只包含一些整數)。 我不希望外界修改這些數據,只是遍歷並閱讀他們 例子:讓我的C++類通過BOOST_FOREACH迭代

struct TestData 
{ 
    int x; 
    int y; 
    // other data as well 
} 

class IterableTest 
{ 
    public: 
    // expose TestData here 
}; 

現在在我的代碼,我想用我的階級是這樣的:

IterableTest test; 
BOOST_FOREACH(const TestData& data, test.data()) 
{ 
    // do something with data 
} 

我已經閱讀了關於成員空間的這篇文章http://accu.org/index.php/journals/1527。 但是,我不想(或不能)將所有TestData保存在內部向量中或其他東西。 這是因爲類本身並不擁有存儲空間,即實際上沒有可以被類直接訪問的底層容器。不過,該類本身可以查詢外部組件以獲取下一個,前一個或第i個元素。

所以基本上我希望我的班表現得好像它有一個集合,但事實上它沒有一個集合。 任何想法?

+4

你不需要提供返回合​​適迭代器的begin/end函數嗎? – jalf 2009-10-20 22:34:42

+0

是的,但我沒有一個底層容器可以提供給我這些迭代器 – newgre 2009-10-20 22:37:01

+0

所以你自己寫。 :) Boost.Iterator庫應該讓你啓動並運行相當快。 – jalf 2009-10-20 22:37:56

回答

5

這聽起來像你必須編寫自己的迭代器。

Boost.Iterator庫有許多有用的模板。我幾次使用過他們的Iterator Facade基類,並且使用它定義自己的迭代器很好,很容易。

但即使沒有它,迭代器也不是火箭科學。他們只需要公開正確的運算符和typedef。在你的情況下,它們只是在他們增加時要調用的查詢函數週圍的包裝器。

一旦您定義了一個迭代器類,您只需將begin()end()成員函數添加到您的類中。

這聽起來像基本的想法將不得不調整你的查詢函數,當​​迭代器增加,以獲得下一個值。 然後解引用應返回從最後一個查詢調用中檢索的值。

這可能有助於查看標準庫stream_iterator的某些語義,因爲它們還必須解決一些魚腥味「我們沒有真正的容器,而且我們也不能創建迭代器指向任何地方,除了目前的河流位置「問題。

例如,假設你需要調用一個query()函數,當你到達序列末尾時返回NULL,創建一個「end-iterator」將會非常棘手。但是,真正的需要的是定義相等性,以便「如果迭代器都將NULL存儲爲緩存值,則它們是相等的」。所以用NULL初始化「結束」迭代器。

它可能有助於查找輸入迭代器所需的語義,或者如果您正在閱讀Boost.Iterator的文檔,專門針對單遍迭代器。您可能無法創建多通道迭代器。因此,請仔細查看單通迭代器需要的行爲,並堅持這一點。

+0

因爲我是個好人:Input Iterator概念>> http://www.sgi.com/tech/stl/InputIterator.html – 2009-10-21 09:20:52

0

如果您的收集類型提供標準容器界面,則不需要執行任何操作使BOOST_FOREACH適用於您的類型。換句話說,如果您的類型具有iteratorconst_iterator嵌套typedefs,並且begin()end()成員函數,BOOST_FOREACH已知道如何迭代您的類型。不需要採取進一步行動。

http://boost-sandbox.sourceforge.net/libs/foreach/doc/html/boost_foreach/extending_boost_foreach.html

+0

我知道這件事,但我從哪裏得到這些迭代器?沒有可以使用迭代器的底層容器 – newgre 2009-10-20 22:39:21

0

從升壓的for_each文檔頁面:

在序列BOOST_FOREACH迭代。但是,什麼樣的資格作爲一個序列呢?由於BOOST_FOREACH構建在Boost.Range之上,因此它自動支持Boost.Range認爲是序列的那些類型。具體而言,BOOST_FOREACH適用於滿足單通範圍概念的類型。例如,我們可以使用BOOST_FOREACH: