Topic: Consider an open throw-specification ?
Author: "ThosRTanner" <ttanner2@bloomberg.net>
Date: Mon, 6 Feb 2006 10:04:24 CST Raw View
Martin Bonner wrote:
> Francis Glassborow wrote:
> > In article <nPXzf.20888$iQ.19653@tornado.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).
But the run-time checking we have now is so unbelievably dangerous (and
to some extent inefficient). TBH I'd accept having to write that with a
try/catch embedded in it to keep the compiler quiet and have the safety
of compile time checks instead.
Thus
double hypot(int a, int b) throw()
{
try { return std::sqrt((double) a * a + (double) b * b); }
catch (...) { abort(); }
}
The runtime overhead is going to be pretty minimal, though the compiler
might decide it won't inline it.
> 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).
That would work too :-)
A couple of other suggestions to go in with compile time exception
specification checking:
1) destructors be implictly throw()
2) extern "C" be implicitly throw() - I realise that last one might be
even more contentious, but I believe it to be unlikely to cause issues
with existing code:
a) C code can't throw exceptions
b) If you throw an exception back through C code, it has no way of
recovering its state, so it's a pretty dangerous thing to do.
c) It would be to a nightmare to add the necessary syntax to existing C
headers
and optionally
d) this declaration is often used for interfaces to other languages,
which could behave even worse if you threw an exception at them
I'd certainly welcome a change, but throw(A, B, ...) doesn't give
anything to the client of the interface that a comment wouldn't give.
And it doesn't really help the compiler any.
---
[ 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 ]
Author: ux9i@yahoo.com (Max Polk)
Date: Fri, 20 Jan 2006 04:33:40 GMT Raw View
> terminatorul@gmail.com (Timothy Madden) writes:
>>and still have your library tell you what exceptions it may throw at you.
David Abrahams replied:
> The proper tool for that job goes by two names:
>
> 1. "Comment"
> 2. "Documentation"
Throw specifications are almost useless.
If you don't exhaustively research every method call your function makes, and
every call they make, recursively, you can't know that your throw
specification is including enough things to prevent unexpected program
termination due to a violation.
Deriving from standard library exception classes doesn't help at all.
Catching a standard exception base class at some high level won't stop a
violation occurring at some mid-level function with a throw specification
listing a few specific exceptions, when during maintenance some low-level
function is changed to let another kind of exception slip by.
The modification to the low-level function is examined, and the modifier sees
the standard exception base class being caught at the high level. They feel
safe adding a new kind of standard exception.
The problem was that they didn't exhaustively research everything in between.
The kind of exhaustive research and call trace analysis is way too
time-consuming. For the more than 70% of programmers doing in-house
development, they can't justify that kind of costly habit.
So that drives programmers to not use throw specifications anywhere, and to
only document in comments what something can throw. At that point having a
throw specification in the language isn't helping you at all.
Throw specifications are almost useless because it's too costly to use them
and we therefore might as well not even have that language feature.
This thread started from someone who wanted some sort of middle ground. The
all-or-none approach into which many of us are forced makes us envious of what
looks like a really neat language feature.
It sounded like the thread originator wanted to use the throw specification to
list what exceptions the current method will ADD, without having to be
bothered performing the exhaustive research doing call trace analysis.
Everybody contributed brilliantly with insightful remarks soundly defeating
that concept completely. Well, congratulations. Now we are back to an
almost-useless language feature, and the daring folks who suggested change
have been silenced. Are we all happy again?
I for one welcome a change!
---
[ 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 ]
Author: dave@boost-consulting.com (David Abrahams)
Date: Fri, 20 Jan 2006 06:00:09 GMT Raw View
ux9i@yahoo.com (Max Polk) writes:
>> terminatorul@gmail.com (Timothy Madden) writes:
>>>and still have your library tell you what exceptions it may throw at you.
>
> David Abrahams replied:
>> The proper tool for that job goes by two names:
>> 1. "Comment"
>> 2. "Documentation"
>
> Throw specifications are almost useless.
>
> If you don't exhaustively research every method call your function makes, and
> every call they make, recursively, you can't know that your throw
> specification is including enough things to prevent unexpected program
> termination due to a violation.
>
> Deriving from standard library exception classes doesn't help at all.
>
> Catching a standard exception base class at some high level won't stop a
> violation occurring at some mid-level function with a throw specification
> listing a few specific exceptions, when during maintenance some low-level
> function is changed to let another kind of exception slip by.
And perhaps more importantly, it doesn't prevent the loss of most of
the same exception info that is lost with catch(...). The standard
exception class doesn't tell you anything about the derived class. If
the real derived exception type doesn't matter to you, why bother with
all the checking?
..
> Throw specifications are almost useless because it's too costly to
> use them and we therefore might as well not even have that language
> feature.
They're also almost useless because, danger aside, they don't do what
we want. Nobody can make good use of a runtime check for a condition
that is likely never to be triggered and is thus untestable.
> This thread started from someone who wanted some sort of middle
> ground. The all-or-none approach into which many of us are forced
> makes us envious of what looks like a really neat language feature.
>
> It sounded like the thread originator wanted to use the throw specification to
> list what exceptions the current method will ADD, without having to be
> bothered performing the exhaustive research doing call trace analysis.
>
> Everybody contributed brilliantly with insightful remarks soundly defeating
> that concept completely. Well, congratulations. Now we are back to an
> almost-useless language feature, and the daring folks who suggested change
> have been silenced.
How would the daring change give us anything we couldn't get from a
comment?
> Are we all happy again?
Again? I've never been happy with exception specifications.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
---
[ 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 ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Fri, 20 Jan 2006 15:53:20 GMT Raw View
In article <nPXzf.20888$iQ.19653@tornado.southeast.rr.com>, Max Polk
<ux9i@yahoo.com> writes
>Everybody contributed brilliantly with insightful remarks soundly
>defeating that concept completely. Well, congratulations. Now we are
>back to an almost-useless language feature, and the daring folks who
>suggested change have been silenced. Are we all happy again?
>
>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.
Actually, I think, compilers or a code analysis tool could do that
itself given access to all the code. We could even (if compilers marked
functions that explicitly throw) pass this task on to the linker.
Quite a few of the ideas that might improve optimisation can be done be
having a compiler annotate the generated object code with such things as
'pure' (i.e. free of side effects). That last piece of information is
actually very useful when generating executables for
multi-core/multi-processor systems.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ 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 ]
Author: "Bob Bell" <belvis@pacbell.net>
Date: Fri, 20 Jan 2006 16:48:14 CST Raw View
Max Polk wrote:
> > terminatorul@gmail.com (Timothy Madden) writes:
> >>and still have your library tell you what exceptions it may throw at you.
>
> David Abrahams replied:
> > The proper tool for that job goes by two names:
> >
> > 1. "Comment"
> > 2. "Documentation"
>
> Throw specifications are almost useless.
I agree; were I to quibble it might be with the use of the word
"almost."
[snip]
> It sounded like the thread originator wanted to use the throw specification to
> list what exceptions the current method will ADD, without having to be
> bothered performing the exhaustive research doing call trace analysis.
>
> Everybody contributed brilliantly with insightful remarks soundly defeating
> that concept completely.
This is a misleading characterization of the thread so far. For myself,
I have asked three times so far for a description of the problem(s)
solved by the OP's suggestion. So far, he hasn't done so. If there are
no problems solved by the new feature, what is the point?
> I for one welcome a change!
I welcome change, too, if the change can be shown to make the language
better. If you or the OP can give a concrete reason why this feature
improves the language, I'm willing to listen. So far, I haven't heard
anything that makes me believe that this feature adds anything to the
language that isn't already there. However, on the off chance that I'm
missing something, I've been asking the OP for more information. What
gains can be made with this feature? So far I'm not convinced, because
I don't see any gain over simply not using exception specifications at
all.
Perhaps, since you seem to support this feature, you can explain what
the gains are. Honestly, I'd love to be proven wrong; exception
specifications suck. If something could be done to make them suck less,
I'd be very interested.
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 ]
Author: terminatorul@gmail.com (Timothy Madden)
Date: Mon, 23 Jan 2006 23:46:32 GMT Raw View
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.
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.
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, ...)
?
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.
Timothy Madden
Romania
---
[ 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 ]
Author: "Earl Purple" <earlpurple@gmail.com>
Date: Tue, 24 Jan 2006 09:43:03 CST Raw View
Timothy Madden wrote:
> 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?
> 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.
> 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 ]
Author: "Bob Bell" <belvis@pacbell.net>
Date: Tue, 24 Jan 2006 09:56:28 CST Raw View
Timothy Madden wrote:
> 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?
> 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(...)"?
> 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.
> 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.
> 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 ]
Author: "Martin Bonner" <martinfrompi@yahoo.co.uk>
Date: Tue, 24 Jan 2006 12:15:51 CST Raw View
Francis Glassborow wrote:
> In article <nPXzf.20888$iQ.19653@tornado.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 ]
Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Mon, 16 Jan 2006 00:01:58 GMT Raw View
Timothy Madden wrote:
> It also allows access violation erros to be catched with
> catch (...)
> and still have your library tell you what exceptions it may throw at you.
Access violation errors are not required to throw C++ exceptions so they
can *not* portably be caught with catch(...). I guess you are referring
to a specific implementation when this can be done (VC++, maybe?) but
this cannot be a valid C++ argument in general.
> Many times programmers leave out throw-specifications because a
> throw-specification requires the programmer to go through the call graph
> for the function to find the set of all possible exceptions that could
> get thrown. I can't say anyone is to blame when trying to avoid this
> procedure.
Many more times programmers leave out throw-specification simply because
they are useless if not even considered harmful. Have a look here
http://www.gotw.ca/gotw/082.htm and here
http://www.gotw.ca/publications/mill22.htm.
> With such an open throw-specification the programmer only has to say
> what exceptions it throws by itself, or from its own library, and let
> other software pluged into its code do what it knows to do.
I disagree. This relaxation make things even worse than they are now.
But that's just my opinion.
Ganesh
---
[ 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 ]
Author: "Bob Bell" <belvis@pacbell.net>
Date: Sun, 15 Jan 2006 18:01:37 CST Raw View
Timothy Madden wrote:
> Bob Bell wrote:
> > Timothy Madden wrote:
> >
> >>Has anyone thought about a throw-specification:
> >>
> >>void Processor() throw (std::runtime_error, CException, ...)
> >>
> >>with meaning 'the function Processor can throw std::runtime_error and
> >>CException in certain cases, and can also throw anything else it may
> >>happen to throw' ?
> >
> > Can you say something about what problems this feature solves? I can't
> > think of any off hand.
> >
>
> It helps when you write a library or some extensible modules.
> Think of a library that does what it does until something special
> happens and then library has to call an user-defined function.
> Or an extensible library might need to call used-defined functions as
> part of its normal operations. In this case user surely knows it has to
> catch library exceptions and his/her own exceptions.
Doesn't the user know that anyway?
I'm sorry, I'm just not getting it. I don't see what this feature lets
you do that can't be done today (or that can be done today but
demonstrably needs improvement).
> Another case is a library build upon a library missing
> throw-specifications. For example my graphic library uses a third-party
> .dll for data compression, and graphic library is build with verision
> 1.5 of compression .dll, but allways uses the latest installed version
> found on user machine. Compression .dll in version 1.5 merely throws
> std::bad_alloc but in version 1.6 it throws 9 other types of exeptions.
How does throw (X, ...) make this simpler?
> In general it helps writing an iterface with functions that explicitly
> throw exceptions local to the interface, but also throw exceptions from
> various interface implementors.
>
> It also allows access violation erros to be catched with
> catch (...)
> and still have your library tell you what exceptions it may throw at you.
Keep in mind that the standard says nothing about access violations
triggering exceptions.
> And I am not only talking about real libraries and interfaces. Software
> projects are often diveded into tasks developed by separate teams, and
> final executable is build much like it would use many libraries. In such
> cases an extesible and open interface between modules can really help.
How? I don't see how
void F() throw (X, ...);
improves on
void F() throw (X, Y, Z);
or
void F();
> Many times programmers leave out throw-specifications because a
> throw-specification requires the programmer to go through the call graph
> for the function to find the set of all possible exceptions that could
> get thrown. I can't say anyone is to blame when trying to avoid this
> procedure.
You can count me as one of those whom you wouldn't blame, then; throw
specifications seem to be pretty useless (IMHO), and you couldn't pay
me to use them (well, I suppose you could; fortunately for me, my
current employer doesn't. ;-) )
> With such an open throw-specification the programmer only has to say
> what exceptions it throws by itself, or from its own library, and let
> other software pluged into its code do what it knows to do.
Consider this function:
void F() throw (X, ...)
{
G();
if (/* ... */)
throw X();
}
Is your proposal aimed at making F() less likely to invoke
std::unexpected()? Because I can make it so that it's not less likely,
I can guarantee that it won't:
void F()
{
G();
if (/* ... */)
throw X();
}
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 ]
Author: Timothy Madden <terminatorul@gmail.com>
Date: Mon, 16 Jan 2006 10:46:43 CST Raw View
===================================== MODERATOR'S COMMENT:
Please do not quote more of past messages than is necessary to provide context
for your reply.
---
Steve Clamage, stephen.clamage@sun.com
===================================== END OF MODERATOR'S COMMENT
Bob Bell wrote:
> Timothy Madden wrote:
>
>>Bob Bell wrote:
>>
>>>Timothy Madden wrote:
>>>
[...]
>>>>void Processor() throw (std::runtime_error, CException, ...)
>>>>
>>>>with meaning 'the function Processor can throw std::runtime_error and
>>>>CException in certain cases, and can also throw anything else it may
>>>>happen to throw' ?
>>>
[...]
>>It helps when you write a library or some extensible modules.
>>Think of a library that does what it does until something special
>>happens and then library has to call an user-defined function.
>>Or an extensible library might need to call used-defined functions as
>>part of its normal operations. In this case user surely knows it has to
>>catch library exceptions and his/her own exceptions.
>
>
> Doesn't the user know that anyway?
[...]
>
>>Another case is a library build upon a library missing
>>throw-specifications. For example my graphic library uses a third-party
>>.dll for data compression, and graphic library is build with verision
>>1.5 of compression .dll, but allways uses the latest installed version
>>found on user machine. Compression .dll in version 1.5 merely throws
>>std::bad_alloc but in version 1.6 it throws 9 other types of exeptions.
>
>
> How does throw (X, ...) make this simpler?
>
>
>>In general it helps writing an iterface with functions that explicitly
>>throw exceptions local to the interface, but also throw exceptions from
>>various interface implementors.
>>
>>It also allows access violation erros to be catched with
>> catch (...)
>>and still have your library tell you what exceptions it may throw at you.
>
>
> Keep in mind that the standard says nothing about access violations
> triggering exceptions.
>
>
[...]
>
>
> How? I don't see how
>
> void F() throw (X, ...);
>
> improves on
>
> void F() throw (X, Y, Z);
>
> or
>
> void F();
>
>
>>Many times programmers leave out throw-specifications because a
>>throw-specification requires the programmer to go through the call graph
>>for the function to find the set of all possible exceptions that could
>>get thrown. I can't say anyone is to blame when trying to avoid this
>>procedure.
>
>
> You can count me as one of those whom you wouldn't blame, then; throw
> specifications seem to be pretty useless (IMHO), and you couldn't pay
> me to use them (well, I suppose you could; fortunately for me, my
> current employer doesn't. ;-) )
[...]
>
> Consider this function:
>
> void F() throw (X, ...)
> {
> G();
> if (/* ... */)
> throw X();
> }
>
> Is your proposal aimed at making F() less likely to invoke
> std::unexpected()? Because I can make it so that it's not less likely,
> I can guarantee that it won't:
>
> void F()
> {
> G();
> if (/* ... */)
> throw X();
> }
>
What I mean is the set of possible exceptions thrown from a library is
open. It is not completly determined at compile-time, because
underlaying used libraries may change version or may change implementor
at run-time. Or because the library may easily call user-defined code,
for which I don't want or I can't impose my throw-specifications. Or it
may happen that underlaying library code uses functions missing
throw-specifications.
Or of course my own design may change just a little during development
if I descover a new error case.
So if the set of exceptions is open, I think syntax for
exception-specifications might allow a programer to define such an open set.
How should I write a library that calls user-defined callback function
void (*OnDeviceShutdow)(int iCause);
and that also throws any DeviceException-derived exceptions ?
OnDeviceShutdwon can throw anything user needs to throw, and my library
will let the exception go through all its code, back into user code
where it can be caught. So formaly at the interface level, the library
actualy throws whatever OnDeviceShutdown throws. However I would like
the language syntax to let user know I for myself will only throw with
some DeviceException-derived objects.
The other example is with the graphics library. My user writes
graphics.dll and for that it buys compression.dll v1.5 from me. I want
to write commpresion.dll v1.5 and to be nice I state what it will throw.
As a seriuos implementer I offer to my client the guarantee that futre
compression.dll v1.6, until commpression.dll v3.0, will all be 100%
compatible with commpresion.dll v1.5. Ideealy graphics.dll only needs to
check at runtime if commpresion.dll version is greated then or equal
with v1.5
At the present time I write the C++ interface exposed by commpresion
v1.5, with all it can throw, but I want to let some provisions in the
interface for some kind of errors that will appear in v2.0, for which I
will need a new exception class.
To answer another question,
void F() throw(X, ...)
could be better then
void F()
in that the former informs the user whatever I throw something other
then X (and maybe X-derived) somehow I do not throw it by myself and
exception comes from some code not actualy in my library or maybe not
actualy known at compile-time. It also tells the user that I for one am
perfectly capable of throwing X objects and there are cases when I do,
and user shoud do well and try to catch ( X ) in its code.
I don't know how you see this ideea, but for me it's all about open
interfaces and flexibility.
Thank you
Timothy Madden
Romania
---
[ 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 ]
Author: brok@rubikon.pl (Bronek Kozicki)
Date: Tue, 17 Jan 2006 04:29:58 GMT Raw View
Timothy Madden wrote:
> What I mean is the set of possible exceptions thrown from a library is
> open.
it is always open, if you do not use throw specification. Library
function that calls user code should not have throw specification in the
first place (and indeed this is how algorithms in C++ Standard Library
are defined). There does not seem to be anything wrong with it. What is
the problem that you are trying to solve?
B.
---
[ 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 ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Tue, 17 Jan 2006 04:32:17 GMT Raw View
In article <43cb845a$0$15781$14726298@news.sunsite.dk>, Timothy Madden
<terminatorul@gmail.com> writes
>To answer another question,
>void F() throw(X, ...)
>
>could be better then
>void F()
>in that the former informs the user whatever I throw something other
>then X (and maybe X-derived) somehow I do not throw it by myself and
>exception comes from some code not actualy in my library or maybe not
>actualy known at compile-time. It also tells the user that I for one am
>perfectly capable of throwing X objects and there are cases when I do,
>and user shoud do well and try to catch ( X ) in its code.
I think you completely miss what a programming language such as C++ is
designed for; it is to allow humans to communicate to computers. Things
we want to communicate to humans and which the compiler cannot make
constructive use of belong in comments.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ 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 ]
Author: brok@rubikon.pl (Bronek Kozicki)
Date: Tue, 17 Jan 2006 04:31:51 GMT Raw View
Timothy Madden wrote:
> What I mean is the set of possible exceptions thrown from a library is
> open.
it is always open, if you do not use throw specification. Library
function that calls user code should not have throw specification in the
first place (and indeed this is how algorithms in C++ Standard Library
are defined). There does not seem to be anything wrong with it. What is
the problem that you are trying to solve?
B.
---
[ 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 ]
Author: "Bob Bell" <belvis@pacbell.net>
Date: Wed, 18 Jan 2006 13:45:14 CST Raw View
Timothy Madden wrote:
[snip]
When asked for justification for this feature, you give examples of
what you _could_ do if the feature were present. What's missing is
_why_ you need to do them. The only thing I've seen so far is that
void F() throw (X, ...);
tells me that F() might throw an X directly, but functions called by
F() might throw anything (including, I imagine, an X). _Why_ do I need
to know that?
>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. Do you then declare it as
void F() throw(X, Y, ...);
If you do, doesn't the program continue to work exactly as it did
before?
> To answer another question,
> void F() throw(X, ...)
>
> could be better then
> void F()
> in that the former informs the user whatever I throw something other
> then X (and maybe X-derived) somehow I do not throw it by myself and
> exception comes from some code not actualy in my library or maybe not
> actualy known at compile-time. It also tells the user that I for one am
> perfectly capable of throwing X objects and there are cases when I do,
> and user shoud do well and try to catch ( X ) in its code.
However, it doesn't tell me that _every_ X that is emitted from F()
came directly from F(). There's no reason to believe that some function
called by F can't or won't throw an X.
Again, I don't understand why it's important to know that an X (as
opposed to anything else) might come from F().
> I don't know how you see this ideea, but for me it's all about open
> interfaces and flexibility.
Let me ask it this way: why is
void F() throw (X, ...);
better than
// F() can throw, among other things, an X.
void F();
They are both equally open and flexible. I don't see what the gain is
that justifies a language change such as this.
Perhaps you should rethink your idea. IMHO, you need to present a real
problem with the way the language is defined today -- so far you
haven't done that -- and then show how your proposal solves that
problem. Continuing to assert a desire for things that are already
attainable in the language today isn't enough, I'm afraid.
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 ]
Author: Timothy Madden <terminatorul@gmail.com>
Date: Fri, 13 Jan 2006 17:28:45 CST Raw View
------=_Part_12223_28101219.1137192549797
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline
Has anyone thought about a throw-specification:
void Processor() throw (std::runtime_error, CException, ...)
with meaning 'the function Processor can throw std::runtime_error and
CException in certain cases, and can also throw anything else it may
happen to throw' ?
I think it would be an excelent feature.
Of course I can't write the function Processor() above and explicitly
throw std::bad_alloc;
in the function body. I can only explicitly throw std::runtime_error and
CException (if I need to).
But if I know of a previously declared function:
void g(int *pLevel) throw (std::bad_alloc);
that clearly throws when pLevel is NULL, it is still ok to directly call
g in Processor function body. If Processor() knows to only pass non-NULL
pointers to g() all is well. If it doesn't, std::bad_alloc may eventualy
get thrown from g(), and all is well too.
I would like to hear comments and suggestions about this.
I am still thinking if it is good to allow throwing CException-derived
classes, and if they should be thrown or catched by only base-class type
or complete type.
Timothy Madden
Romania
------=_Part_12223_28101219.1137192549797
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline
<br>
Has anyone thought about a throw-specification:<br>
<br>
void Processor() throw (std::runtime_error, CException, ...)<br>
<br>
with meaning 'the function Processor can throw std::runtime_error and <br>
CException in certain cases, and can also throw anything else it may <br>
happen to throw' ?<br>
<br>
I think it would be an excelent feature.<br>
<br>
Of course I can't write the function Processor() above and explicitly<br>
throw std::bad_alloc;<br>
in the function body. I can only explicitly throw std::runtime_error and <b=
r>
CException (if I need to).<br>
<br>
But if I know of a previously declared function:<br>
<br>
void g(int *pLevel) throw (std::bad_alloc);<br>
<br>
that clearly throws when pLevel is NULL, it is still ok to directly call<br=
>
g in Processor function body. If Processor() knows to only pass non-NULL <b=
r>
pointers to g() all is well. If it doesn't, std::bad_alloc may eventualy <b=
r>
get thrown from g(), and all is well too.<br>
<br>
I would like to hear comments and suggestions about this.<br>
<br>
I am still thinking if it is good to allow throwing CException-derived <br>
classes, and if they should be thrown or catched by only base-class type <b=
r>
or complete type.<br>
<br>
Timothy Madden<br>
Romania<br>
<br>
------=_Part_12223_28101219.1137192549797--
---
[ 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 ]
Author: invalid@bigfoot.com (Bob Hairgrove)
Date: Sat, 14 Jan 2006 00:13:34 GMT Raw View
On Fri, 13 Jan 2006 17:28:45 CST, Timothy Madden
<terminatorul@gmail.com> wrote:
>Has anyone thought about a throw-specification:
>
>void Processor() throw (std::runtime_error, CException, ...)
>
>with meaning 'the function Processor can throw std::runtime_error and
>CException in certain cases, and can also throw anything else it may
>happen to throw' ?
If it can throw anything at all, what's the use of a throw qualifier?
The things that can be thrown are a contract with the code calling the
function. IOW, if I have only "throw (std::runtime_error)" after the
function signature, code calling this function need only catch that
exception. If I open it up so that the function could throw anything,
that's just the same as leaving off the throw specification entirely.
>I think it would be an excellent feature.
Really?
>Of course I can't write the function Processor() above and explicitly
> throw std::bad_alloc;
>in the function body. I can only explicitly throw std::runtime_error and
>CException (if I need to).
You can throw anything you like as long as you can construct it, can't
you? That's the case today, even with the current state of affairs.
>But if I know of a previously declared function:
>
>void g(int *pLevel) throw (std::bad_alloc);
>
>that clearly throws when pLevel is NULL, it is still ok to directly call
>g in Processor function body. If Processor() knows to only pass non-NULL
>pointers to g() all is well. If it doesn't, std::bad_alloc may eventualy
>get thrown from g(), and all is well too.
>
>I would like to hear comments and suggestions about this.
>
>I am still thinking if it is good to allow throwing CException-derived
>classes, and if they should be thrown or catched by only base-class type
>or complete type.
What is "CException"?
>Timothy Madden
>Romania
--
Bob Hairgrove
NoSpamPlease@Home.com
---
[ 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 ]
Author: "Bob Bell" <belvis@pacbell.net>
Date: Fri, 13 Jan 2006 18:26:42 CST Raw View
Timothy Madden wrote:
> Has anyone thought about a throw-specification:
>
> void Processor() throw (std::runtime_error, CException, ...)
>
> with meaning 'the function Processor can throw std::runtime_error and
> CException in certain cases, and can also throw anything else it may
> happen to throw' ?
>
> I think it would be an excelent feature.
Can you say something about what problems this feature solves? I can't
think of any off hand.
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 ]
Author: terminatorul@gmail.com (Timothy Madden)
Date: Sat, 14 Jan 2006 02:10:22 GMT Raw View
Bob Bell wrote:
> Timothy Madden wrote:
>
>>Has anyone thought about a throw-specification:
>>
>>void Processor() throw (std::runtime_error, CException, ...)
>>
>>with meaning 'the function Processor can throw std::runtime_error and
>>CException in certain cases, and can also throw anything else it may
>>happen to throw' ?
>
> Can you say something about what problems this feature solves? I can't
> think of any off hand.
>
It helps when you write a library or some extensible modules.
Think of a library that does what it does until something special
happens and then library has to call an user-defined function.
Or an extensible library might need to call used-defined functions as
part of its normal operations. In this case user surely knows it has to
catch library exceptions and his/her own exceptions.
Another case is a library build upon a library missing
throw-specifications. For example my graphic library uses a third-party
.dll for data compression, and graphic library is build with verision
1.5 of compression .dll, but allways uses the latest installed version
found on user machine. Compression .dll in version 1.5 merely throws
std::bad_alloc but in version 1.6 it throws 9 other types of exeptions.
In general it helps writing an iterface with functions that explicitly
throw exceptions local to the interface, but also throw exceptions from
various interface implementors.
It also allows access violation erros to be catched with
catch (...)
and still have your library tell you what exceptions it may throw at you.
And I am not only talking about real libraries and interfaces. Software
projects are often diveded into tasks developed by separate teams, and
final executable is build much like it would use many libraries. In such
cases an extesible and open interface between modules can really help.
Many times programmers leave out throw-specifications because a
throw-specification requires the programmer to go through the call graph
for the function to find the set of all possible exceptions that could
get thrown. I can't say anyone is to blame when trying to avoid this
procedure.
With such an open throw-specification the programmer only has to say
what exceptions it throws by itself, or from its own library, and let
other software pluged into its code do what it knows to do.
Timothy Madden
Romania
---
[ 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 ]
Author: dave@boost-consulting.com (David Abrahams)
Date: Sat, 14 Jan 2006 15:59:03 GMT Raw View
terminatorul@gmail.com (Timothy Madden) writes:
> Bob Bell wrote:
>> Timothy Madden wrote:
>>
>>>Has anyone thought about a throw-specification:
>>>
>>>void Processor() throw (std::runtime_error, CException, ...)
>>>
>>>with meaning 'the function Processor can throw std::runtime_error and
>>>CException in certain cases, and can also throw anything else it may
>>>happen to throw' ?
>> Can you say something about what problems this feature solves? I
>> can't
>> think of any off hand.
>>
..
> It also allows access violation erros to be catched with
> catch (...)
Not in portable C++
> and still have your library tell you what exceptions it may throw at you.
The proper tool for that job goes by two names:
1. "Comment"
2. "Documentation"
> And I am not only talking about real libraries and
> interfaces. Software projects are often diveded into tasks developed
> by separate teams, and final executable is build much like it would
> use many libraries. In such cases an extesible and open interface
> between modules can really help.
>
> Many times programmers leave out throw-specifications because a
> throw-specification requires the programmer to go through the call
> graph for the function to find the set of all possible exceptions that
> could get thrown. I can't say anyone is to blame when trying to avoid
> this procedure.
There are much better reasons not to use (non-empty) exception
specifications. Your version of the feature nullifies most of those
reasons, but since it is functionally equivalent to a comment, I don't
think it's worth adding a language feature for.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
---
[ 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 ]