可以使用输入迭代器在期望向前迭代器吗? [英] Can input iterators be used where forward iterators are expected?

查看:138
本文介绍了可以使用输入迭代器在期望向前迭代器吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,迭代器类别的层次结构如下:

 随机访问 - 双向>前进 - >输入
- >输出

正确?



有一个规则,如果一个算法期望一个特定类型的迭代器,你可以提供链上的类别的迭代器,但不能向下。所以我在阅读这个答案,其中ildjarn 建议建议(然后使用 std :: ifstream std :: istream_iterator std :: search 来查找文件中的数据。我将要评论你不能这样做,因为 search 期望Forward迭代器,并且 istream_iterator 是一个Input迭代器。但只是为了确保,我尝试这样:

  std :: istringstream iss(Elephant hats for sale。 
std :: istream_iterator< char> begin(iss),end;

std :: string sub(hat);
auto i = std :: search(begin,end,sub.begin(),sub.end());



我没想到它会编译,但是它。但是,结果似乎没有用,因为如果我跟着这个:

  while(i!= end)
{
std :: cout<< *一世;
++ i;
}

没有输出。所以,我的问题是这是:我的编译器错误允许我调用搜索使用 istream_iterator

解决方案


可以将输入迭代器用于向前需要迭代器吗?


否。输入迭代器和前向迭代器之间的区别在于输入迭代器是单遍迭代器,而前向迭代器是多遍迭代器。



提升输入迭代器后,您将无法再访问范围中的前一个元素。如果你创建一个输入迭代器的副本,两个迭代器保持有效,直到你提前一个;



使用前向迭代器,您可以对序列进行任意次数的迭代,可以同时拥有多个可用的迭代器副本,您可以同时使用多个迭代器到序列中,并且您可以在重新推送之前解除引用迭代器的次数。


所以,我的问题是这是:我的编译器错误允许我的调用使用 istream_iterator




没有规则,编译器必须拒绝代码。



规则是你必须确保传递函数所需的正确类型的迭代器。有时如果你传递错误类型的迭代器,你会得到一个编译错误。有时程序会编译,但不会正常工作。有时,事情似乎会正常工作。






通用算法通常会对其类型参数施加要求假设提供的类型参数实际上满足要求。因此,例如,只对随机访问迭代器起作用的算法将通过执行只对随机访问迭代器(例如 it + 1 )起作用的一些操作来强制 。如果迭代器不支持该操作( operator +(iterator,int)这里),代码将无法编译。


$ b $问题是没有办法以这种方式区分输入迭代器和正向迭代器:你可以增加和解除引用它们;区别在于您可以执行每个操作的次数以及可以执行这些操作的顺序。因此, std :: search 的算法将使用 * it ++ it ,这将工作只是罚款输入迭代器,至少在代码将编译。



理论上,一个算法可以使用 std :: iterator_traits 类模板来确定迭代器是输入迭代器还是前向迭代器;我不知道这是否将被允许的C ++语言标准。如果库这样做,你可能会得到一个编译错误,这将是更好的。


To my knowledge, the hierarchy of iterator categories goes like this:

Random access -> Bi-directional -> Forward -> Input
                                           -> Output

Correct?

I always thought there was a rule, that if an algorithm expects a particular type of iterator, you can provide iterators of categories up the chain, but not down. So I was reading this answer, where ildjarn suggests suggested (then later corrected himself) using std::ifstream with std::istream_iterator and std::search to find data in a in a file. I was about to comment that you can't do that, because search expects Forward iterators, and istream_iterator is an Input iterator. But just to make sure, I tried this:

std::istringstream iss("Elephant hats for sale.");
std::istream_iterator<char> begin(iss), end;

std::string sub("hat");
auto i = std::search(begin, end, sub.begin(), sub.end());

I didn't expect it to compile, but it did. However, the results seem to be useless because if I follow it with this:

while(i != end)
{
    std::cout << *i;
    ++i;
}

There is no output. So, my question is this: Is my compiler in error for allowing my call to search using istream_iterator? Or are there no rules preventing this sort of thing?

解决方案

Can input iterators be used where forward iterators are expected?

No. The difference between an input iterator and a forward iterator is that an input iterator is a "single-pass" iterator but a forward iterator is a "multi-pass" iterator.

Once you advance an input iterator, you can no longer access the previous elements in the range. If you make a copy of an input iterator, both iterators remain valid until you advance one of them; then the other ceases to be valid.

With a forward iterator, you can iterate over the sequence any number of times, you can have multiple usable copies of an iterator at once, you can use multiple iterators into the sequence at the same time, and you can dereference an iterator as many times as you'd like before advancing it again.

So, my question is this: Is my compiler in error for allowing my call to search using istream_iterator?

There is no rule that the compiler must reject the code.

The rule is that you must be sure to pass the right type of iterator that is required by the function. Sometimes if you pass the wrong type of iterator you get a compilation error. Sometimes the program will compile but will not function correctly. Sometimes things will appear to work correctly. The results are undefined if you violate the requirements of calling the function.


Generic algorithms usually impose requirements on their type parameters by assuming that the type arguments provided actually meet the requirements. So, for example, an algorithm that only works with random access iterators will "enforce" this requirement by performing some operation that only works with random access iterators (e.g. it + 1). If the iterator doesn't support that operation (operator+(iterator, int) here), the code will fail to compile.

The problem is that there is no way to distinguish between input iterators and forward iterators this way: you can increment and dereference both of them; the difference is in how many times you can perform each of those operations and the sequence in which you can perform those operations. So, an algorithm like std::search will use *it and ++it, which will "work" just fine for input iterators, at least insofar as the code will compile.

In theory, an algorithm could use the std::iterator_traits class template to determine whether an iterator is an input iterator or a forward iterator; I don't know whether that would be permitted by the C++ language standard. If the library did that, you could get a compilation error for your code, which would be better.

这篇关于可以使用输入迭代器在期望向前迭代器吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆