2011-09-26 341 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!=