自定义输入迭代器
我有一个需要遍历的自定义只读数据结构。我想创建一个需要跳过某些值的自定义迭代器。
下面是一个简单但等效的示例。我有一个数字向量,我想循环遍历所有跳过负值的向量。通常我会做类似的事情:
vector<int> v;
for (vector<int>::iterator it = v.begin(); it!=v.end(); ++it) {
if (*it > 0) {
dosomething(*it);
}
}
但我想做类似的事情:
vector<int> v;
for (vector<int>::my_iterator it = v.my_begin(); it!=v.my_end(); ++it) {
dosomething(*it);
}
实现这一目标的正确方法是什么?
I have a custom read-only data structure that I need to transverse. I would like to create a custom iterator that need to skip certain values.
A simple but equivalent example would be the following. I have a vector of numbers and I want to loop through all skipping the negative values. Normally I would do something like:
vector<int> v;
for (vector<int>::iterator it = v.begin(); it!=v.end(); ++it) {
if (*it > 0) {
dosomething(*it);
}
}
But I would like to do something like:
vector<int> v;
for (vector<int>::my_iterator it = v.my_begin(); it!=v.my_end(); ++it) {
dosomething(*it);
}
What is the right way to achieve this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这可以通过
boost::filter_iterator 轻松实现
,如果您的数据结构已经在底层存储了一个容器。这是一个简单的示例:Ideone 的实时示例。 输出:
This is easily achieved with a
boost::filter_iterator
, if your data structure already stores a container under the hood. Here's a simple example:Live example at Ideone. Output:
这不是一个很好的解决方案,但无论如何我都会发布它。任何取消引用此迭代器包装器的尝试都将导致它检查当前值并将迭代器推进到超过任何负值。它将被称为 recur,
可以像这样使用:
这有一些问题,例如我还没有实现
const
方法来允许取消引用value_type
。因此,使用风险需您自担!This isn't a very nice solution, but I'll post it anyway. Any attempt to dereference this iterator wrapper will cause it to check the current value and advance the iterator past any negative values. It will be called recur
which can be used like this:
This has some problems, for example I haven't implemented a
const
method to allow to dereference tovalue_type
. So use at your own risk!假设您无法控制
vector
的接口,例如因为它实际上是std::vector
,那么您要做的第一件事就是是改变你获取自定义迭代器的方式。也就是说,您可以使用
您可以实现自定义容器的修改接口,而不是编写,但这是一个更大的问题。现在创建输入迭代器本质上相当于为底层迭代器创建合适的包装器。这可能看起来像这样:
my_begin()
和my_end()
函数将创建该类型的合适对象。避免编写此代码的一种方法是查看 Boost 的迭代器适配器:那里应该有合适的东西。Assuming you don't have control over the interface of
vector<int>
, e.g. because it is actuallystd::vector<int>
, the first thing you want to do is to change the way you get your custom iterators. That is, instead of writingyou would use
You can achieve the modified interface for a custom container but this is a bigger fish to fry. Creating your input iterator now essentially amounts to creating a suitable wrapper for the underlying iterator. This could look something like this:
The
my_begin()
andmy_end()
functions would then create a suitable object of this type. One approach to avoid having to write this is to have a look a Boost's iterator adaptors: there should be something suitable over there.