Boost logo

Boost :

From: Geoff Leyland (gley001_at_[hidden])
Date: 2004-02-09 22:34:02


On 10/02/2004, at 2:36 PM, Jonathan Turkanis wrote:

> Are you proposing a single new exception which overloads operator<<,
> for use in testing, or are you thinking of using it as a framework for
> user-define exceptions in situations where the programmer judges that
> low resources will not be a problem?

Well, I have a use case in which it helps me, which I explained in the
last post - and I can explain further if you like - and perhaps there
are others.

I think that for testing and correctness Boost.Test type things and and
assertions are the right tools.

I guess I am using it in a case:
   where I judge that low resources will not be a problem;
   where, if an another exception occurs in generating the exception,
well, bummer;
   where it's not worth spending time on a nicer mechanism;
   where I would like a semi-explanatory error message to be printed on
the console or saved;
   where I do want the option of continuing with something (the next
test), but I'm not really interested in rectifying the error.

In my particular case, as I said, the errors usually come from the user
not getting an input file quite right (parseable, but not containing
all the information I later need)

On 10/02/2004, at 2:54 PM, Reece Dunn wrote:

> Using a stringstream would be my approach to achieve this affect, but
> I wonder what would happen if the stream operation generated an
> exception? E.g.
>
> throw( std::ostringstream() << "Error #" << 404 << weberror( 404 ));

I'm actually using it to replace the case where, lazy as I am, I
couldn't be bothered creating a new exception class, and just threw a
char *:

throw "Couldn't open the file";

Which is certainly exception safe, and very mindful of limited
resources, but when you're trying to open about 20 user specified files
and dlls, not very informative. So

throw streamy_exception() << "Couldn't open the file '" << file_name <<
"'";

is a world better for me. Yes, it uses lots of resources. Yes, the
exception constructor and subsequent streaming could throw, but my
experience has shown that the biggest danger is neither of these. What
goes wrong is that I'm too lazy to write a really nice exception for
every case, and so uninformative exceptions are thrown.

> what if weberror thows an exception? Also, is ostringstream guaranteed
> not to throw an exception?

What about

throw spiffy_web_exception(404, weberror(404));

It's not much different is it? You could call weberror() in the
exception's what(), inside a try block, but if it did throw, what would
you do?

throw spiffy_web_error(404);

then

virtual const char *spiffy_web_error::throw(void) const throw()
{
   static std::string temp;
   try
   {
     std::ostringstream os;
     os << "Error #" << error_number << weberror( error_number );
     temp = os.str();
     return temp.c_str();
   }
   catch (...)
   {
     return "spiffy_web_error : couldn't work out what happened, sorry"
   }
}

The message in the final case doesn't give much useful information.
Also, you can see in order to get a char * that will live beyond the
scope of what you have to either:
   have something like a static temporary string-type thing lying around
or strcpy os.str into some newed memory;
   make the ostringstream a member of the exception - and so have it
constructed at the time you throw it - risking the double exception
again;
   have a better idea?

and also shows why sometimes it might, just might, be easier to go:

std::cerr << s;

rather than

std::cerr << s.what();

> Throwing an exception during the exception process is not a good idea!

It's not that bad - the program exits without giving a clear indication
of what went wrong. If the alternative is to have the program exit
without giving a clear indication of what went wrong, then that's
probably ok.

I do agree that you could throw an ostringstream though. The
advantages I see of throwing an exception I see are

You get to overload what().

You can extend the exception : throw streamy_web_error(404) << "Error
#" << 404 << weberror( 404 );
(You could potentially disable the streamy part (make "<<" do nothing),
  and end up throwing an exception that spat out a readable error in a
command line version, an exception containing just the error code and
type information in (say) a windows version, and, to some extent, get
some free documentation at the point of the error.)

I'm also imagining that by using the format library and some kind of
translation tool, you could probably fairly easily get translated
versions of the text of your exception. I haven't played with the
format library that much though.

I'm certainly not advocating that everyone who uses exceptions should
use such an exception. Those who can do better certainly should. Nor
am I advocating that Boost libraries should throw such exceptions : I
think it would be a very bad idea for Boost to put all that stream
overhead into libraries that don't need it or to throw exceptions in
english.

However, if there are other people like me who write

throw "oops. Something went wrong";

or even

throw 1;

in their own code, as I often did in the last days of my thesis, then
maybe such a facility will help them a bit. Of course they could write
such an exception themselves, but there are one or two tricks : you
really do get problems if you try to return os.str.c_str() to an
ostringstream in what()'s scope.

cheers,
Geoff


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk