Cannot explain why std::istream_iterator set std::ios_base in error state
I am trying to conert a vector into a stream and back. While the first part works without issues, the last line of the following code put std::ios_base is an error state. Have you got any idea why it is so? Apparently myVecOut is equal to myVec after the code executes....
std::vector<double> myVec( 3 );
std::stringstream temp;
std::copy(myVec.begin(), myVec.end(), std::ostream_iterator<double>(temp, " "));
std::cout << temp.str() << std::endl;
std::vector<double> myVecOut;
std::copy(std::istream_iterator<double>(temp), std::istream_iterator&开发者_StackOverflow中文版lt;double>(), std::back_inserter(myVecOut));
It's set into fail
state, because copy
does not know how many items to read. It reads as long as the stream is in a non-.good()
.fail()
state. While skipping the last space, it hits the end, and sets both eof
(because it tried to read beyond the end) and fail
(because it could not read the double it wanted to).
Call .clear()
afterwards to clear those error bits.
The difference between the iterators comparing non-equal while .good()
is true and while .fail()
is false is that istream_iterator
will still advance even if the stream is in an eof
state. The following further examines it:
std::stringstream a;
a << "1.1 2.2";
std::copy(std::istream_iterator<double>(a), std::istream_iterator<double>(),
std::ostream_iterator<double>(std::cout, " "));
Now, after we read "2.2", the eof
state is set (because it tried to read beyond "2"). But the begin and end iterator won't yet compare equal, because the fail
state is not set, and thus .fail()
does not return true (while .good()
would have returned false, because it considers .eof()
in addition). Only after the next read, when it could not read another double anymore, the fail
state is set, and then the iterators compare equal, and the loop within std::copy
exits.
精彩评论