Re: When operator>> can throw...
In article <daniel_t-8ECA2C.13591419012008@earthlink.vsrv-
sjc.supernews.net>, daniel_t@earthlink.net says...
Erik Wikstr=C3=B6m <Erik-wikstrom@telia.com> wrote:
On 2008-01-19 16:15, Daniel T. wrote:
This is basically what I have now...
class Foo { /* definition irrelevant */ };
istream& operator>>( istream& is, Foo& foo ); // could throw
int main() {
ifstream file( "file.txt" );
Foo foo;
int i = 0;
try {
while ( file >> foo ) {
//process foo;
++i;
}
}
catch ( exception& e ) {
cout << "error at: " << i << '\n';
}
}
The problem I'm having is that op>> could throw. If it does, I don't=
want to process the foo object that threw, but I want the program to=
report an error and continue extracting foo objects.
I could make op>> a no-throw and give Foo some sort of error or inval=
id
state, but that doesn't feel right. I can't report the error inside t=
he
op>> because I don't have enough information to make a full report.
Does anyone have a better idea, or do I give Foo and error state and=
query it after the read?
Something like this perhaps?
int main() {
ifstream file( "file.txt" );
Foo foo;
int i = 0;
while ( file.eof() == false ) {
try {
file >> foo;
} catch ( exception& e )
cout << "error at: " << i << '\n';
continue;
}
++i;
}
}
That doesn't handle the end of file correctly...
I could do something like:
typedef int Foo;
int main() {
ifstream file( "file.txt" );
Foo foo;
int i = 0;
while ( file.eof() == false ) {
try {
while ( file >> foo ) {
// process foo
++i;
}
} catch ( exception& e ) {
cout << "error at: " << i << '\n';
}
}
}
But that seems strange.
Does anyone have a different idea?
I don't really _like_ it, but this seems at least a bit less convoluted:
int i=1;
for(;;) {
try {
in>>foo;
if (!in)
break;
// process foo
++i;
}
catch(exception const &) {
std::cout << "error at: " << i << "\n";
}
}
I think the better solution would be for a failure to read an object
correctly to set the stream's fail bit to indicate the problem.
Processing this cleanly still isn't entirely trivial, but it's quite a
bit cleaner:
int i = 1;
do {
in.clear();
while (in>>f) {
foos.push_back(f);
++i;
}
if (!in.eof())
std::cout << "Error at: " << i << "\n";
} while (!in.eof());
If you want to produce robust code, something along this general line
(i.e. checking for what went wrong when a stream is no longer good() and
reacting accordingly) is often necessary anyway. Of course, "reacting
accordingly" normally involves more than a completely cryptic error
message, but we'll leave that alone for now...
I think you could make a fair argument that errors in input are to be
expected sufficiently often that throwing an exception from operator>>
is never really justified.
--
Later,
Jerry.
The universe is a figment of its own imagination.