首先让我们稍微概括一下:
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() 之前的箭头中。如果要在外部迭代器按值包含内部范围的更常见情况下使用此类,可以将这些箭头替换为点。请注意顺便说一句,这个类不知道内部范围包含指针这一事实,只有该类的客户端需要知道这一点。
如果我们使用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