C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Re: Consider an open throw-specification ?

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards
View previous topic :: View next topic  
Author Message
Earl Purple
Guest





PostPosted: Tue Jan 24, 2006 3:43 pm    Post subject: Re: Consider an open throw-specification ? Reply with quote




Timothy Madden wrote:

Quote:
Think of this function:

// F only throws X plus whatever gets thrown from your callback
void F(void (*fnCallback)(void) = NULL) throw (X, ...)

The elipsis are there for the compiler to allow std::bad_alloc be thrown
at run-time from *fnCallback, but only allow 'throw X()' in F body at
compile time.

The ideea is the compiler knows that any exceptions can be thrown from
fnCallback, but user knows exactly what exceptions really are thrown
from fnCallback and knows what to catch. User needs to call F several
times, each time with a different fnCallback function, and each time
with different exception handlers.

So comment what exceptions F might throw, and I will catch them along
with those of the callback I pass.

Does the compiler have to know anything?

Quote:
Let me be the one to ask you this question:
Why is
void F(void (*fnCallback)(void) = NULL)
better than
void F(void (*fnCallback)(void) = NULL) throw (X, ...)
?

Why is the second one better? I can catch X but then still have to
handle the ...
The advantage of a non-empty exception specification is that you are
promising your function won't throw anything else, so I can safely set
up an exception handler for just your exception type and not worry. But
as has been proven with time, they actually lead to more problems than
they gain and apart from the empty specification, they are not really
worth it to the language.

Quote:
Also please do not leave in the cold implementations which have the
privilege to catch access violation errors at run-time as some unknown
exception type. For them, it is helpfull if I could write exception
specifications and still have the catch (...) handler usefull.

If you are talking about std::range_error which can be caught using
at() for vector or string, then it is only your throw specification
that is leaving them in the cold. If you don't have an exception
specification then std::range_error can be caught like any other.

Unchecked access violations lead to undefined behaviour, not
exceptions. If you are writing good code then 99.999% of the time
(actually should be 100% of the time) your indices are not out of range
and it is wasteful to check them in what might be performance-critical
code.

The only time you would want to be checking ranges would be from
runtime information input from outside the program, eg user input, file
I/O etc, where an index of some table could conceivably be out of
range, and then on such an occasion, you would want to trap the error
and throw the exception (I generally use std::invalid_argument most of
the time for this kind of thing. One exception, we all know what to
catch), but in a way such that the user can understand and fix the
problem. (You might terminate the program, you might log the error and
continue, you might put a dialog box up on a GUI app - how your program
handles the exception will depend on circumstances).

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
Bob Bell
Guest





PostPosted: Tue Jan 24, 2006 3:56 pm    Post subject: Re: Consider an open throw-specification ? Reply with quote



Timothy Madden wrote:
Quote:
Bob Bell wrote:
Timothy Madden wrote:
[...]
void F() throw (X, ...);

From the point of view of a user of F(), does it really matter whether
an exception comes from code in F() itself as opposed to code called
from F()? I don't see how that knowledge helps me write better code. I
don't see what advantage that has if F() evolves such that it can also
throw a Y. [...]

Think of this function:

// F only throws X plus whatever gets thrown from your callback
void F(void (*fnCallback)(void) = NULL) throw (X, ...)

The elipsis are there for the compiler to allow std::bad_alloc be thrown
at run-time from *fnCallback, but only allow 'throw X()' in F body at
compile time.

I think maybe you missed the point of the question. How does knowing
that F() has code within it that might directly throw an X help me use
F() more effectively?

Are you suggesting that the following would be ill-formed?

void F(void (*fnCallback)(void) = NULL) throw (X, ...)
{
throw Y();
}

Assuming that this code would be ill-formed, how is that useful?
Doesn't a caller of F() have to be prepared to catch a Y? If so, why
shouldn't F() be allowed to throw a Y directly?

Quote:
The ideea is the compiler knows that any exceptions can be thrown from
fnCallback, but user knows exactly what exceptions really are thrown
from fnCallback and knows what to catch.

void F(void (*fnCallback)(void) = NULL) throw (X, ...)
{
if (/* ... */)
throw X(); // here's our X

PreCallback();

if (fnCallback != 0)
fnCallback();
}

void PreCallback()
{
if (/* ... */)
throw Y();
if (/* ... */)
throw X();
// ...
}

Now F() can throw both X and Y, as well as whatever exceptions the
callbacks throw. The X may or may not come from F() directly. The user
may know that none of his callbacks can throw a Y, but he still needs
to be prepared to catch a Y. So again, how does "void F (...) throw(X,
..)" help me use F() more effectively than "void F(...)"?

Quote:
User needs to call F several
times, each time with a different fnCallback function, and each time
with different exception handlers.

So again, what problem are you solving that can't be solved by

// F only throws X plus whatever gets thrown from your callback
void F(void (*fnCallback)(void) = NULL);

You're still telling me _what_ you can do; you're not telling me _why_
the existing language isn't able to solve the problem.

Quote:
Let me be the one to ask you this question:
Why is
void F(void (*fnCallback)(void) = NULL)
better than
void F(void (*fnCallback)(void) = NULL) throw (X, ...)

Because they are exactly equal in terms of expressiveness, yet the
former alternative doesn't require a change to the language, which is a
huge undertaking, perhaps measured in many man-years by the time the
standard is changed and the change is implemented by all compiler
vendors. All things being equal, not changing the language beats
changing the language every time.

Quote:
Also please do not leave in the cold implementations which have the
privilege to catch access violation errors at run-time as some unknown
exception type. For them, it is helpfull if I could write exception
specifications and still have the catch (...) handler usefull.

I'm afraid I don't know what this last paragraph means; access
violations don't get reported as exceptions -- except on certain broken
implementations of C++. If your idea is that your proposal makes such
an implementation less broken, can you explain how?

Bob

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
Martin Bonner
Guest





PostPosted: Tue Jan 24, 2006 6:15 pm    Post subject: Re: Consider an open throw-specification ? Reply with quote



Francis Glassborow wrote:
Quote:
In article <nPXzf.20888$iQ.19653 (AT) tornado (DOT) southeast.rr.com>, Max Polk
I for one welcome a change!

So am I. However the change I want is to remove throw specifications
entirely and just allow a 'nothrow' qualification to a function with the
added requirement that this be checked at compile time.

What about the following?

double hypot(int a, int b) throw()
{
return std:sqrt( (double)a*a + (double)b*b );
}

We can reasonably expect the compiler to know that std:sqrt can throw.
What we can't expect it to know, is that it only throws if it's
argument is negative, and that this function ensures that sqrt's
argument cannot be negative. (This is the original Bjarne Stroustrup
argument against compile time checking of throw specifications).

Actually, I think the solution is to label the expression that looks as
though it throws (perhaps with a throw_cast?) to say that the
programmer knows it can't throw (and of course, with undefined
behaviour if the expression /does/ throw).

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.