When operator>> can throw...



 DEVELOP > c-Plus-Plus > When operator>> can throw...

LINK TO THIS PAGE  


rating :  0   |  0


  Page 1 of 1

1

 
Topic: DEVELOP > c-Plus-Plus
User: "Daniel T."
Date: 19 Jan 2008 09:15:59 AM
Object: When operator>> can throw...
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 invalid
state, but that doesn't feel right. I can't report the error inside the
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?
.

User: "James Kanze"

Title: Re: When operator>> can throw... 20 Jan 2008 04:13:46 AM
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 =3D 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.

The question is: what can it throw, and do you want to handle
it? A well written >> will probably only throw something like
bad_alloc, which you generally cannot really handle anyway.

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.

Doesn't that depend on why it threw?

I could make op>> a no-throw and give Foo some sort of error
or invalid state, but that doesn't feel right. I can't report
the error inside the op>> because I don't have enough
information to make a full report.

I'm not sure I understand. Error reporting for istream's is
pretty much standardized: if you encounter a format error, or
there is nothing left to read, you set failbit, a hard read
error, badbit, and while not really an error, anytime you see
EOF, you should set eofbit.
After that, it is the users responsibility to determine whether
he wants that error to throw or no. It's sometimes (often?)
appropriate in the case of badbit, only rarely for failbit, and
probably never for eofbit.
Note that recovering from the error can be more or less
difficult: you have to clear the error in the stream, of course,
but you also have to resynchronize. (For line oriented input,
where each record is a line, it is usual to use getline(), and
then use an istringstream to parse the text. This automatically
leaves the stream "synchronized" for the next input.)

Does anyone have a better idea, or do I give Foo and error
state and query it after the read?

I doubt that Foo should have error state, but istream already
has it.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34
.
User: "Daniel T."

Title: Re: When operator>> can throw... 20 Jan 2008 03:07:02 PM
James Kanze <james.kanze@gmail.com> wrote:

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.


The question is: what can it throw, and do you want to handle
it? A well written >> will probably only throw something like
bad_alloc, which you generally cannot really handle anyway.

I took the above advice (and Jerry Coffin's) and redesigned my op>> so
that it will not throw.

I'm not sure I understand. Error reporting for istream's is
pretty much standardized: if you encounter a format error, or
there is nothing left to read, you set failbit, a hard read
error, badbit, and while not really an error, anytime you see
EOF, you should set eofbit.

I just read
http://www.unc.edu/depts/case/pgi/pgC++_lib/stdlibug/err_7848.htm and it
seems to indicate that I should not set badbit inside my op>>, rather
that is something the stream itself would do if there is a problem
internal to it.
(from the website cited.)
The flag ios_base::badbit indicates problems with the underlying
stream buffer. These problems could be:
* Memory shortage. There is no memory available to create the
buffer, or the buffer has size zero for other reasons[21], or the
stream cannot allocate memory for its own internal data, as with
iword and pword.
* The underlying stream buffer throws an exception. The stream
buffer might lose its integrity, as in memory shortage, or code
conversion failure, or an unrecoverable read error from the
external device. The stream buffer can indicate this loss of
integrity by throwing an exception, which is caught by the stream
and results in setting the badbit in the stream's state.
.
User: "Jerry Coffin"

Title: Re: When operator>> can throw... 20 Jan 2008 05:18:35 PM
In article <daniel_t-700A6E.16070220012008@earthlink.vsrv-
sjc.supernews.net>,
says...
[ ... ]

I just read
http://www.unc.edu/depts/case/pgi/pgC++_lib/stdlibug/err_7848.htm and it
seems to indicate that I should not set badbit inside my op>>, rather
that is something the stream itself would do if there is a problem
internal to it.

True -- badbit normally indicates something severely wrong with the
stream itself, such an unrecoverable error attempting to read from the
disk or something like that.
You want to use failbit to report a failed conversion. That's typically
set by an operator>>, or something it delegates to such as the num_get
in the locale associated with that stream.
--
Later,
Jerry.
The universe is a figment of its own imagination.
.

User: "James Kanze"

Title: Re: When operator>> can throw... 21 Jan 2008 02:48:47 AM
On Jan 20, 10:07 pm, "Daniel T." <danie...@earthlink.net> wrote:

James Kanze <james.ka...@gmail.com> wrote:

Daniel T. wrote:

I just read
http://www.unc.edu/depts/case/pgi/pgC++_lib/stdlibug/err_7848.htmand
it seems to indicate that I should not set badbit inside my
op>>, rather that is something the stream itself would do if
there is a problem internal to it.

This depends on how you implement your operator>>. There are
two basic approches:
-- You implement your operator>> in terms of other, existing
operator>> (and other istream functions, like get() or
peek()). In this case, you probably shouldn't bother with
badbit, since it will be (or should be, at least) fully
handled by the operator>> functions you call. The same
thing holds for eofbit---the only error bit you should be
concerned with if failbit, because that is the indicator
that either no data was present (if eof was encountered), or
that there was an error in the format (no eof).
-- You implement your operator>> by means of direct access to
the streambuf, reading individual characters. In that case,
you should catch any exception and map it to badbit; you
also have to ensure that anytime you see EOF (including
during look-ahead), you set eofbit, and that you never try
to read the streambuf once eofbit has been set. (I usually
use a small reader class to handle the the eofbit stuff.)
The text you quote seems to only consider the first case. While
typically, the first case is easier to implement, and should be
preferred, it doesn't apply to all user defined types; you can't
really use it for something like BigDecimal, for example.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34
.



User: "=?UTF-8?B?RXJpayBXaWtzdHLDtm0=?="

Title: Re: When operator>> can throw... 19 Jan 2008 11:31:14 AM
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 invalid
state, but that doesn't feel right. I can't report the error inside the
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;
}
}
--
Erik Wikström
.
User: "Daniel T."

Title: Re: When operator>> can throw... 19 Jan 2008 12:59:14 PM
Erik Wikström <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 invalid
state, but that doesn't feel right. I can't report the error inside the
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?
.
User: "Jerry Coffin"

Title: Re: When operator>> can throw... 19 Jan 2008 09:23:09 PM
In article <daniel_t-8ECA2C.13591419012008@earthlink.vsrv-
sjc.supernews.net>,
says...

Erik Wikstr=C3=B6m <Erik-wikstrom@telia.com> wrote:

On 2008-01-19 16:15, Daniel T. wrote:

=20

This is basically what I have now...
=20
class Foo { /* definition irrelevant */ };
=20
istream& operator>>( istream& is, Foo& foo ); // could throw
=20
int main() {
ifstream file( "file.txt" );
Foo foo;
int i =3D 0;
try {
while ( file >> foo ) {
//process foo;
++i;
}
}
catch ( exception& e ) {=20
cout << "error at: " << i << '\n';
}
}
=20
The problem I'm having is that op>> could throw. If it does, I don't=

=20

want to process the foo object that threw, but I want the program to=

=20

report an error and continue extracting foo objects.
=20
I could make op>> a no-throw and give Foo some sort of error or inval=

id=20

state, but that doesn't feel right. I can't report the error inside t=

he=20

op>> because I don't have enough information to make a full report.
=20
Does anyone have a better idea, or do I give Foo and error state and=

=20

query it after the read?

=20
Something like this perhaps?
=20
int main() {
ifstream file( "file.txt" );
Foo foo;
int i =3D 0;
while ( file.eof() =3D=3D false ) {
try {
file >> foo;
} catch ( exception& e )
cout << "error at: " << i << '\n';
continue;
}
++i;
}
}

=20
That doesn't handle the end of file correctly...
=20
I could do something like:
=20
typedef int Foo;
=20
int main() {
ifstream file( "file.txt" );
Foo foo;
int i =3D 0;
while ( file.eof() =3D=3D false ) {
try {
while ( file >> foo ) {
// process foo
++i;
}
} catch ( exception& e ) {
cout << "error at: " << i << '\n';
}
}
}
=20
But that seems strange.
=20
Does anyone have a different idea?

I don't really _like_ it, but this seems at least a bit less convoluted:
int i=3D1;
for(;;) {
try {=20
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=20
correctly to set the stream's fail bit to indicate the problem.=20
Processing this cleanly still isn't entirely trivial, but it's quite a=20
bit cleaner:
int i =3D 1;
do {=20
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=20
(i.e. checking for what went wrong when a stream is no longer good() and=20
reacting accordingly) is often necessary anyway. Of course, "reacting=20
accordingly" normally involves more than a completely cryptic error=20
message, but we'll leave that alone for now...
I think you could make a fair argument that errors in input are to be=20
expected sufficiently often that throwing an exception from operator>>=20
is never really justified.
--=20
Later,
Jerry.
The universe is a figment of its own imagination.
.


User: "James Kanze"

Title: Re: When operator>> can throw... 20 Jan 2008 04:15:30 AM
On Jan 19, 6:31 pm, Erik Wikstr=F6m <Erik-wikst...@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 =3D 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 invalid
state, but that doesn't feel right. I can't report the error inside the
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 =3D 0;
while ( file.eof() =3D=3D false ) {
try {
file >> foo;
} catch ( exception& e )
cout << "error at: " << i << '\n';
continue;
}
++i;
}
}

That's almost certainly wrong. It doesn't handle EOF correctly.
(Of course, his original code didn't handle EOF at all.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34
.



  Page 1 of 1

1

 


Related Articles
Format of compiler generated derived destructor when base has 'virtual ~base() throw():"
throw specifiers only when debugging
Any idea why do this program crash when I throw derived object as shown ?
Optimisation problems when mixing asm with C++
Compiler warning when casting from a pointer to an integer
Error when creating class reference to an instance of itself
Visual selection on TListView component goes away when focus changes: C++ Builder
unresolved external when using templates
Strange linking behavior when overriding global new and malloc
When can I have my templated typedefs?
thread lockup when comiling with optimizations.
linkage error when initializing static member array
Compilation problem when upgrading from g++ 3.3 to g++ 3.4
0D after 0A in hex when writing a binary file
when to use uint? dis/advantages?
 

NEWER

pg.1232     pg.940     pg.716     pg.544     pg.412     pg.311     pg.234     pg.175     pg.130     pg.96     pg.70     pg.50     pg.35     pg.24     pg.16     pg.10     pg.6     pg.3     pg.1

OLDER