This is an interesting problem in that there are issues with: the code, the MS CRT implementation, and the MS STL implementation.
First, the code. istream_iterator<X> performs an operator>>(X) on the input stream when the iterator is constructed and when the iterator is incremented. When istream_iterator is default constructed, it represents an iterator of an input stream which is no longer good (ie. istream.good() == false). That means that a default constructed istream_iterator should only be used for comparisons. So far nothing new...
The issue with the display() code stems from the "*start++" construct. When input of "1 2 3<enter>" is used, you should see "1<endl>2<endl>". So what happened to 3? The answer is that cin is waiting for the next integer input (after 3), but before 3 is displayed.
Why?
Well, to understand why, let's rewrite "*start++" to logically equivalent code:
Code:
[1] Iter tmp = start;
[2] start++;
[3] cout << *tmp << endl;
It should be easier to why 3 is not displayed. First, istream_iterator<int>(cin) is constructed which initiates the first "cin >> int" operation. Remember that input is buffered, so were actually inside the istream_iterator constructor when we type "1 2 3<return>". Hitting <return> causes execution to return from "cin >> int" after the 1 is extracted from the stream. Then we go into display(). Since cin is still good, the expression "start != end" is true. Then on line [1], we create a copy of the iterator witch initially contains 1. Line [2] then extracts the next integer from the stream, which is readily available. Then "1<endl>" is sent to cout on line [3].
Eventually, line [2] will execute and there won't be any buffered input to extract integers from, so the call "blocks" waiting for input from the keyboard, but before the previously extracted integer is displayed.
Now on to the MS implementation issues. The first "issue" is within the MS CRT implementation in how it handles CTRL-Z on stdin (when stdin is not redirected). What it does is this: If the first character read is CTRL-Z, then EOF is returned. If the first character read is not CTRL-Z, the buffered input from stdin is truncated at the first occurrence of CTRL-Z.
To demonstrate this issue, I'll use an istreambuf_iterator<char>(cin) to get the raw characters from stdin:
Code:
#include <iostream>
#include <iterator>
using namespace std;
template<typename Iter>
void display(Iter start, Iter end)
{
while (start != end)
{
// display the contents of "*start" as an int
cout << "[" << int(*start) << "]" << endl;
start++;
}//while
// display cin's state bits
// NOTE: when using an istreambuf_iterator<cin>, the state will not change
// since it operates on the stream's buffer
ios_base::iostate st = cin.rdstate();
cout << "cin.rdstate() == ";
if (st & ios_base::eofbit)
cout << "eofbit | ";
if (st & ios_base::failbit)
cout << "failbit | ";
if (st & ios_base::badbit)
cout << "badbit | ";
if (st == ios_base::goodbit)
cout << "goodbit | ";
cout << "\b\b " << endl; // remove the trailing "| "
}//display
int main()
{
display(istreambuf_iterator<char>(cin), istreambuf_iterator<char>());
return 0;
}//main
The following test run shows input in blue:
Code:
ab<enter>
[97]
[98]
[10]
a^Zb<enter>
[97]
^Z<enter>
cin.rdstate() == goodbit
As you can see, placing a CTRL-Z between the 'a' and 'b' caused the 'b' and the <return> to be ignored. Using CTRL-Z as the first character of the line caused the streambuf to reach the "end-of-file". Those of you using MinGW will find the same behavior because it uses the MS CRT under the hood.
Now on to the issue with the MS STL implementation. Here I'm referring to the MS STL that ships with VC++ 6.0. The issue here is that they "broke" CTRL-Z even further when using a formatted-input function on stdin. That is, CTRL-Z as the first character of a line doesn't work as expected. To demonstrate this one, we'll perform the same test as above, except we'll use an istream_iterator<char> in the call to display().
Code:
ab<enter>
[97]
[98]
a^Zb<enter>
[97]
^Z<enter>
<enter>
[10]
^Z<enter>
^Z<enter>
cin.rdstate() == eofbit | failbit
Why you have to hit CTRL-Z <enter> twice to generate an "end-of-file" is beyond me. The GNU STL implementation that comes with Dev-C++ 4.9.8 handles CTRL-Z as expected, only if it's the first thing read from unbuffered input (but that's not their fault, unless you blame them for using the MS CRT ).
I would be interested in other's results using different implementations (STLport or 7.0 MS CRT).
gg