c ++ 11 foreach语法和自定义迭代器

时间:2011-09-26 23:00:34

标签: c++ iterator c++11

我正在编写一个用于代替STL容器的容器的迭代器。目前,STL容器正在许多地方使用,c++11 foreach syntax例如: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
};

如何让auto为自定义容器使用正确的迭代器,以便能够以下列方式调用代码?:

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

一般来说,确保auto为类使用正确的迭代器需要什么?

4 个答案:

答案 0 :(得分:51)

为了能够使用基于范围的,您的班级应该提供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

答案 1 :(得分:51)

您有两种选择:

  • 您提供名为beginend的成员函数,可以调用C.begin()C.end();
  • 否则,您提供名为beginend的免费函数,这些函数可以使用参数依赖查找或名称空间std找到,并且可以像begin(C)一样调用和end(C)

答案 2 :(得分:7)

正如其他人所说,您的容器必须实现begin()end()函数(或具有将容器实例作为参数的全局或std::函数。)

这些函数必须返回相同的类型(通常为container::iterator,但这只是一种约定)。返回的类型必须实现operator*operator++operator!=

答案 3 :(得分:2)

据我所知SomeSortedContainer,只需提供begin()end()即可。这些应该返回一个标准的兼容前向迭代器,在你的情况下SomeSortedContainerIterator,它实际上会包裹std::vector<Type>::iterator。标准兼容我的意思是它必须提供通常的增量和解除引用操作符,还有所有那些value_typereference_type,... typedef,而foreach结构又使用它来确定底层容器元素的类型。但您可以从std::vector<Type>::iterator转发它们。