
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