This comes down to a perhaps unintuitive fact of istream_iterator
: it doesn't read when you dereference it, but instead when you advance (or construct) it.
(x indicates a read)
Normal forward iterators:
Data: 1 2 3 (EOF)
Construction
*it x
++it
*it x
++it
*it x
++it (`it` is now the one-past-the-end iterator)
Destruction
Stream iterators:
Data: 1 2 3 (EOF)
Construction x
*it
++it x
*it
++it x
*it
++it (`it` is now the one-past-the-end iterator)
Destruction
We still expect the data to be provided to us via *it
. So, to make this work, each bit of read data has to be temporarily stored in the iterator itself until we next do *it
.
So, when you create iit
, it's already pulling the first number out for you, 1
. That data is stored in the iterator. The next available data in the stream is 2
, which you then pull out using copy_n
. In total that's two pieces of information delivered, out of a total of two that you asked for, so the first copy_n
is done.
The next time, you're using a copy of iit
in the state it was in before the first copy_n
. So, although the stream is ready to give you 3
, you still have a copy of that 1
"stuck" in your copied stream iterator.
Why do stream iterators work this way? Because you cannot detect EOF on a stream until you've tried and failed to obtain more data. If it didn't work this way, you'd have to do a dereference first to trigger this detection, and then what should the result be if we've reached EOF?
Furthermore, we expect that any dereference operation produces an immediate result; with a container that's a given, but with streams you could otherwise be blocking waiting for data to become available. It makes more logical sense to do this blocking on the construction/increment, instead, so that your iterator is always either valid, or it isn't.
If you sack off the copies, and construct a fresh stream iterator for each copy_n
, you should be fine. Though I would generally recommend only using one stream iterator per stream, as that'll avoid anyone having to worry about this.