2011-09-26 48 views
57

我正在寫一個容器的迭代器,用於替代STL容器。目前,STL容器正在許多地方使用,例如:c++11 foreach syntax,例如:for(auto &x: C)。我們需要更新使用該包裝的STL容器的自定義類的代碼:C++ 11 foreach語法和自定義迭代器

template< typename Type> 
class SomeSortedContainer{ 
    std::vector<typename Type> m_data; //we wish to iterate over this 
    //container implementation code 
};  
class SomeSortedContainerIterator{ 
    //iterator code 
}; 

如何獲得自動使用正確的迭代器自定義容器,這樣的代碼可以在下面被稱爲方式?:

SomeSortedContainer C; 
for(auto &x : C){ 
    //do something with x... 
} 

通常需要什麼來確保auto爲類使用正確的迭代器?

+0

如果您使用Visual Studio,則可以將鼠標懸停在變量的名稱上以查看其類型。 IIRC,它顯示了實際的類型,而不是「auto」。 –

回答

50

你有兩個選擇:

命名 beginend
  • 你提供的成員函數可以被稱爲像C.begin()C.end();
  • 否則,您提供的名爲beginend可以使用參數相關的查找找到,或者在命名空間std免費功能,並且可以被稱爲像begin(C)end(C)
+2

請參閱Stroustrup的[C++ 11 FAQ](http://www.stroustrup.com/C++11FAQ.html)以獲取[「Range-for」語句]的詳細說明(http://www.stroustrup .com/C++ 11FAQ.html#for)(包括成員/函數優先級)。 – rluba

50

爲了能夠使用基於範圍的,您的班級應提供const_iterator begin() constconst_iterator end() const成員。你也可以重載全球begin函數,但是在我看來,有一個成員函數更好。 iterator begin()const_iterator cbegin() const也是推薦的,但不是必需的。如果你只是想遍歷一個內部的容器,這是非常簡單:

template< typename Type> 
class SomeSortedContainer{ 

    std::vector<Type> m_data; //we wish to iterate over this 
    //container implementation code 
public: 
    typedef typename std::vector<Type>::iterator iterator; 
    typedef typename std::vector<Type>::const_iterator const_iterator; 

    iterator begin() {return m_data.begin();} 
    const_iterator begin() const {return m_data.begin();} 
    const_iterator cbegin() const {return m_data.cbegin();} 
    iterator end() {return m_data.end();} 
    const_iterator end() const {return m_data.end();} 
    const_iterator cend() const {return m_data.cend();} 
};  

如果你想遍歷任何定製雖然,你可能必須設計自己的迭代器作爲容器內的類。

class const_iterator : public std::iterator<random_access_iterator_tag, Type>{ 
    typename std::vector<Type>::iterator m_data; 
    const_iterator(typename std::vector<Type>::iterator data) :m_data(data) {} 
public: 
    const_iterator() :m_data() {} 
    const_iterator(const const_iterator& rhs) :m_data(rhs.m_data) {} 
    //const iterator implementation code 
}; 

有關編寫迭代器類的更多詳細信息,請參閱my answer here

2

據我所知SomeSortedContainer只需要提供begin()end()。這些應該返回一個符合標準的前向迭代器,在你的案例SomeSortedContainerIterator中,它實際上會包裝一個std::vector<Type>::iterator。對於標準兼容,我的意思是它必須提供通常的增量和解引用操作符,而且還要提供所有那些value_typereference_type,... typedefs,這些依次由foreach構造使用來確定容器元素的基礎類型。但是你可能只是從std::vector<Type>::iterator轉發他們。

+3

如果你缺少'begin'和'end'成員函數,那麼foreach也可以使用'begin'和'end'非成員函數。 – 2011-09-26 23:26:08

+0

@Mike你是指將容器作爲單一參數的自由函數?很好,我不知道。我猜,這對於擴展現有的容器類很有用。 –

6

正如其他人所指出的,您的容器必須實現begin()end()功能(或有把你作爲參數容器的情況下,全球或std::功能)。

這些函數必須返回相同的類型(通常爲container::iterator,但這只是一個約定)。返回的類型必須實現operator*,operator++operator!=