Topic: exception specifications
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1997/11/20 Raw View
Marc Sherman wrote:
>
> Perhaps we also need a throw_cast, which lets you explicitly change
> an exceptionspecification when you are certain that your input matches
> the preconditions that guarantee the new exception specification.
> Throwing an exception that was in the original specification but not
> the new one is undefined behaviour.
>
> void foo() throw(X,Y);
>
> void bar() throw(X,Z)
> {
> throw_cast<>(foo)(); // legal - undefined if foo throws an
> // X or a Y
> throw_cast<X>(foo)(); // legal - undefined if foo throws a Y
> throw_cast<X,Z>(foo)(); // illegal - throw_cast can only
> // narrow the exception spec
> }
Looks pretty elegant to me. But remember that this addition to the language
would only bee needed _if_ compilers made deductions about the coherency of
throw specs, and treated violations as errors. I, for one, are content that
they don't.
--
Ciao,
Paul
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Marc Sherman <marcsh@corel.ca>
Date: 1997/11/21 Raw View
> I wrote:
> >
> > Perhaps we also need a throw_cast, which lets you explicitly change
> > an exception specification when you are certain that your input matches
> > the preconditions that guarantee the new exception specification.
> > Throwing an exception that was in the original specification but not
> > the new one is undefined behaviour.
> > [example snipped]
Paul D. DeRocco wrote:
>
> Looks pretty elegant to me. But remember that this addition to the language
> would only bee needed _if_ compilers made deductions about the coherency of
> throw specs, and treated violations as errors. I, for one, are content that
> they don't.
Of course. Personally, I'd prefer to see the compiler emit a warning
when the throw-spec is (possibly) violated at compile-time. Since
warnings are outside the domain of the spec, places where you'd want to
use throw_cast could also be handled with a #pragma to disable the
warning in a block, if required. This warning could be implemented in a
compiler that conforms to last Friday's ISO spec, and would give you the
best of both worlds -- the compiler would warn you of possible runtime
errors, but would still accept the code as valid.
- Marc
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Anatoli <REMOVETHISanatoli@ptc.com>
Date: 1997/11/12 Raw View
kjhopps@mmm.com wrote:
> [snip, snip]
> Yes, when you change the argument list of a function you also have to
> re-examine the code of every function that called it. But changing
> exception specifications has a more far reaching impact than that.
> Suppose you have a function f() that calls g() and h(). If you change
> the argument lists of g() or h(), you have to look at the code for f(),
> but not any of the code the calls f(). But changing the exception
> specifications for g() or h() ripples into the exception specifications
> for f(), which forces you to look at all the callers of f() as well as
> f() itself. And you can't stop there -- you have to look all the way up
> through callers of callers of callers, until you hit main().
>
Three trivial notes.
(1) When adding new exception, one anyway must look all the way up until
correct exception handler (or a place to insert one) is found, EVEN IF
there are no exception specs.
This procedure is error-prone and can lead to a program that aborts on
unexpected exception. "Strict" ex-specs would enable the compiler
to perform the checks.
(2) When changing function arguments, one must look all the way up in
pretty much the same fashion until there's a place where new argument
may be computed. The situation is completely symmetric.
(3) Changing ex-specs is not supposed to be an everyday activity.
In fact, it is much more extraordinary than, say, changing arg-lists.
Normally one just derives some new exception class.
> If you write a function with exception specifications that calls other
> functions, the only way to avoid this is to write it so that it contains
> a try/catch and remaps any exceptions into one that is in its exception
> specification. This, in turn, may lose information that is valuable to
> the ultimate handler of the exception.
>
You either
(1) make sure the exception will not happen, or
(2) propagate ex-specs back, or
(3) remap callee's exception to caller's one, or
(4) fail miserably.
That's independent of whether there are "strong" ex-specs or "weak"
(current) ones.
Now, let's look at the canonical example again.
extern double sqrt(double) throw(domain_error);
double sqrt_abs(double x) throw() {
return sqrt(x < 0 ? -x : x);
}
This is pretty much equivalent to the following:
extern double sqrt(double) throw(domain_error);
double
sqrt_abs(double x) throw() {
try {
return sqrt(x < 0 ? -x : x) ;
}
catch(...) {
unexpected();
}
}
If the compiler doesn't know that sqrt() will not throw
under these circumstances, it *must* generate the
equivalent of above code.
Such code, when written explicitely, says more or less:
"I've made sure that no uncaught exception will happen here; kill
me if I'm wrong".
With "weak" ex-specs, this is the default wrt each and every call
in the program, and there's no way to change it.
With "strong" ex-specs, we have the right to choose: either the
compiler does the check (the default), or the runtime (but we have
to request it explicitely).
Regards
--
anatoli
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1997/11/12 Raw View
stephen.clamage_nospam@eng.sun.com (Steve Clamage) writes:
|> But there is also a stronger reason. If potentially disallowed
|> exceptions were errors, function f1 could not call function foo at all
|> without surrounding it with a try/catch clause, because foo might exit
|> via any exception. Worse, any time the exception specification of a
|> function changed, you would have to re-examine the code of every
|> function that called it, and the functions that called any of those
|> that changed, and so on.
But this is the case anyway, or should be. Unless you are
systematically prepared to receive any exception from any function.
--
James Kanze +33 (0)1 39 23 84 71 mailto: kanze@gabi-soft.fr
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
I'm looking for a job -- Je recherche du travail
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: Ryszard Kabatek <kabatek@chemie.uni-halle.de>
Date: 1997/11/12 Raw View
I think, the C++ model of the exception specification is incomplete.
Java has the same model, but the work of the finding of the throw
dependicies makes the compiler.
For what reason should the C++ programmer make the work of the compiler?
--
Ryszard Kabatek
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: htrd@tcp.co.uk (Toby Dickenson)
Date: 1997/11/12 Raw View
"Paul D. DeRocco" <pderocco@ix.netcom.com> wrote:
>Leif Rilbe wrote:
>>
>> Does anyone know anything about the rationale for not enforcing this
>> guarantee at compile time? Seems to me that the lack of compile time
>> check makes the mechanism far less usable than it would be otherwise.
>> Especially a compile time check of the empty exception specification
>> would be very useful for writing exception safe code.
>
>The canonical example of why it isn't checked at compile time is
>this:
>
> extern double sqrt(double) throw(domain_error);
>
> double sqrt_abs(double x) throw() {
> return sqrt(x < 0 ? -x : x);
> }
>
>The compiler would detect a static violation of the exception
>specs that could never occur in practice.
Contrived, but...
extern double s(double *x) {
if(*x<0) *x=0;
return x;
}
double s_abs(const double *x) {
if(*x<0) {
double xx=*x;
return s(xx);
}
else {
return s(x);
}
}
The compiler would detect another violation (of const) that could never occur in
practice, and that is a good thing. I can't see why compile-time checking of
exception specifications is not an equally good thing.
------------------------------------------------------------------------------
Toby Dickenson PGP Key ID: 63CCA0A1
htrd@tcp.co.uk Fingerprint: 45 B4 8A 79 67 03 1B 11
37 29 F5 5C B5 FD 2C A2
------------------------------------------------------------------------------
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1997/11/13 Raw View
Stein Somers <stein.somers@intec.rug.ac.be> writes:
|> > The canonical example of why it isn't checked at compile time is
|> > this:
|> >
|> > extern double sqrt(double) throw(domain_error);
|> >
|> > double sqrt_abs(double x) throw() {
|> > return sqrt(x < 0 ? -x : x);
|> > }
|>
|> I'm not convinced. Why not slice off a layer from sqrt:
|>
|> double sqrt_of_positive(double) throw();
|>
|> This core function would be called from sqrt and sqrt_abs and does not
|> have to check its argument, since it didn't specify a domain error in
|> its contract.
You'd still have to check, but you could (or should?) abort if the check
fails?
The point is, you have a specific precondition -- that the argument is
>= 0. The language provides no direct way of enforcing that condition
(e.g. a built-in type positive_double). So a user WILL violated, and
you must define what its violation means. (Typically: violation ==
undefined behavior, which in turn means that the default version of the
library will abort -- you might want to provide a version of the library
without the checks as well, which may return garbage, or go into an
endless loop, or...)
|> Hmmm, an exception specification *is* part of a
|> function's contract, isn't it?
Very much so. Ideally, any change in a functions contract should
require a change in its interface, so that code written with the
previous contract won't compile, and must be rewritten. In practice,
this isn't always practical. (Although one piece of standard advice I
always heard in C was that if you change what a function does, you also
change its name, so that old code won't compile.)
I don't think that there is any argument concerning the fact that what
exceptions a function might throw are part of its interface. (Removing
one isn't a problem, but adding one is a violation of contract.) The
question is simple to what degree this part of the contract is
controlled by the language specification -- part of the contract of
sin(double) is that the returned value is in the range [-1.0 ... 1.0],
but I don't see anything in the declaration of the function which says
this.
|> Doesn't that mean that sqrt must throw
|> if its argument is negative? Which means it must check that argument
|> (be it by intercepting a floating point processor trap)?
This is part of the contract: if the function specification says that is
will throw, then it must throw. If the function specification says that
a negative argument is undefined behavior, it is not required to throw.
At the language level, all that you can say is that it might throw x,
and (more significantly) that it won't throw anything but x -- if the
function declaration is:
double sqrt( double ) throw ( domain_error ) ;
it will not throw bad_alloc, or range_error, or anything else.
IMHO, it is this negative garantee that is important. (The most
important form is, of course, "throw()", since this means that I don't
have to worry about making the calling code exception safe.)
|> Dare I generalize: if a function knows its callee will not throw some
|> particular exception, then this is because the callee specifies in its
|> contract it will not throw given certain values for its arguments or for
|> the global environment. Thus there could be a function with a stricter
|> contract that doesn't specify the exception; a function thougher on its
|> input, thougher on its ouput, and more efficient by not having to check
|> the input state. Counter objections to the extra function call with
|> gratuitous claims of inlining and compiler optimization, and there you
|> have it:
|>
|> Steve Clamage wrote:
|> > the potential for throwing an exception that violates the
|> > exception specification is not an error
|>
|> but it is a sign of inefficiency, or laziness.
No. All Steve is saying is that the error is a run-time one -- it is
only an error if it actually occurs. Sort of like i/j is only an error
if j actually is equal to 0, and not if j is potentially equal to 0.
|> Just like Good
|> Programmers invest in members with identical bodies overloaded on
|> constness?
To continue the division by zero parable: a good programmer will check
before dividing, if it is at all possible for j to be 0. But the
"error" will still only be an error when j actually is 0.
--
James Kanze +33 (0)1 39 23 84 71 mailto: kanze@gabi-soft.fr
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
I'm looking for a job -- Je recherche du travail
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: Darron Shaffer <darron.shaffer@beasys.com>
Date: 1997/11/13 Raw View
--Multipart_Wed_Nov_12_10:00:46_1997-1
Content-Type: text/plain; charset=US-ASCII
Anatoli <REMOVETHISanatoli@ptc.com> writes:
(much clipped)
>
> Now, let's look at the canonical example again.
>
> extern double sqrt(double) throw(domain_error);
>
> double sqrt_abs(double x) throw() {
> return sqrt(x < 0 ? -x : x);
> }
>
> This is pretty much equivalent to the following:
>
> extern double sqrt(double) throw(domain_error);
>
> double
> sqrt_abs(double x) throw() {
> try {
> return sqrt(x < 0 ? -x : x) ;
> }
> catch(...) {
> unexpected();
> }
> }
>
> If the compiler doesn't know that sqrt() will not throw
> under these circumstances, it *must* generate the
> equivalent of above code.
>
> Such code, when written explicitely, says more or less:
> "I've made sure that no uncaught exception will happen here; kill
> me if I'm wrong".
>
> With "weak" ex-specs, this is the default wrt each and every call
> in the program, and there's no way to change it.
>
> With "strong" ex-specs, we have the right to choose: either the
> compiler does the check (the default), or the runtime (but we have
> to request it explicitely).
>
There is a third choice, the "weaker" exception specification:
extern double sqrt(double) throw(domain_error);
double sqrt_abs(double x) {
return sqrt(x < 0 ? -x : x);
}
This says either:
a) I've made sure that no uncaught exception will happen here, if
I'm wrong, let someone else deal with it. Perhaps many other
people.
or
b) I didn't even think about exceptions. I hope I'm lucky.
Java also disallows this third choice, by making no throw
specification the same as "throw()". I think this is a good thing.
I also like the other suggestion of making extern "C" imply throw().
--Multipart_Wed_Nov_12_10:00:46_1997-1
Content-Type: text/plain; charset=US-ASCII
__ __ _
_ ) ___ _\
__) __ \ Enterprise Middleware Solutions Darron J. Shaffer
BEA Systems Inc. Sr. Software Engineer
17101 Preston Rd darron.shaffer@beasys.com
LB# 115, Ste 260 Voice: (972) 738-6137
Dallas, TX 75248 Fax: (972) 738-6111
http://www.beasys.com
--Multipart_Wed_Nov_12_10:00:46_1997-1--
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1997/11/14 Raw View
J. Kanze wrote:
>
> What's wrong with writing?
>
> double
> sqrt_abs( double x ) throw()
> {
> try
> {
> return sqrt( x < 0 ? -x : x ) ;
> }
> catch ( ... )
> {
> abortWithMessage( "..." ) ;
> }
> }
>
> In practice, you have to write about as much anyway, so what's wrong
> with making it something that the compiler can read, rather than just
> comments.
Because it compiles into real code. Even with an empty catch clause, my
compilers add both time and space overhead. I know CPUs are getting faster all
the time, and in many cases the ultimate user won't notice the overhead, but
adding all this runtime behavior moves us ever further from C and ever closer
to SmallTalk. Perhaps my prejudices come from working mostly in embedded code
with a limited address space, and the slowest, cheapest CPU that will do the
job.
--
Ciao,
Paul
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: hoshi@sra.co.jp (Hoshi Takanori)
Date: 1997/11/14 Raw View
In article <64ei34$2dd@netlab.cs.rpi.edu> Darron Shaffer <darron.shaffer@beasys.com> writes:
> Java also disallows this third choice, by making no throw
> specification the same as "throw()". I think this is a good thing.
Java allows not specifying throws clause for RuntimeException,
Error, and their subclasses.
> I also like the other suggestion of making extern "C" imply throw().
C routine itself will not throw, but C++ callback routine passed
to C routine will.
hoshi
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: 1xx754.273x@compuserve.com (Martin Aupperle)
Date: 1997/11/15 Raw View
On 04 Nov 97 05:20:24 GMT, Leif Rilbe <leif_rilbe@hotmail.com> wrote:
>Jerry Leichter wrote:
>>
>> | ...i just read about exception specifications but i do not really
>> understand where and when should i use them....
>> |
>> | // ------
>> | // somewhere here goes the defintions of classes A and B...
>> |
>> | void f(int i) throw(A); // function declaration
>> |
>[...]
>>
>> What the specification for f() above guarantees is that no caller for
>> f() will ever see an exception emerge from f() that is not (derived
>> from) A. This is a *run-time* guarantee, and compilers are actually
>> required to accept code that, on its face, violates it: The violation
>> can be eliminated at run time, and the programmer is allowed to try.
>> (Nevertheless, a good compiler should probably be able to emit a
>> warning, as designing your application around such fixups seems
>> dangerous.)
>> -- Jerry
>
>Does anyone know anything about the rationale for not enforcing this
>guarantee at compile time? Seems to me that the lack of compile time
>check makes the mechanism far less usable than it would be otherwise.
>Especially a compile time check of the empty exception specification
>would be very useful for writing exception safe code. Are there any
>changes in the works in this regard?
>
Because it is not possible. Consider
void f() { ... } // in some library you use
Now you write function g as
void g() throw( X,Y,Z ) { f(); }
How can a compiler handle that? It must generate code to look at
exceptions that come from f and classify them: if it is a X,Y or Z
then pass it on, otherwise call unexpected.
Please note: The additional run time penalty only occurs in the case
of exceptions. Normal program operation is not slower.
------------------------------------------------
Martin Aupperle 1xx754.273x@compuserve.com
(replace x with 0 - fight spamming)
------------------------------------------------
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: Esa Pulkkinen <esap@cs.tut.fi>
Date: 1997/11/15 Raw View
kanze@gabi-soft.fr (J. Kanze) writes:
> I don't think that there is any argument concerning the fact that what
> exceptions a function might throw are part of its interface. (Removing
> one isn't a problem, but adding one is a violation of contract.) The
> question is simple to what degree this part of the contract is
> controlled by the language specification -- part of the contract of
> sin(double) is that the returned value is in the range [-1.0 ... 1.0],
> but I don't see anything in the declaration of the function which says
> this.
Yes, it's not feasible to require exact specification of functions
(because they would be as long as the function implementation itself in
many cases! And no-one wants to write that.). But I don't agree in that
I think exception specifications should be enforced in
compile-time. Consider the problem in the previous article:
>> double sqrt_abs(double x) throw() {
>> return sqrt(x < 0 ? -x : x);
>> }
Here the problem really is that the programmer knows the sqrt cannot
fail, but the compiler doesn't - the compiler has no means to deduce
that the sqrt can only accept non-negative values. Ideally, the
specification of sqrt could be changed to take this into account, for
example, a hypothetical language could allow something along the lines of:
double sqrt(double a) throw() where a >= 0;
double sqrt(double a) throw(domain_error) where a < 0;
i.e. allow the user to define preconditions, which could be used for
telling the compiler more exactly the conditions where the function will
throw an exception.
Of course, this kind of feature isn't probably a good idea for C++, it
will cause problems with the (already complicated) rules for overloading
and would be hard to enforce. I think Haskell has an overloading
mechanism, that can do this (when you encode the condition "a >= 0" as a
type class).
But there is another way of solving this problem: Require the user to
catch (or maybe say somehow that it cannot happen) all exceptions the
compiler doesn't know are safe. For example:
double sqrt_abs(double a) throw()
{
cannot_throw(domain_error) {
return sqrt(x < 0 ? -x : x);
}
}
This would require the programmer to tell when it's reasonable to assume
the postcondition of the sqrt can be assumed to be stricter than what
the specification of the function says. I would assume such cases are
rare in code that uses exception specifications for all interfaces. It's
better to require the programmer to tell when the declaration is wrong
(even if that is because the language doesn't allow you to express it
right) than to assume implicitly that it's right when it in fact is
not. The situation is very much the same as with const - it's possible
to avoid the compile-time check with explicitly using const_cast to
inform the compiler that the code is correct even though the compiler
can't deduce it since it hasn't been given enough information.
This would also discourage the use of "throw everything" exception
specifications, which IMHO is a good thing, but still allow better
checks and allow better optimizations for exceptions (because no
run-time code would have to be generated for checking exception
specifications).
IMO the safety benefits of compile-time checking are far more important
than the little inconvenience that the compile-time checking will cause
when interfacing with code whose exception specifications are wrong. Of
course, compatibility with existing code is a problem - because
potentially most existing code using exceptions might be affected.
> IMHO, it is this negative garantee that is important. (The most
> important form is, of course, "throw()", since this means that I don't
> have to worry about making the calling code exception safe.)
Yes, this also means IMHO that throw() should have been the default, not
throw(...). By default, functions are not exception safe.
> No. All Steve is saying is that the error is a run-time one -- it is
> only an error if it actually occurs. Sort of like i/j is only an error
> if j actually is equal to 0, and not if j is potentially equal to 0.
It's a run-time error only if the compiler isn't provided enough
information about the function in the interface (or in the call) to
check it at compile-time. The real problem is that C++ doesn't allow the
programmer to express the mapping from preconditions to postconditions
exactly enough that the compiler could in all cases make the
distinction. I'm not sure a language like C++ could ever require that. I
know you _can_ express those things in a specification language, but
those are complex and most people don't want to specify their interfaces
in such detail. But still, exception specifications are (nearly) useless
without their enforcement at compile-time. Current situation is that
exception specifications are just syntactic sugar for a try block that
rethrows the specified exceptions, and calls unexpected otherwise.
[followups set to comp.std.c++]
--
Esa Pulkkinen | C++ programmers do it virtually
E-Mail: esap@cs.tut.fi | everywhere with class, resulting
WWW : http://www.cs.tut.fi/~esap/ | in multiple inheritance.
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: Stein Somers <stein.somers@intec.rug.ac.be>
Date: 1997/11/15 Raw View
I proposed:
> double sqrt_of_positive(double) throw();
>
> This core function would be called from sqrt and sqrt_abs and does not
> have to check its argument, since it didn't specify a domain error in
> its contract.
J. Kanze replied:
> You'd still have to check, but you could (or should?) abort if the
> check fails?
Even if the contract states that behaviour is undefined if argument<0,
and advises clients to turn to sqrt(), sqrt_abs() or other library f's?
> The point is, you have a specific precondition -- that the argument is
> >= 0. The language provides no direct way of enforcing that condition
> (e.g. a built-in type positive_double).
Agreed that you have to check preconditions, that you should distrust
users' compliance for the fine print of a contract, otherwise you will
get the blame for their mistakes. But surely there are library elements
targeted at "advanced" users. They could be marked with a feature the
language supports directly, i.e. a special name. Should we have any
mercy for a user coding sqrt_of_positive(-1.), or sqrt_unchecked(x)?
No, but perhaps we still have to fear that (l)user...
Back to the question why exception specifications are not checked by the
compiler and one of the arguments of the defense (the other argument
being slammed down already):
> The canonical example of why it isn't checked at compile time is
> this:
>
> extern double sqrt(double) throw(domain_error);
>
> double sqrt_abs(double x) throw() {
> return sqrt(x < 0 ? -x : x);
> }
I reformulate my objection: every function with a non empty exception
specification has a range of input conditions for which no exceptions
will be thrown.
* If these conditions are simple, for example "argument must be >=0",
then it is easy to offer an efficient core function without throw list
that doesn't check these conditions, and to implement the original
function in terms of that. The compiler is welcome to check exception
specifications in this situation. The core function would be one of
those library elements targeted at "advanced" clients.
* If these conditions are complicated or fuzzy, for example "this input
operation will succeed if the input is decent", is it possible to offer
a version with empty throw list, that calls the original operation so
sure of itself that it doesn't even try to catch its exceptions?
> No. All Steve is saying is that the error is a run-time one -- it is
> only an error if it actually occurs.
Yes, in the (draft) Standard, but this thread is of the "this should
change in C++ or we're not happy" type so who cares. :)
> Sort of like i/j is only an error
> if j actually is equal to 0, and not if j is potentially equal to 0.
> a good programmer will check
> before dividing, if it is at all possible for j to be 0. But the
> "error" will still only be an error when j actually is 0.
If the language allowed, wouldn't you prefer the compiler to complain
about:
int operator/ (int, nonzero int);
int f(int x)
{
if (x!=0) 1/x; // ok
1/x; // error: possible division by 0
}
then wait for the detection of an offence at run-time?
Stein
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1997/11/17 Raw View
Toby Dickenson wrote:
>
> Contrived, but...
>
> extern double s(double *x) {
> if(*x<0) *x=0;
> return x;
> }
>
> double s_abs(const double *x) {
> if(*x<0) {
> double xx=*x;
> return s(xx);
> }
> else {
> return s(x);
> }
> }
>
> The compiler would detect another violation (of const) that could
> never occur in
> practice, and that is a good thing. I can't see why compile-time
> checking of
> exception specifications is not an equally good thing.
Modulo typos, the above is a good analogy, except that I think in practice it's
less common than the situation I described. Besides, in the above case you can
quiet the compiler with a simple const_cast, which compiles down to nothing,
while in the exception case you have to wrap the body in a try block, which
compiles down to something not so insignificant.
--
Ciao,
Paul
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1997/11/17 Raw View
Toby Dickenson wrote:
>
> Contrived, but...
>
> extern double s(double *x) {
> if(*x<0) *x=0;
> return x;
> }
>
> double s_abs(const double *x) {
> if(*x<0) {
> double xx=*x;
> return s(xx);
> }
> else {
> return s(x);
> }
> }
>
> The compiler would detect another violation (of const) that could
> never occur in
> practice, and that is a good thing. I can't see why compile-time
> checking of
> exception specifications is not an equally good thing.
Modulo typos, the above is a good analogy, except that I think in practice it's
less common than the situation I described. Besides, in the above case you can
quiet the compiler with a simple const_cast, which compiles down to nothing,
while in the exception case you have to wrap the body in a try block, which
compiles down to something not so insignificant.
--
Ciao,
Paul
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Marc Sherman <marcsh@corel.ca>
Date: 1997/11/18 Raw View
[reposted - my previous post was xposted to too many newsgroups.]
[snip a const correctness example that's analagous to strict exception
specifications]
Paul D. DeRocco wrote:
> Modulo typos, the above is a good analogy, except that I think in practice it's
> less common than the situation I described. Besides, in the above case you can
> quiet the compiler with a simple const_cast, which compiles down to nothing,
> while in the exception case you have to wrap the body in a try block, which
> compiles down to something not so insignificant.
Perhaps we also need a throw_cast, which lets you explicitly change
an exceptionspecification when you are certain that your input matches
the preconditions that guarantee the new exception specification.
Throwing an exception that was in the original specification but not
the new one is undefined behaviour. For example:
double sqrt_abs(double x)
{
return (x < 0) ?
throw_cast<>(sqrt)(-x) : throw_cast<>(sqrt)(x);
}
Note that to be entirely consistant with the other cast operators,
the calls to sqrt would actually be written as
"throw_cast<double(*)(double) throw()>(sqrt)(x)", but since throw_cast
can only change the exception specification, only writing the new
specification inside the <>'s is preferable, I think.
Another example:
void foo() throw(X,Y);
void bar() throw(X,Z)
{
throw_cast<>(foo)(); // legal - undefined if foo throws an
// X or a Y
throw_cast<X>(foo)(); // legal - undefined if foo throws a Y
throw_cast<X,Z>(foo)(); // illegal - throw_cast can only
// narrow the exception spec
}
- Marc
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: kjhopps@mmm.com
Date: 1997/11/09 Raw View
Steve Clamage wrote:
>
> On 04 Nov 97 05:20:24 GMT, Leif Rilbe <leif_rilbe@hotmail.com> wrote:
>
> >> What the specification for f() above guarantees is that no caller for
> >> f() will ever see an exception emerge from f() that is not (derived
> >> from) A. This is a *run-time* guarantee, and compilers are actually
> >> required to accept code that, on its face, violates it: The violation
> >> can be eliminated at run time, and the programmer is allowed to try.
> >> (Nevertheless, a good compiler should probably be able to emit a
> >> warning, as designing your application around such fixups seems
> >> dangerous.)
> >
> >Does anyone know anything about the rationale for not enforcing this
> >guarantee at compile time? Seems to me that the lack of compile time
> >check makes the mechanism far less usable than it would be otherwise.
> >Especially a compile time check of the empty exception specification
> >would be very useful for writing exception safe code. Are there any
> >changes in the works in this regard?
>
> A general principle in C++ (often violated) is that things that might
> go wrong are not necessarily errors. For example, if you declare an
> ambiguous set of overloaded functions, it is not an error unless you
> actually make a call that is ambiguous.
>
> Similarly, the potential for throwing an exception that violates the
> exception specification is not an error. If we made the potential
> undesired exception a compile-time error, we would then run into
> problems like these:
> void foo(int*);
> void f1(int i) throw(int)
> {
> foo(&i);
> if( i < 3 )
> throw "hello";
> }
> Error? Not if foo exits by throwing an int exception, or if i>=3 after
> the call to foo. The compiler in general cannot tell, and how much
> global analysis should we require a compiler to do?
>
> But there is also a stronger reason. If potentially disallowed
> exceptions were errors, function f1 could not call function foo at all
> without surrounding it with a try/catch clause, because foo might exit
> via any exception. Worse, any time the exception specification of a
> function changed, you would have to re-examine the code of every
> function that called it, and the functions that called any of those
> that changed, and so on. It seemed like that situation would make
> exception specifications even less useful than they are under current
> rules.
By saying that you don't want the compiler to do this, you have not
saved me from this analysis. Finding out about a bug triggered by a
violated exception specification is even more costly at run time. I
agree that the compiler should not do this, but more relevant is that
this is a strong argument against using exception specifications at all
(except perhaps throw(), the "will not throw" specification).
Exception specifications are a guarantee, yes, but they also betray the
implementation somewhat. At the very least, using an exception
specification on my function makes it very difficult for me to change
its implementation and still maintain my guarantee of what exceptions
can escape it. This is especially true of template classes. What
guarantees can you possibly make, having no idea of what "T" will be
used to instantiate the template?
I'm not sure if the benefit of exception specifications justifies the
cost of their use.
--
Kevin J. Hopps, Imation. E-mail to: kjhopps-at-imation-dot-com
My opinions are my own. I speak neither for Imation nor 3M.
Support the anti-spam amendment, HR 1748. See http://www.cauce.org
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Leif Rilbe <leif_rilbe@hotmail.com>
Date: 1997/11/09 Raw View
Steve Clamage wrote:
>
> On 04 Nov 97 05:20:24 GMT, Leif Rilbe <leif_rilbe@hotmail.com> wrote:
>
> >> What the specification for f() above guarantees is that no caller for
> >> f() will ever see an exception emerge from f() that is not (derived
> >> from) A. This is a *run-time* guarantee, and compilers are actually
[...]
> >Does anyone know anything about the rationale for not enforcing this
> >guarantee at compile time? Seems to me that the lack of compile time
[...]
> A general principle in C++ (often violated) is that things that might
> go wrong are not necessarily errors. For example, if you declare an
> ambiguous set of overloaded functions, it is not an error unless you
> actually make a call that is ambiguous.
Agreed. But you still get a compile time error. You do not get a run
time error of the character: "ooops...don't know what that hacker really
meant here...sorry...reboot the life support system...".
[...]
> void foo(int*);
> void f1(int i) throw(int)
> {
> foo(&i);
> if( i < 3 )
> throw "hello";
> }
> Error? Not if foo exits by throwing an int exception, or if i>=3 after
> the call to foo. The compiler in general cannot tell, and how much
> global analysis should we require a compiler to do?
>
I am not a compiler writer, so I am not very well informed as to the
complexities involved. However, I would think that the complexity
involved here would be unmanageable. Maybe in combination with template
handling there could be problems of course (but what isn't:).
> But there is also a stronger reason. If potentially disallowed
> exceptions were errors, function f1 could not call function foo at all
> without surrounding it with a try/catch clause, because foo might exit
> via any exception.
Exactly. Why do you consider that a bad thing?
> Worse, any time the exception specification of a
> function changed, you would have to re-examine the code of every
> function that called it, and the functions that called any of those
> that changed, and so on. It seemed like that situation would make
> exception specifications even less useful than they are under current
> rules.
>
IMHO it would be better to be forced to deal with the problem at compile
time rather than at run time. What you describe is a perfect way of
breaking existing code without getting compile time errors. When I
change the argument list of a function I also have to "re-examine the
code of every function that called it". This is what static type
checking is all about, is it not? It forces you to make decisions at
compile time in order to avoid problems at run time. Why should it be
different for exception specifications?
Exception handling per se introduces many difficulties. IMHO it is
rarely worth the cost to make code exception safe. In these cases (not
needing exception safety) i think one would not use exception
specifications in any larger extent, thus having no compile time
problems. In other cases, with extreme requirements on fault tolerance
etc, I would think that compile time errors would be preferrable to run
time ones.
See also David Chase's posting in comp.lang.c++.moderated.
> ---
> Steve Clamage, stephen.clamage_nospam@eng.sun.com
> ( Note: remove "_nospam" when replying )
> ---
Regards,
Leif Rilbe
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: kjhopps@mmm.com
Date: 1997/11/09 Raw View
Steve Clamage wrote:
>
> On 04 Nov 97 05:20:24 GMT, Leif Rilbe <leif_rilbe@hotmail.com> wrote:
>
> >> What the specification for f() above guarantees is that no caller for
> >> f() will ever see an exception emerge from f() that is not (derived
> >> from) A. This is a *run-time* guarantee, and compilers are actually
> >> required to accept code that, on its face, violates it: The violation
> >> can be eliminated at run time, and the programmer is allowed to try.
> >> (Nevertheless, a good compiler should probably be able to emit a
> >> warning, as designing your application around such fixups seems
> >> dangerous.)
> >
> >Does anyone know anything about the rationale for not enforcing this
> >guarantee at compile time? Seems to me that the lack of compile time
> >check makes the mechanism far less usable than it would be otherwise.
> >Especially a compile time check of the empty exception specification
> >would be very useful for writing exception safe code. Are there any
> >changes in the works in this regard?
>
> A general principle in C++ (often violated) is that things that might
> go wrong are not necessarily errors. For example, if you declare an
> ambiguous set of overloaded functions, it is not an error unless you
> actually make a call that is ambiguous.
>
> Similarly, the potential for throwing an exception that violates the
> exception specification is not an error. If we made the potential
> undesired exception a compile-time error, we would then run into
> problems like these:
> void foo(int*);
> void f1(int i) throw(int)
> {
> foo(&i);
> if( i < 3 )
> throw "hello";
> }
> Error? Not if foo exits by throwing an int exception, or if i>=3 after
> the call to foo. The compiler in general cannot tell, and how much
> global analysis should we require a compiler to do?
>
> But there is also a stronger reason. If potentially disallowed
> exceptions were errors, function f1 could not call function foo at all
> without surrounding it with a try/catch clause, because foo might exit
> via any exception. Worse, any time the exception specification of a
> function changed, you would have to re-examine the code of every
> function that called it, and the functions that called any of those
> that changed, and so on. It seemed like that situation would make
> exception specifications even less useful than they are under current
> rules.
By saying that you don't want the compiler to do this, you have not
saved me from this analysis. Finding out about a bug triggered by a
violated exception specification is even more costly at run time. I
agree that the compiler should not do this, but more relevant is that
this is a strong argument against using exception specifications at all
(except perhaps throw(), the "will not throw" specification).
Exception specifications are a guarantee, yes, but they also betray the
implementation somewhat. At the very least, using an exception
specification on my function makes it very difficult for me to change
its implementation and still maintain my guarantee of what exceptions
can escape it. This is especially true of template classes. What
guarantees can you possibly make, having no idea of what "T" will be
used to instantiate the template?
I'm not sure if the benefit of exception specifications justifies the
cost of their use.
--
Kevin J. Hopps, Imation. E-mail to: kjhopps-at-imation-dot-com
My opinions are my own. I speak neither for Imation nor 3M.
Support the anti-spam amendment, HR 1748. See http://www.cauce.org
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Leif Rilbe <leif_rilbe@hotmail.com>
Date: 1997/11/09 Raw View
Steve Clamage wrote:
>
> On 04 Nov 97 05:20:24 GMT, Leif Rilbe <leif_rilbe@hotmail.com> wrote:
>
> >> What the specification for f() above guarantees is that no caller for
> >> f() will ever see an exception emerge from f() that is not (derived
> >> from) A. This is a *run-time* guarantee, and compilers are actually
[...]
> >Does anyone know anything about the rationale for not enforcing this
> >guarantee at compile time? Seems to me that the lack of compile time
[...]
> A general principle in C++ (often violated) is that things that might
> go wrong are not necessarily errors. For example, if you declare an
> ambiguous set of overloaded functions, it is not an error unless you
> actually make a call that is ambiguous.
Agreed. But you still get a compile time error. You do not get a run
time error of the character: "ooops...don't know what that hacker really
meant here...sorry...reboot the life support system...".
[...]
> void foo(int*);
> void f1(int i) throw(int)
> {
> foo(&i);
> if( i < 3 )
> throw "hello";
> }
> Error? Not if foo exits by throwing an int exception, or if i>=3 after
> the call to foo. The compiler in general cannot tell, and how much
> global analysis should we require a compiler to do?
I am not a compiler writer, so I am not very well informed as to the
complexities involved. However, I would think that the complexity
involved here would be unmanageable. Maybe in combination with template
handling there could be problems of course (but what isn't:).
> But there is also a stronger reason. If potentially disallowed
> exceptions were errors, function f1 could not call function foo at all
> without surrounding it with a try/catch clause, because foo might exit
> via any exception.
Exactly. Why do you consider that a bad thing?
> Worse, any time the exception specification of a
> function changed, you would have to re-examine the code of every
> function that called it, and the functions that called any of those
> that changed, and so on. It seemed like that situation would make
> exception specifications even less useful than they are under current
> rules.
IMHO it would be better to be forced to deal with the problem at compile
time rather than at run time. What you describe is a perfect way of
breaking existing code without getting compile time errors. When I
change the argument list of a function I also have to "re-examine the
code of every function that called it". This is what static type
checking is all about, is it not? It forces you to make decisions at
compile time in order to avoid problems at run time. Why should it be
different for exception specifications?
Exception handling per se introduces many difficulties. IMHO it is
rarely worth the cost to make code exception safe. In these cases (not
needing exception safety) i think one would not use exception
specifications in any larger extent, thus having no compile time
problems. In other cases, with extreme requirements on fault tolerance
etc, I would think that compile time errors would be preferrable to run
time ones.
See also David Chase's posting in comp.lang.c++.moderated.
Regards,
Leif Rilbe
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: David Chase <chase@world.std.com>
Date: 1997/11/09 Raw View
Paul D. DeRocco wrote:
> The canonical example of why it isn't checked at compile time is
> this:
>
> extern double sqrt(double) throw(domain_error);
>
> double sqrt_abs(double x) throw() {
> return sqrt(x < 0 ? -x : x);
> }
>
> The compiler would detect a static violation of the exception
> specs that could never occur in practice.
Probably true (see below), but how painful is it in practice to
include:
extern double sqrt(double) throw(domain_error);
double sqrt_abs(double x) throw() {
try {
return sqrt(x < 0 ? -x : x);
} catch (domain_error) {
cannot_happen();
return DNaN;
}
}
I've written a fair amount of Java and Modula-3 and lived with this
restriction, and the painfulness of it seems to be overestimated by
people who appear never to have tried it.
- these cases are relatively rare; in general, it is difficult to
be certain that you have in fact eliminated all chance of a domain
error. In your example, for instance, I note that you believe
that NaN and +Inf are in the domain of sqrt. Are they? (They
could be -- sqrt(Nan)=Nan and sqrt(Inf)=Inf) Are these
assumptions guaranteed by the standard?
- it's not that painful to add the boilerplate; it's easy to find the
places where you need it, since the compiler whines at you when
you forget it.
- it doesn't slow the code down much, given a decent implementation
of exception-handling (depending upon your implementation, there
may or may not be a tail-call-elimination that the try-catch
would inhibit. That should be the only cost.)
- checking in the compiler detects a fair amount of lurking errors
that otherwise go unnoticed. These are also errors that are not
easily detected by testing, since you have to get exceptions
thrown all over the place to verify that you put a handler
everywhere that you actually needed one. (I.e., you need code
coverage of all the places that "aren't there", but coverage tools
are better at reporting on coverage of places that actually exist
in your program. Compile-time-checking forces you to ensure
that there is a there there.)
- unless you have tried this and used it for a while, you probably
have no idea of the benefits.
As I've stated elsewhere, I'm not sure that this is a good idea for
C++, since it is claimed by complex-language experts that combining
this feature with templates would just be too hard. However, the
assertions that this feature is generally difficult to live with are
completely contrary to my experience writing code in languages with
exactly this feature. I'm not talking about toy programs, either --
I'm talking about compilers, linkers, runtime systems, and web servers,
ranging in size from a few thousand lines of code to over 100,000
lines of code. But hey, what's my experience worth, versus the
armchair theorizing of dozens of C++ experts?
If this could be cleanly meshed with the rest of C++, it would be
a benefit, but I do not know if this is possible. It's not
something I worry much about anymore; I'm having more fun making
Java go faster and faster.
--
David Chase, chase@world.std.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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1997/11/10 Raw View
David Chase wrote:
>
> how painful is it in practice to
> include:
>
> extern double sqrt(double) throw(domain_error);
>
> double sqrt_abs(double x) throw() {
> try {
> return sqrt(x < 0 ? -x : x);
> } catch (domain_error) {
> cannot_happen();
> return DNaN;
> }
> }
Ouch. Most implementations _do_ add runtime overhead (Borland
adds about a dozen instructions if you force inline exception
contexts), which isn't a huge amount, but it's a lot to spend on
quieting the compiler. Second, it's a lot harder to read, since
four out of the five lines of the function definition are in
fact superfluous. Anyway, I don't like exception specs anyway,
so whether the compiler tries to enforce them or not won't make
me happy.
--
Ciao,
Paul
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1997/11/10 Raw View
Leif Rilbe wrote:
>
> Exception handling per se introduces many difficulties. IMHO it is
> rarely worth the cost to make code exception safe. In these cases (not
> needing exception safety) i think one would not use exception
> specifications in any larger extent, thus having no compile time
> problems. In other cases, with extreme requirements on fault tolerance
> etc, I would think that compile time errors would be preferrable to run
> time ones.
Exception handling is very much like multi-threading, in that
you have to learn a new way of thinking. You have to be able to
"feel" how exceptions flow, in much the same way that you learn
to "feel" how threads interact. Once you "get it", exceptions
are a much more natural way of expressing certain things, just
as multi-threading is a much more natural way of expressing
other things.
That said, I still hate exception specifications. I could learn
to live with a simple dichotomy between functions that throw and
those that don't, but trying to nail things down further leads
to complexities that I've never been able to resolve, so I
simply don't use them. It doesn't matter to me that much whether
a program aborts because of a violation of an exception
specification, or because of a completely uncaught exception.
--
Ciao,
Paul
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: Stein Somers <stein.somers@intec.rug.ac.be>
Date: 1997/11/11 Raw View
> The canonical example of why it isn't checked at compile time is
> this:
>
> extern double sqrt(double) throw(domain_error);
>
> double sqrt_abs(double x) throw() {
> return sqrt(x < 0 ? -x : x);
> }
I'm not convinced. Why not slice off a layer from sqrt:
double sqrt_of_positive(double) throw();
This core function would be called from sqrt and sqrt_abs and does not
have to check its argument, since it didn't specify a domain error in
its contract. Hmmm, an exception specification *is* part of a
function's contract, isn't it? Doesn't that mean that sqrt must throw
if its argument is negative? Which means it must check that argument
(be it by intercepting a floating point processor trap)?
Dare I generalize: if a function knows its callee will not throw some
particular exception, then this is because the callee specifies in its
contract it will not throw given certain values for its arguments or for
the global environment. Thus there could be a function with a stricter
contract that doesn't specify the exception; a function thougher on its
input, thougher on its ouput, and more efficient by not having to check
the input state. Counter objections to the extra function call with
gratuitous claims of inlining and compiler optimization, and there you
have it:
Steve Clamage wrote:
> the potential for throwing an exception that violates the
> exception specification is not an error
but it is a sign of inefficiency, or laziness. Just like Good
Programmers invest in members with identical bodies overloaded on
constness?
Steve Clamage continued:
> But there is also a stronger reason.
> [...] Worse, any time the exception specification of a
> function changed, you would have to re-examine the code of every
> function that called it, and the functions that called any of those
> that changed, and so on.
Taking into account Leif Rilbe's and Kevin J. Hopps' words, can one
change an exception specification without doing that? Maybe if we were
to widen the input contract, for example generalize:
double sqrt(double) throw(domain_error);
to
double sqrt(numeric) throw(domain_error, bad_alloc);
where double is-a numeric, and so is some class of infinite precision
decimals (hence the dynamic memory). The new exception arrises only
given new kinds of input, so there is no need to re-examine existing
code. Does it make sense to throw away the specialised function?
It does to me. Somewhat.
Stein
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[If this message is appended to a post, the .sig has been
snipped. Either it had some strange characters in it, and it
got snipped by my newsreader, or it was excessively long. --hlh]
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: kjhopps@mmm.com
Date: 1997/11/11 Raw View
Leif Rilbe wrote:
>
> Steve Clamage wrote:
[snip]
> > Worse, any time the exception specification of a
> > function changed, you would have to re-examine the code of every
> > function that called it, and the functions that called any of those
> > that changed, and so on. It seemed like that situation would make
> > exception specifications even less useful than they are under current
> > rules.
> >
>
> IMHO it would be better to be forced to deal with the problem at compile
> time rather than at run time. What you describe is a perfect way of
> breaking existing code without getting compile time errors. When I
> change the argument list of a function I also have to "re-examine the
> code of every function that called it". This is what static type
> checking is all about, is it not? It forces you to make decisions at
> compile time in order to avoid problems at run time. Why should it be
> different for exception specifications?
Yes, when you change the argument list of a function you also have to
re-examine the code of every function that called it. But changing
exception specifications has a more far reaching impact than that.
Suppose you have a function f() that calls g() and h(). If you change
the argument lists of g() or h(), you have to look at the code for f(),
but not any of the code the calls f(). But changing the exception
specifications for g() or h() ripples into the exception specifications
for f(), which forces you to look at all the callers of f() as well as
f() itself. And you can't stop there -- you have to look all the way up
through callers of callers of callers, until you hit main().
If you write a function with exception specifications that calls other
functions, the only way to avoid this is to write it so that it contains
a try/catch and remaps any exceptions into one that is in its exception
specification. This, in turn, may lose information that is valuable to
the ultimate handler of the exception.
> Exception handling per se introduces many difficulties. IMHO it is
> rarely worth the cost to make code exception safe. In these cases (not
> needing exception safety) i think one would not use exception
> specifications in any larger extent, thus having no compile time
> problems. In other cases, with extreme requirements on fault tolerance
> etc, I would think that compile time errors would be preferrable to run
> time ones.
I think you may have the wrong idea about the cost of making code
exception safe. I do it all the time, and by now it is second nature.
Much of the time it only involves a reordering of statements and/or the
use of resource releasing classes, which are useful even in
non-exception code.
Cases where exception safety is not important are rare. Any significant
application written without consideration for exception safety is
vulnerable to crashing unexpectedly. Would you consider prohibiting
this an "extreme fault tolerance requirement," or am I misunderstanding
you?
--
Kevin J. Hopps, Imation. E-mail to: kjhopps-at-imation-dot-com
My opinions are my own. I speak neither for Imation nor 3M.
Support the anti-spam amendment, HR 1748. See http://www.cauce.org
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[If this message is appended to a post, the .sig has been
snipped. Either it had some strange characters in it, and it
got snipped by my newsreader, or it was excessively long. --hlh]
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1997/11/11 Raw View
stephen.clamage_nospam@eng.sun.com (Steve Clamage) writes:
|> But there is also a stronger reason. If potentially disallowed
|> exceptions were errors, function f1 could not call function foo at all
|> without surrounding it with a try/catch clause, because foo might exit
|> via any exception. Worse, any time the exception specification of a
|> function changed, you would have to re-examine the code of every
|> function that called it, and the functions that called any of those
|> that changed, and so on.
But this is the case anyway, or should be. Unless you are
systematically prepared to receive any exception from any function.
--
James Kanze +33 (0)1 39 23 84 71 mailto: kanze@gabi-soft.fr
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
I'm looking for a job -- Je recherche du travail
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[If this message is appended to a post, the .sig has been
snipped. Either it had some strange characters in it, and it
got snipped by my newsreader, or it was excessively long. --hlh]
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: kanze@gabi-soft.fr (J. Kanze)
Date: 1997/11/11 Raw View
"Paul D. DeRocco" <pderocco@ix.netcom.com> writes:
|> Leif Rilbe wrote:
|> >
|> > Does anyone know anything about the rationale for not enforcing this
|> > guarantee at compile time? Seems to me that the lack of compile time
|> > check makes the mechanism far less usable than it would be otherwise.
|> > Especially a compile time check of the empty exception specification
|> > would be very useful for writing exception safe code.
|>
|> The canonical example of why it isn't checked at compile time is
|> this:
|>
|> extern double sqrt(double) throw(domain_error);
|>
|> double sqrt_abs(double x) throw() {
|> return sqrt(x < 0 ? -x : x);
|> }
|>
|> The compiler would detect a static violation of the exception
|> specs that could never occur in practice.
"Could never occur in practice" sounds like wishful thinking to me:-).
(Are you saying that you've never seen an error in a library routine?)
What's wrong with writing?
double
sqrt_abs( double x ) throw()
{
try
{
return sqrt( x < 0 ? -x : x ) ;
}
catch ( ... )
{
abortWithMessage( "..." ) ;
}
}
In practice, you have to write about as much anyway, so what's wrong
with making it something that the compiler can read, rather than just
comments.
--
James Kanze +33 (0)1 39 23 84 71 mailto: kanze@gabi-soft.fr
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
I'm looking for a job -- Je recherche du travail
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
[If this message is appended to a post, the .sig has been
snipped. Either it had some strange characters in it, and it
got snipped by my newsreader, or it was excessively long. --hlh]
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: Gerard Weatherby <gerardw@alum.mit.edu>
Date: 1997/11/05 Raw View
Stanley Friesen wrote:
> When used *systematically* throughout a project, they can lead to
> significant optimizations, and to better control of error propagation.
> They also help find bugs in your program.
What optimizations?
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Gerhard Menzl <gerhard.menzl@sea.ericsson.se>
Date: 1997/11/07 Raw View
Leif Rilbe wrote:
> > What the specification for f() above guarantees is that no caller for
> > f() will ever see an exception emerge from f() that is not (derived
> > from) A. This is a *run-time* guarantee, and compilers are actually
> > required to accept code that, on its face, violates it: The violation
> > can be eliminated at run time, and the programmer is allowed to try.
> > (Nevertheless, a good compiler should probably be able to emit a
> > warning, as designing your application around such fixups seems
> > dangerous.)
> > -- Jerry
>
> Does anyone know anything about the rationale for not enforcing this
> guarantee at compile time? Seems to me that the lack of compile time
> check makes the mechanism far less usable than it would be otherwise.
> Especially a compile time check of the empty exception specification
> would be very useful for writing exception safe code. Are there any
> changes in the works in this regard?
My understanding is that such a check could be performed only in a
shallow way, i.e. the compiler could only scan for throws of the
prohibited exception in f() itself, but not in functions called by f(),
which could be in a separate translation unit. This would only be
possible under the restriction that a function with an exception
specification cannot call a function that does not bear the same
exception specification, just like const member functions cannot call
non-const member functions.
Gerhard Menzl
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: stephen.clamage_nospam@eng.sun.com (Steve Clamage)
Date: 1997/11/07 Raw View
On 04 Nov 97 05:20:24 GMT, Leif Rilbe <leif_rilbe@hotmail.com> wrote:
>> What the specification for f() above guarantees is that no caller for
>> f() will ever see an exception emerge from f() that is not (derived
>> from) A. This is a *run-time* guarantee, and compilers are actually
>> required to accept code that, on its face, violates it: The violation
>> can be eliminated at run time, and the programmer is allowed to try.
>> (Nevertheless, a good compiler should probably be able to emit a
>> warning, as designing your application around such fixups seems
>> dangerous.)
>
>Does anyone know anything about the rationale for not enforcing this
>guarantee at compile time? Seems to me that the lack of compile time
>check makes the mechanism far less usable than it would be otherwise.
>Especially a compile time check of the empty exception specification
>would be very useful for writing exception safe code. Are there any
>changes in the works in this regard?
A general principle in C++ (often violated) is that things that might
go wrong are not necessarily errors. For example, if you declare an
ambiguous set of overloaded functions, it is not an error unless you
actually make a call that is ambiguous.
Similarly, the potential for throwing an exception that violates the
exception specification is not an error. If we made the potential
undesired exception a compile-time error, we would then run into
problems like these:
void foo(int*);
void f1(int i) throw(int)
{
foo(&i);
if( i < 3 )
throw "hello";
}
Error? Not if foo exits by throwing an int exception, or if i>=3 after
the call to foo. The compiler in general cannot tell, and how much
global analysis should we require a compiler to do?
But there is also a stronger reason. If potentially disallowed
exceptions were errors, function f1 could not call function foo at all
without surrounding it with a try/catch clause, because foo might exit
via any exception. Worse, any time the exception specification of a
function changed, you would have to re-examine the code of every
function that called it, and the functions that called any of those
that changed, and so on. It seemed like that situation would make
exception specifications even less useful than they are under current
rules.
---
Steve Clamage, stephen.clamage_nospam@eng.sun.com
( Note: remove "_nospam" when replying )
---
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Marc Girod <girod@trshp.trs.ntc.nokia.com>
Date: 1997/11/07 Raw View
>>>>> "BS" == Bradd W Szonye <bradds@concentric.net> writes:
BS> Marc Girod wrote in message <1yd8kicvm7.fsf@dshp01.trs.ntc.nokia.com>...
BS> I believe that you misread this. The claim is not that exceptions help in
BS> debugging, but that exception-specifications do. In other words, it's
BS> possible that you accidentally throw an exception that the caller is not
BS> prepared to catch. (Or that a maintenance change adds a thrown exception
BS> that the original handler was not prepared for.)
I did read this, Bradd. Exception specifications -not exceptions-
introduce a possibility for crash which may pass the tests, yet is
non-acceptable in the final product (similarily to assert).
BS> When the unexpected exception occurs, you then know to fix one side of the
BS> interface to match the other: either you re-design the caller to expect the
BS> new exception, or you re-code the callee to throw something that's already
BS> expected.
_If_ it occurs.
The win, I admit, is for the cases when the compiler will find the
problem.
Best Regards!
--
Marc Girod Nokia Telecommunications INS/IPS/MS/NOMA
Valimo 1/2 P.O. Box 315 Phone: +358-9-511 63331
00380 Helsinki 00045 NOKIA Group Fax: +358-9-511 63310
Finland marc.girod@ntc.nokia.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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1997/11/07 Raw View
Leif Rilbe wrote:
>
> Does anyone know anything about the rationale for not enforcing this
> guarantee at compile time? Seems to me that the lack of compile time
> check makes the mechanism far less usable than it would be otherwise.
> Especially a compile time check of the empty exception specification
> would be very useful for writing exception safe code.
The canonical example of why it isn't checked at compile time is
this:
extern double sqrt(double) throw(domain_error);
double sqrt_abs(double x) throw() {
return sqrt(x < 0 ? -x : x);
}
The compiler would detect a static violation of the exception
specs that could never occur in practice.
--
Ciao,
Paul
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Bradd W. Szonye" <bradds@concentric.net>
Date: 1997/11/04 Raw View
Marc Girod wrote in message <1yd8kicvm7.fsf@dshp01.trs.ntc.nokia.com>...
>>>>>> "SF" == Stanley Friesen <sarima@ix.netcom.com> writes:
>
>SF> When [exception specifications are]
>SF> used *systematically* throughout a project, they can lead to
>SF> significant optimizations, and to better control of error propagation.
>SF> They also help find bugs in your program.
>
>This is 3 arguments, ok? ...
>The 3rd is fighting in an other series. You are now using exceptions
>for "debugging", i.e. as an extension of assert: stop right now in
>catastrophe; this code will not make it to production...
I believe that you misread this. The claim is not that exceptions help in
debugging, but that exception-specifications do. In other words, it's
possible that you accidentally throw an exception that the caller is not
prepared to catch. (Or that a maintenance change adds a thrown exception
that the original handler was not prepared for.)
When the unexpected exception occurs, you then know to fix one side of the
interface to match the other: either you re-design the caller to expect the
new exception, or you re-code the callee to throw something that's already
expected.
---
Bradd W. Szonye
bradds@concentric.net
http://www.concentric.net/~Bradds
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: sarima@ix.netcom.com (Stanley Friesen)
Date: 1997/11/02 Raw View
Marc Girod <girod@trshp.trs.ntc.nokia.com> wrote:
>Exception Specification" (C++ Report, Vol 8, Nr 7, July 1996). (I
>simplify): forget about exception specifications.
Bunk.
When used *systematically* throughout a project, they can lead to
significant optimizations, and to better control of error propagation.
They also help find bugs in your program.
The peace of God be with you.
Stanley Friesen
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Marc Girod <girod@trshp.trs.ntc.nokia.com>
Date: 1997/11/03 Raw View
>>>>> "SF" == Stanley Friesen <sarima@ix.netcom.com> writes:
SF> When used *systematically* throughout a project, they can lead to
SF> significant optimizations, and to better control of error propagation.
SF> They also help find bugs in your program.
This is 3 arguments, ok?
I admit I am defenseless to the first.
The 2nd was taken into consideration by Meyers and Reeves. If nothing
has changed since they wrote histheir advices, I still hold them for
valid.
The 3rd is fighting in an other series. You are now using exceptions
for "debugging", i.e. as an extension of assert: stop right now in
catastrophe; this code will not make it to production...
I claim that this is an unacceptable strategy. I clashes with reuse:
there is not two global states of the code (development/production).
Therefore, the catastrophes that exception specifications introduce
are unbearable.
This leads to placing under scrutiny what you may mean by
"systematically". Hopefully you don't mean: forbidding the use of
templates, restricting virtual functions and typedefs, etc.
You would be throwing the baby with the bath water. And barring that,
one cannot use exception specifications *systematically*, can one?
What you may also mean is catching unknown exceptions and converting
them. But the result is worst than the initial situation: loosing
information and building design bottlenecks.
SF> The peace of God be with you.
Argh! I wasn't prepared to catch this one :-)
Best Regards!
--
Marc Girod Nokia Telecommunications INS/IPS/MS/NOMA
Valimo 1/2 P.O. Box 315 Phone: +358-9-511 63331
00380 Helsinki 00045 NOKIA Group Fax: +358-9-511 63310
Finland marc.girod@ntc.nokia.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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Leif Rilbe <leif_rilbe@hotmail.com>
Date: 1997/11/04 Raw View
Jerry Leichter wrote:
>
> | ...i just read about exception specifications but i do not really
> understand where and when should i use them....
> |
> | // ------
> | // somewhere here goes the defintions of classes A and B...
> |
> | void f(int i) throw(A); // function declaration
> |
[...]
>
> What the specification for f() above guarantees is that no caller for
> f() will ever see an exception emerge from f() that is not (derived
> from) A. This is a *run-time* guarantee, and compilers are actually
> required to accept code that, on its face, violates it: The violation
> can be eliminated at run time, and the programmer is allowed to try.
> (Nevertheless, a good compiler should probably be able to emit a
> warning, as designing your application around such fixups seems
> dangerous.)
> -- Jerry
Does anyone know anything about the rationale for not enforcing this
guarantee at compile time? Seems to me that the lack of compile time
check makes the mechanism far less usable than it would be otherwise.
Especially a compile time check of the empty exception specification
would be very useful for writing exception safe code. Are there any
changes in the works in this regard?
/Leif
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Marc Girod <girod@trshp.trs.ntc.nokia.com>
Date: 1997/10/28 Raw View
Er... to answer the original question:
> ...i just read about exception specifications but i do not really
> understand where and when should i use them....
Let me check that nothing has changed since Scott Meyers' advice in
"More Effective C++" , Item 14, or Jack Reeves' in "Ten Guidelines for
Exception Specification" (C++ Report, Vol 8, Nr 7, July 1996). (I
simplify): forget about exception specifications.
There is no reason whatsoever to use them in any case.
Any use will only make things worse, at the least, loose information
(A special case for working with CORBA, which uses them).
Best Regards!
--
Marc Girod Nokia Telecommunications INS/IPS/MS/NOMA
Valimo 1/2 P.O. Box 315 Phone: +358-9-511 63331
00380 Helsinki 00045 NOKIA Group Fax: +358-9-511 63310
Finland marc.girod@ntc.nokia.com
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Jerry Leichter <leichter@smarts.com>
Date: 1997/10/22 Raw View
| ...i just read about exception specifications but i do not really
understand where and when should i use them....
|
| // ------
| // somewhere here goes the defintions of classes A and B...
|
| void f(int i) throw(A); // function declaration
|
| void main()
| {
| try
| {
| f(10);
| }
| catch (A a)
| {
| // some code here
| }
| catch (B b)
| {
| // some code here
| }
| }
|
| void f(int i) // function definition
| {
| B b;
|
| throw b;
| }
| // ------
|
| is it correct to be able to throw an exception with an class B
| parameter from inside the f() function, since i declared that function
| with the exception specification "throw(A)" ? ...
If B is derived from A, this would be legal (though in that case the
catch clauses in your try statement should be the other way around).
Otherwise, the *run-time* behaviour is fully defined: The throw of b in
f() will be turned into a call to std::unexpected(), which by default
calls std::terminate() (which by default terminates the program). It's
possible to replace either of these functions using set_unexpected() or
set_terminate(). (Also, if the exception specification includes the
built-in type std::bad_exception, an exception not otherwise on the list
is re-thrown as a std::bad_exception.)
Note that this isn't *illegal*. You can define your own "unexpected"
function to throw some exception that *is* in the specification. (The
std::bad_exception mechanism is a built-in mechanism for doing this.)
What the specification for f() above guarantees is that no caller for
f() will ever see an exception emerge from f() that is not (derived
from) A. This is a *run-time* guarantee, and compilers are actually
required to accept code that, on its face, violates it: The violation
can be eliminated at run time, and the programmer is allowed to try.
(Nevertheless, a good compiler should probably be able to emit a
warning, as designing your application around such fixups seems
dangerous.)
-- Jerry
---
[ 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
]
[ FAQ:
http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy:
http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu
]
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: "Ray Brown" <Ray.Brown@lawson.com>
Date: 1997/10/22 Raw View
I believe that your code should compile, but that the program should
terminate instead of propagating B out of f (unless B is derived from A or
you do something special in your unexpected_handler). As I understand it,
conformance to the exception specification for the general case can be
checked at run time only.
All of this is moot in your case, though, since VC5 does not yet support
exception specifications.
--
________________________________________________________________
Ray Brown Home: (612) 892-7329
Lawson Software Office: (612) 379-8086 x4393
1300 Godward Street Fax: (612) 379-8512
Minneapolis, MN 55413-3004 Email: Ray.Brown@lawson.com
________________________________________________________________
TytySoft wrote in message ...
>void f(int i) throw(A); // function declaration
>
>void main()
>{
> try
> {
> f(10);
> }
> catch (A a)
> {
> // some code here
> }
> catch (B b)
> {
> // some code here
> }
>}
>void f(int i) // function definition
>{
> B b;
> throw b;
>}
>anyway, i was able to compile this chunk of code with the Visual C++ 5.0
>compiler...
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: Jerry Leichter <leichter@smarts.com>
Date: 1997/10/23 Raw View
| ...i just read about exception specifications but i do not really
understand where and when should i use them....
|
| // ------
| // somewhere here goes the defintions of classes A and B...
|
| void f(int i) throw(A); // function declaration
|
| void main()
| {
| try
| {
| f(10);
| }
| catch (A a)
| {
| // some code here
| }
| catch (B b)
| {
| // some code here
| }
| }
|
| void f(int i) // function definition
| {
| B b;
|
| throw b;
| }
| // ------
|
| is it correct to be able to throw an exception with an class B
| parameter from inside the f() function, since i declared that function
| with the exception specification "throw(A)" ? ...
If B is derived from A, this would be legal (though in that case the
catch clauses in your try statement should be the other way around).
Otherwise, the *run-time* behaviour is fully defined: The throw of b in
f() will be turned into a call to std::unexpected(), which by default
calls std::terminate() (which by default terminates the program). It's
possible to replace either of these functions using set_unexpected() or
set_terminate(). (Also, if the exception specification includes the
built-in type std::bad_exception, an exception not otherwise on the list
is re-thrown as a std::bad_exception.)
Note that this isn't *illegal*. You can define your own "unexpected"
function to throw some exception that *is* in the specification. (The
std::bad_exception mechanism is a built-in mechanism for doing this.)
What the specification for f() above guarantees is that no caller for
f() will ever see an exception emerge from f() that is not (derived
from) A. This is a *run-time* guarantee, and compilers are actually
required to accept code that, on its face, violates it: The violation
can be eliminated at run time, and the programmer is allowed to try.
(Nevertheless, a good compiler should probably be able to emit a
warning, as designing your application around such fixups seems
dangerous.)
-- Jerry
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: "TytySoft" <amoga@aspdeveloper.net>
Date: 1997/10/21 Raw View
hi,
i'd like to ask for assistance someone who have experinece working with
exceptions. the problem is: i just read about exception specifications but i
do not really understand where and when should i use them.
please take a look at the following code:
// ------
// somewhere here goes the defintions of classes A and B...
void f(int i) throw(A); // function declaration
void main()
{
try
{
f(10);
}
catch (A a)
{
// some code here
}
catch (B b)
{
// some code here
}
}
void f(int i) // function definition
{
B b;
throw b;
}
// ------
is it correct to be able to throw an exception with an class B parameter
from inside the f() function, since i declared that function with the
exception specification "throw(A)" ?
if it is correct, what is the use of exception specifications anyway?
i thought by using exception specifications i'm telling to the compiler to
check for incorrect throw statements _inside_ the function bounded by the
specifications... am i wrong here?
anyway, i was able to compile this chunk of code with the Visual C++ 5.0
compiler...
any help will be greatly appreciated.
AM
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Ray Brown" <Ray.Brown@lawson.com>
Date: 1997/10/22 Raw View
I believe that your code should compile, but that the program should
terminate instead of propagating B out of f (unless B is derived from A
or
you do something special in your unexpected_handler). As I understand
it,
conformance to the exception specification for the general case can be
checked at run time only.
All of this is moot in your case, though, since VC5 does not yet support
exception specifications.
--
________________________________________________________________
Ray Brown Home: (612) 892-7329
Lawson Software Office: (612) 379-8086 x4393
1300 Godward Street Fax: (612) 379-8512
Minneapolis, MN 55413-3004 Email: Ray.Brown@lawson.com
________________________________________________________________
TytySoft wrote in message ...
>void f(int i) throw(A); // function declaration
>
>void main()
>{
> try
> {
> f(10);
> }
> catch (A a)
> {
> // some code here
> }
> catch (B b)
> {
> // some code here
> }
>}
>void f(int i) // function definition
>{
> B b;
> throw b;
>}
>anyway, i was able to compile this chunk of code with the Visual C++
5.0
>compiler...
---
[ 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
]
[ FAQ:
http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy:
http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu
]
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: Gerhard Menzl <gerhard.menzl@sea.ericsson.se>
Date: 1997/10/22 Raw View
TytySoft wrote:
> is it correct to be able to throw an exception with an class B parameter
> from inside the f() function, since i declared that function with the
> exception specification "throw(A)" ?
>
> if it is correct, what is the use of exception specifications anyway?
>
> i thought by using exception specifications i'm telling to the compiler to
> check for incorrect throw statements _inside_ the function bounded by the
> specifications... am i wrong here?
>
> anyway, i was able to compile this chunk of code with the Visual C++ 5.0
> compiler...
>
> any help will be greatly appreciated.
> AM
According to 15.5 ARM,
"An implementation may not reject an expression simply because it may
throw an exception not specified in an exception-specification of the
function containing the expression; the handling of violations of an
exception-specification is done at run-time."
and:
"An attempt by a function to throw an exception not in its exception
list will cause a call of the function unexpected()."
The way I read this is: if you throw an exception from a function that
is not in the exception list of that function, your compiler won't
complain, but your program will be terminated when the unspecified
exception occurs. For me, this is a major reason for not using
exception specifications.
Gerhard Menzl
---
[ 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
]
[ FAQ:
http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy:
http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu
]
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: "Ray Brown" <Ray.Brown@lawson.com>
Date: 1997/10/22 Raw View
I believe that your code should compile, but that the program should
terminate instead of propagating B out of f (unless B is derived from A or
you do something special in your unexpected_handler). As I understand it,
conformance to the exception specification for the general case can be
checked at run time only.
All of this is moot in your case, though, since VC5 does not yet support
exception specifications.
--
________________________________________________________________
Ray Brown Home: (612) 892-7329
Lawson Software Office: (612) 379-8086 x4393
1300 Godward Street Fax: (612) 379-8512
Minneapolis, MN 55413-3004 Email: Ray.Brown@lawson.com
________________________________________________________________
TytySoft wrote in message ...
>void f(int i) throw(A); // function declaration
>
>void main()
>{
> try
> {
> f(10);
> }
> catch (A a)
> {
> // some code here
> }
> catch (B b)
> {
> // some code here
> }
>}
>void f(int i) // function definition
>{
> B b;
> throw b;
>}
>anyway, i was able to compile this chunk of code with the Visual C++ 5.0
>compiler...
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]
Author: Geoffrey Phipps <phipps>
Date: 10 Feb 1995 05:21:56 GMT Raw View
I am trying to upgrade a 2.0 C++ grammar to ARM May 1992.
In particular I am adding the exception syntax, but
I can't work out exactly where to put Exception
Specifications.
The ARM just gives some examples:
15.5, p363
void f() throw (X,Y)
{
...
}
Using the grammar from the back of the book,
the example shows that exception-specification goes somewhere
between the declarator and the fct-body, but it doesn't
tell me which side if the ctor-initializer.
A similar quesion arises with function decls, for example:
extern void f() throw (X, Y);
Where does that fit? Up at decl after declarator? down in
declarator after ( argument -declaration-list ) ?
Or has the whole thing changed again?
thanks,
Geoffrey Phipps