From the standard [24.5.1]/1:
[...] The constructor with no arguments
istream_iterator() always constructs
an end of stream input iterator
object, which is the only legitimate
iterator to be used for the end
condition. [...] The main peculiarity of the istream iterators is the fact that ++ operators are not equality preserving, that is, i == j does not guarantee at all that ++i == ++j. Every time ++ is used a new value is read.
[24.5.1]/3
Two end-of-stream iterators are
always equal. An end-of-stream
iterator is not equal to a
non-end-of-stream iterator. Two
non-end-of-stream iterators are equal
when they are constructed from the
same stream
The first paragraph states that you cannot use any but end-of-stream iterators as end conditions, so your first usage is correct and expected. The third paragraph in the chapter states that any two non-end-of-stream iterators into the same stream are guaranteed to be equal at all times. That is, the second usage is correct from the language standpoint and will provide the results you are getting.
The last part of paragraph 1, where it states that i == j
does not imply ++i == ++j
deals with the particular case of one last element present in the stream. After incrementing the first of the iterators (either i
or j
) the datum is consumed by that iterator. Advancing the other iterator will hit the end of stream and thus the two iterators will differ. In all other cases (there is more than one datum left in the stream), ++i == ++j
.
Also note that the sentence ++i == ++j
executes two mutating operations on the same element (stream) and thus it is not which of the two iterators get the first/second datum in the stream.