Thread View: comp.std.c++
3 messages
3 total messages
Started by dak
Thu, 07 Dec 1995 18:28
Re: throw declarations
Author: dak
Date: Thu, 07 Dec 1995 18:28
Date: Thu, 07 Dec 1995 18:28
62 lines
2328 bytes
2328 bytes
clamage@Eng.Sun.COM (Steve Clamage) wrote:
>
> In article 41C67EA6@ecid.cig.mot.com, Joe Walker <walkerjj@ecid.cig.mot.com> writes:
> >
> >As I understand the DWP this is legal:
> >
> > void func () throw ()
> > {
> > throw 1;
> > }
> >
> >The question is, why?
> >Surely this should be a compiler error.
>
> It is an error if the throw statement is executed, but not otherwise.
> That is, "func" might not ever be called.
>
But how does this affect the fact that it throws when it says it doesn't ?
A function returning the wrong type will cause a compiler disgnostic even
if it is never called (it could be checked at run time...)
> That may sound like nit-picking, but it avoids having to
> decide whether examples like the following are valid:
>
> void f1(int j) throw()
> {
> if( j == 0 )
> throw 1; // the programmer believes j is always > 0
> }
>
> #include <math>
> void f2(unsigned x) throw()
> {
> if( std::sqrt((double)x) ) < 0.0 )
> throw 1; // really can't happen, but must compiler deduce that?
> }
Why the need to decide ? Again, comparison with return value, IMO, shows
that not to be a valid reason. I believed that the real reason was to
somehow relax the design of templates and allow a wider range of types to
be use (and resolve any design error at run-time). All time seems quite
contrary to the rest of the C++ design which is to check things at
compile time.
While I understand that some people may think it necessary to allow
non-throwing functions to call functions without throw specs, or even
functions with throw specs, I don't see how it can extent to actual throw
expression...
So am I right to think the rule was decided upon due to templates ?
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: throw declarations
Author: Steve Clamage
Date: Fri, 08 Dec 1995 17:23
Date: Fri, 08 Dec 1995 17:23
99 lines
4372 bytes
4372 bytes
In article 100000@zorglub.cae.ca, dak <pierreba@poster.cae.ca> writes:
>clamage@Eng.Sun.COM (Steve Clamage) wrote:
>> In article 41C67EA6@ecid.cig.mot.com, Joe Walker <walkerjj@ecid.cig.mot.com> writes:
>> >
>> >As I understand the DWP this is legal:
>> >
>> > void func () throw () // #1
>> > {
>> > throw 1;
>> > }
>> >The question is, why?
>> >Surely this should be a compiler error.
>> It is an error if the throw statement is executed, but not otherwise.
>> That is, "func" might not ever be called.
>But how does this affect the fact that it throws when it says it doesn't ?
>A function returning the wrong type will cause a compiler disgnostic even
>if it is never called (it could be checked at run time...)
The difference is that the return type of a function is known statically.
The runtime behavior of a program cannot in general be known until runtime.
More below.
>> That may sound like nit-picking, but it avoids having to
>> decide whether examples like the following are valid:
>>
>> void f1(int j) throw() // #2
>> {
>> if( j == 0 )
>> throw 1; // the programmer believes j is always > 0
>> }
>>
>> #include <math>
>> void f2(unsigned x) throw() // #3
>> {
>> if( std::sqrt((double)x) ) < 0.0 )
>> throw 1; // really can't happen, but must compiler deduce that?
>> }
>
>
>
>Why the need to decide ?
We are talking about the standard. It must define what is well-formed code
and what is not. The number of valid C++ functions having throw expressions
is unbounded, so the standard cannot simply list all the valid functions.
It must instead provide a method for determining whether an as-yet
undreamed-of function is valid.
Example #1 above is clearly invalid in the sense that it will always result
in a call to unexpected(). But what do we say in the standard to make it a
compile-time error? The rule would have to involve determining whether
the throw expression would be executed. In the general case (and the
standard must deal with the general case) that is impossible -- it is
equivalent to solving the halting problem.
In example #2, we cannot know whether the throw expression will be
executed. Is the function valid? If so, why? If not, why not? (Don't
answer yet.)
Example #3 looks a lot like #2, but the difference is that according to
the semantics of "unsigned" and "std::sqrt(double)", the throw expression
can never be executed -- the "if" condition is always false. If #2
is invalid, what sort of compile-time analysis do we require compilers to do
in order to allow #3? If #3 is to be invalid, how about if we replace it with
if(0) throw 1;
Don't answer my questions yet, because I have one more example:
void g(); // has no throw-specification, can throw anything
void f4() throw() // #4
{
g(); // valid or not?
}
The current rule, related to the original question, is that function f4
is OK, and an error results only if g actually exits via an exception.
The alternative would be to require that every function called have an
exception specification at least as restrictive as the calling function.
Such a rule would make exceptions specifications completely useless.
Any answers about #1, #2 and #3 must also make sense with regard to #4.
If #4 is valid, how can #2 be invalid? If #2 is valid, how do we write
a rule that makes #1 invalid? You can't make rules like "If the flow of
control must pass through ..." because in general that is unknowable.
---
Steve Clamage, stephen.clamage@eng.sun.com
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: throw declarations
Author: Sam Fenster
Date: Sat, 09 Dec 1995 07:16
Date: Sat, 09 Dec 1995 07:16
72 lines
4617 bytes
4617 bytes
>>> Joe Walker <walkerjj@ecid.cig.mot.com> writes:
>>>> As I understand the DWP this is legal:
>>>> void func () throw () {throw 1;}
>>>> The question is, why? Surely this should be a compiler error.
>> clamage@Eng.Sun.COM (Steve Clamage) wrote:
>>> It is an error if the throw statement is executed, but not otherwise.
>>> That is, "func" might not ever be called.
> dak <pierreba@poster.cae.ca> writes:
>> But how does this affect the fact that it throws when it says it doesn't ?
>> A function returning the wrong type will cause a compiler disgnostic even
>> if it is never called (it could be checked at run time...)
clamage@Eng.sun.com (Steve Clamage) writes:
> The difference is that the return type of a function is known statically.
> The runtime behavior of a program cannot in general be known until runtime.
As dak just said, you could say that about a conditional return statement too.
In fact, you're being disingenuous. This issue was debated here a while back
by people (including you, I'm sure) who all had valid points of view. No one
claimed that compile-time exception type checking couldn't be done. They just
argued its safety versus its oppressive restrictiveness.
It would be perfectly reasonable for the compiler to disallow any throw
statement whose exception type is not handled by an enclosing handler and not
declared in the enclosing function's exception signature. Furthermore, it
would also be perfectly reasonable to disallow implied or explicit calls of
functions whose exception signatures specify that they *might* throw such a
type at run time.
Contrary to what you say, an exception signature is very much like a return
type. Both can be enforced at compile time. In fact, in Modula-3, a function
return is considered a kind of exception throw!
With compile-time exception type checking, there would be complete run-time
exception safety. No unexpected exceptions would ever occur. And it would
still allow the style of programming where exceptions are not specified at
compile time, via the `throw (...)' ("throws anything") construct, which is
the default in the absence of an exception signature! It would be much like
const-correctness, a style which is available to C and C++ programmers, but
need not be used.
There *would* be problems: Libraries whose functions used the `throw-anything'
style would need wrappers when used by code that used the `specific exception
signatures' style. Template code, in particular, would be troublesome -- the
text of the template could not be written knowing what the functions it called
might throw. Also, functions would need ungainly exception signatures or
catch clauses, since they would all need to include a cumbersome list of
standard exceptions that could be generated by often-used (standard and
vendor) library routines and operators.
So you could make a valid argument that compile-time restriction would hamper
programmers too much. But it's certainly debatable. And you can't plausibly
argue that compile-time enforcement can't be done!
> Don't answer my questions yet, because I have one more example:
> void g(); // has no throw-specification, can throw anything
> void f4() throw() {g();}
>
> The current rule, related to the original question, is that function f4
> is OK, and an error results only if g actually exits via an exception.
> The alternative would be to require that every function called have an
> exception specification at least as restrictive as the calling function.
> Such a rule would make exceptions specifications completely useless.
Maybe, maybe not. Doesn't Modula-3 do it? (I'm not sure.)
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads