Ah, language, James, language! I don't know where you got the
idea that I might be stupid. After all, I'm pretty smart.
I know you are. But even smart people don't know everything.
The smartest, of course, know enough to know what they don't
know. That's why I don't understand your posting.
And of course I've tried it, and you do risk getting an
exception on (first detection of) EOF if you ask for
exceptions on failbit.
With what compiler? I've never encountered this.
And if
you only ask for exceptions on badbit, you're not guaranteed to get an
exception when an input operation fails to read what you requested[1],
so that's not exceptions on failure. In short, to use your chosen
descriptive word here, it's "stupid", and you're wrong.
No I'm not. The exception mask is exactly identical with the
bits: if you ask for an exception on eofbit, you get one on
eofbit (which is totally useless). If you ask for one on
failbit, then you get one on failbit, and only on failbit. (At
least according to the standard---I've obviously not tried every
library in existance. But it works correctly with the g++
implementation of the library, Rogue Wave's, the STL port and
Dinkumware.)
Treating detection of EOF as an exceptional failure (and more
generally, coupling detection of EOF to failure to read what's
asked for) is very ungood design.
I'm not particularly happy about the fact that you cannot easily
distinguish between failure due to end of file, and failure due
to a format error. Regretfully, the old C style I/O isn't
particulary good about this either.
For that matter, sticky EOF state, hidden modes, silent
failure, etc. etc. associated with this particular little
aspect of iostreams, it's so bad that even "badbit" and
"failbit" don't adequately convey how badly it fails.
The sticky error states are a good point (and also inherited
from the C I/O). Under Unix, for various reasons, EOF state
also has to be sticky at some level; I agree that it would have
been perhaps better to say that if filebuf::sgetc() returns EOF
once, it must return EOF always. (This is not totally without
problems, either, but problems which could potentially be solved
by addiing some state manipulation functions to streambuf.)
There is a real, very fundamental, problem with both C and C++
I/O: they are too Unix centric.
<code>
#include <iostream>
#include <ostream>
#include <cstddef>
#include <stdexcept>
#include <string>
void cppMain()
{
using namespace std;
cin.exceptions( ios::badbit ); // James' recommendation.
// Are we guaranteed that non-throwing input = successful input?
while( !cin.fail() )
{
int x;
cin >> x;
cout << "* " << x << endl;
}
Obviously not. If you have a hard error (a disk read error, for
example), I would expect an exception. But only if you have a
hard error. (And whether the system detects such errors is a
quality of implementation issue---I think most Unix based
systems would just treat them as end of file, in the great Unix
tradition of sticking your head in the sand.)
You don't want an exception for the failure errors. If the
failure is due to no more data, it's a "normal" condition, and
if it is due to a format error in the file, it's also an
"expected" condition, and not exceptional---typically, too, it
will be handled locally by outputting an error message, then
clearing the error status, and skipping ahead to some
resynchronization point where you can resume reading the file.
Usually, the only time you want an exception is when a really
exceptional condition occurs: a hardware read error from the
disk, for example.
Exceptionally, of course, you may feel sure enough about the
format of the file to decide that a format error *is* an
exceptional condition. (If, for example, it is, or should be, a
file written by your program sometime earlier.) You know, for
example, that it contains three integers. In such cases, it
might make sense to request exceptions for failbit as well. And
of course, you will get the exception if the file doesn't
actually contain three integer values.
If your claim is simply that the error states don't provide as
much information as they should, then I totally agree, although
the C++ I/O is slightly better than the C in this regard. (C++
does allow disinguishing between hardware errors and the others,
which is usually fairly important. In most cases, it's also
possible to distinguish between format errors and a real eof,
but it does require more programming than it should, and it
isn't 100% reliable.)