I just ran some code I had under the new VC7.1 beta and noticed that it is
now complaining about code such as this:
class MyException;
void Function() throw(MyException);
It complains saying that MyException is not a complete type which it isn't.
This is new to me so I did a little research into the standard and came
across this:
"A type denoted in an exception specification shall not denote an incomplete
type. A type denoted in an exception specification shall not denote a
pointer or reference to an incomplete type, other than void*, const void*,
volatile void*, or const volatile void*."
So far so good - I see VC++ is just doing what is correct. Now what about
the following though:
class MyException
{
public:
static void Throw() throw(MyException)
{
throw MyException();
}
};
Of course - this has the same issue since MyException is not completely
defined at the point it is being used in an exception specification. My
problem is how can I declare an exception specification for my function if
the function itself is a member of the class? I tend to always delegate the
actual throw to a static member of the class so this is something that is
going to greatly affect me. Is there anything I can do?
Thanks
Why are you using exception specifications at all? They must be one of the
worst thought out bits of C++.
NeilB
Fair enough. Personally I agree with both sides but I tend to lean a bit
more to using them when possible. If you know what a function throws you
might as well put it there. If you put them and are wrong then you will
quickly find out (yes.. not in VC++). If you don't use them and are wrong in
the documentation then I would argue that 'just as bad' things could happen.
Another argument I would make for using them is that it is a 'standard' way
of mentioning what exceptions can be thrown. This can be used in tools such
as lint to actually let you know that you may be missing a catch. I would
prefer that the C++ compiler did this (like Java) but I will take what I can
get.
Don't blame VC++ for this one. There is no way the compiler can be sure that
another type of exception won't be thrown no matter what your specification
reads. And if that happens it just causes the program to fail in a different
way. How does that help you? Neil is right -- this is probably the only
feature of C++ which is downright silly.
The only silliness of ES is the mandatory unwinding way up to the
injected SILLY catch(...) [in a sort of function-try-block]. Other
than that, blame yourself please... for being unable to comprehend
the reasoning behind ES.
regards,
alexander.
Some other considerations regarding the use of ES:
http://www.gotw.ca/publications/mill22.htm
http://www.gotw.ca/gotw/082.htm
--
Peter van Merkerk
merkerk(at)turnkiek.nl
http://groups.google.com/groups?selm=3DAFEBE3.8473B83C%40web.de
(Subject: Re: Doug McIlroy on exception handling)
> http://www.gotw.ca/gotw/082.htm
http://groups.google.com/groups?selm=3C77AFCB.481D2587%40web.de
(Subject: Re: Guru of the Week #82: Solution)
regards,
alexander.
Guess I'll have to join the list of self-blamers. (At least I'm in
good company.) I think I understand how exception specifications work,
and I've followed the arguments several times for why they were added,
but I still can't *comprehend* why they're a good idea.
P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Even throw()? (a bit more difficult to comprehend throw-something ones
aside for a moment)
regards,
alexander.
Referring to C++PL Stroustrup advocates the use of ES only on major
interfaces. This seems reasonable to me, I imagine this would be a
relatively small number of functions that declare they throw only a
root exception of that system. These functions can ensure that
std::unexpected() is not called by locally overriding the handler
(14.6.3.1). It is then part of the specification of the library/system
that std::unexpected is never called in such a way that terminate() is
called.
I agree with most other comments against the use of ES, they are a
nuisance in Java. One example being a function that uses another
library function that throws an exception. Either this (checked)
exception must be declared to be propagated or caught and mapped. This
has its merits (and correctness) but often I can trivially assert it
will not be thrown through testing (in the absense of libary errors).
Eventually the system deteriates into half the code being try/catch
blocks mapping exceptions or declaring Exception to be thrown on every
interface. The c++ implemetation avoids this by having the
std::unexpected() loophole, but that is only marginally more appealing
to me. Another example is a function that declares it throws nothing,
if the implementation is changed to use an exception throwing function
what do I do? This violates all that is good about implementation
hiding.
I never use ES (my compiler doesn't support it anyway). I find Doxygen
a far better way to document my code without incuring any runtime
problems.
Pete
There was an article in The Java Report a couple years ago which
advocated using unchecked exceptions in order to avoid this nuisance.
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Well, how would that nice "root exception" help you to RECOVER?
http://groups.google.com/groups?selm=3D7343D4.5AB30F1B%40web.de
(Subject: Re: Non throwing stl like containers)
> These functions can ensure that std::unexpected() is not called by
> locally overriding the handler (14.6.3.1).
Unfortunately, you can't override unexpected() [and terminate() for
that matter] handler *locally*.
http://groups.google.com/groups?selm=3D326BB4.96F72607%40web.de
(Subject: Re: Is internal catch-clause rethrow standard?)
[...]
> I agree with most other comments against the use of ES, they are a
> nuisance in Java.
Well, yeah, Java's EH is totally busted, right. ;-)
http://groups.google.com/groups?selm=3C729687.3A8A462%40web.de
http://groups.google.com/groups?selm=3C73AB86.99B8CBE0%40web.de
(Subject: Re: Guru of the Week #82: Solution)
regards,
alexander.
--
"upgrade n. Wholesale bug replacement." -<http://tinyurl.com/3ef9>
Can anyone comment on how exceptions might look in C++0x?
--
--- remove zees if contacting by email ---
OK, I'm game. Please explain why I would want to write a throw()
specification.
virtual const char * what() const throw();
const std::string & why() const;
void raise() throw(xmsg);
private:
std::string *str;
};
I don't know what the macro expands to.
Fraser.
That doesn't help in the general case since 3rd party libraries will
most likely use checked exceptions as the language advocates. Unless
of course each libary has a wrapper around it to map them to runtime
exceptions.
It doesn't but it's an indication of what a major interface might look
like in my mind.
> http://groups.google.com/groups?selm=3D7343D4.5AB30F1B%40web.de
> (Subject: Re: Non throwing stl like containers)
>
> > These functions can ensure that std::unexpected() is not called by
> > locally overriding the handler (14.6.3.1).
>
> Unfortunately, you can't override unexpected() [and terminate() for
> that matter] handler *locally*.
Well as good as ...
From C++PL
class STC {
unexpected_handler old;
public:
STC(unexpected_handler f) {old = set_unexpected(f);}
~STC() {set_unexpected(old);}
};
class Yunexpected : public Yerr {};
void throwY() throw(Yunexpected) {throw Yunexpected ();}
void dosomething() throw(Yerr)
{
STC sentry(&throwY);
//do stuff
}
of course we could have
void dosomething() throw(Yerr, std::bad_exception);
Thank you.
> Please explain why I would want to write a throw() specification.
Nah, first you should spend another 18 (+1) bucks [IEEE/?ACM?-member
discount aside] on the following PDF:
http://www.computer.org/concurrency/pd2000/p4072abs.htm
("C++ Exception Handling", Christophe de Dinechin,
IEEE Concurrency October-December 2000 (Vol. 8, No. 4))
regards,
alexander.
P.S. Heck, a couple of months ago the price was just 10! They seemed
to have "aligned" it recently with the Std.C++ pricing, so to speak.