c ++ 11 foreach语法和自定义迭代器
我正在写一个容器的迭代器,用于代替STL容器。 目前,在许多地方使用c ++ 11 foreach语法来使用STL容器,例如: for(auto &x: C)
。 我们需要更新代码以使用包装STL容器的自定义类:
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为类使用正确的迭代器需要什么?
你有两个select:
- 您提供了名为
begin
和end
成员函数,可以称为C.begin()
和C.end()
; - 否则,您可以使用参数相关查找或命名空间
std
提供名为begin
和end
免费函数,并可以像begin(C)
和end(C)
一样调用。
为了能够使用基于范围的,你的类应该提供const_iterator begin() const
和const_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();} };
如果你想迭代任何自定义的,你可能必须devise自己的迭代器作为你的容器内的类。
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 };
有关编写迭代器类的更多详细信息,请参阅我的答案 。
正如其他人所说的,你的容器必须实现begin()
和end()
函数(或者具有以你的容器实例为参数的全局函数或std::
函数)。
这些函数必须返回相同的types(通常是container::iterator
,但这只是一个约定)。 返回的types必须实现operator*
, operator++
和operator!=
。
据我所知, SomeSortedContainer
只需要提供begin()
和end()
。 这些应该返回一个标准的顺从迭代器,在你的情况SomeSortedContainerIterator
,它实际上会包装一个std::vector<Type>::iterator
。 对于标准兼容,我的意思是它必须提供通常的增量和取消引用操作符,而且所有的这些value_type
, reference_type
,… typedefs,这反过来由foreach构造使用,以确定容器元素的基础types。 但你可能只是从std::vector<Type>::iterator
转发它们。