我有一个类TContainer,它是指向TItems类的几个stl集合指针的集合。
我需要创建一个Iterator来遍历我的TContainer类中所有集合中的元素,从而抽象出内部工作的客户端。
这样做的好方法是什么?我应该创建一个扩展迭代器的类(如果是,我应该扩展什么迭代器类),我应该创建一个迭代器类,它是迭代器的集合吗?
我只需要一个FORWARD_ONLY迭代器。
I.E,如果这是我的容器:
typedef std::vector <TItem*> ItemVector;
class TContainer {
std::vector <ItemVector *> m_Items;
};
遍历m_Items成员变量向量中包含的所有项目的好迭代器。
答案 0 :(得分:31)
当我使用自己的迭代器(前一段时间)时,我继承自std :: iterator并将该类型指定为第一个模板参数。希望有所帮助。
对于前向迭代器,用户使用forward_iterator_tag而不是以下代码中的input_iterator_tag。
这个类最初来自istream_iterator类(并且我自己修改了它,因此它可能不再像istram_iterator那样)。
template<typename T>
class <PLOP>_iterator
:public std::iterator<std::input_iterator_tag, // type of iterator
T,ptrdiff_t,const T*,const T&> // Info about iterator
{
public:
const T& operator*() const;
const T* operator->() const;
<PLOP>__iterator& operator++();
<PLOP>__iterator operator++(int);
bool equal(<PLOP>__iterator const& rhs) const;
};
template<typename T>
inline bool operator==(<PLOP>__iterator<T> const& lhs,<PLOP>__iterator<T> const& rhs)
{
return lhs.equal(rhs);
}
在迭代器标签上查看此文档:
http://www.sgi.com/tech/stl/iterator_tags.html
重新阅读有关迭代器的信息:
http://www.sgi.com/tech/stl/iterator_traits.html
这是旧的做事方式(iterator_tags)更现代的方法是设置iterator_traits&lt;&gt;为你的迭代器使它与STL完全兼容。
答案 1 :(得分:22)
如果您有权访问Boost,使用iterator_facade
是最强大的解决方案,而且使用起来非常简单。
答案 2 :(得分:18)
首先让我们概括一下:
typedef int value_type;
typedef std::vector<value_type*> inner_range;
typedef std::vector<inner_range*> outer_range;
现在是迭代器:
struct my_iterator : std::iterator_traits<inner_range::iterator>
{
typedef std::forward_iterator_tag iterator_category;
my_iterator(outer_range::iterator const & outer_iterator,
outer_range::iterator const & outer_end)
: outer_iterator(outer_iterator), outer_end(outer_end)
{
update();
}
my_iterator & operator++()
{
++inner_iterator;
if(inner_iterator == inner_end)
{
++outer_iterator;
update();
}
return *this;
}
reference operator*() const
{
return *inner_iterator;
}
bool operator==(my_iterator const & rhs) const
{
bool lhs_end = outer_iterator == outer_end;
bool rhs_end = rhs.outer_iterator == rhs.outer_end;
if(lhs_end && rhs_end)
return true;
if(lhs_end != rhs_end)
return false;
return outer_iterator == rhs.outer_iterator
&& inner_iterator == rhs.inner_iterator;
}
private:
outer_range::iterator outer_iterator, outer_end;
inner_range::iterator inner_iterator, inner_end;
void update()
{
while(outer_iterator != outer_end)
{
inner_iterator = (*outer_iterator)->begin();
inner_end = (*outer_iterator)->end();
if(inner_iterator == inner_end)
++outer_iterator;
else
break;
}
}
};
此类假定外部迭代器包含指向内部范围的指针,这是您的问题中的要求。这反映在update
成员,begin()
和end()
之前的箭头中。如果要在外部迭代器按值包含内部范围的更常见情况下使用此类,则可以用点替换这些箭头。注意BTW,这个类与内部范围包含指针的事实无关,只有类的客户端才需要知道。
如果我们使用boost::iterator_facade
,代码可能会更短,但是没有必要为这么简单的事情添加一个boost依赖。此外,唯一棘手的部分是相等和增量操作,无论如何我们必须对它们进行编码。
我将以下的锅炉板成员留作“为读者练习”:
另一项有趣的练习是将其转换为适用于任意容器的模板。除了必须在几个地方添加typename
注释之外,代码基本相同。
使用示例:
int main()
{
outer_type outer;
int a = 0, b = 1, c = 2;
inner_type inner1, inner2;
inner1.push_back(&a);
inner1.push_back(&b);
inner2.push_back(&c);
outer.push_back(&inner1);
outer.push_back(&inner2);
my_iterator it(outer.begin(), outer.end());
e(outer.end(), outer.end());
for(; it != e; ++it)
std::cout << **it << "\n";
}
打印哪些:
0 1 2
答案 3 :(得分:6)
迭代器只是一个支持某个接口的类。至少,您希望能够:
一旦你有一个可以为你的集合明智地做这个的类,你将需要修改集合以具有返回迭代器的函数。至少你会想要
答案 4 :(得分:1)
答案 5 :(得分:0)
这是我能够生成的最简单的代码(用于自定义迭代器)。请注意,我才开始探索这个领域。这会调用内置的upper_bound
函数来对整数函数x^2
执行二进制搜索。
#include <algorithm>
#include <iostream>
using namespace std;
class Iter
{
public:
int x;
Iter() { x = -1; }
Iter(int a) { x = a; }
bool operator!=(Iter &i2) const { return x != i2.x; }
void operator++() { x++; }
void operator+=(int b) { x += b; }
int operator-(const Iter &i2) const { return x - i2.x; }
int operator*() const {
cout << "calculating for x " << x << endl;
return x*x;
}
typedef random_access_iterator_tag iterator_category;
typedef int value_type;
typedef int difference_type;
typedef int* pointer;
typedef int& reference;
};
main ()
{
ios::sync_with_stdio(false);
cout << upper_bound(Iter(0), Iter(100), 40).x << endl;
}
// :collapseFolds=1:folding=explicit:
这就是输出的样子:
calculating for x 50
calculating for x 25
calculating for x 12
calculating for x 6
calculating for x 9
calculating for x 8
calculating for x 7
7