Alex Rivera | Logout

Can input iterators be used where forward iterators are expected?

Asked 2011-06-23T04:15:06.403
13

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?

Edit
Report

1 Answer

19

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 be

answered 2011-06-23T04:20:50.363

Your Answer