What is the technical reason why it is considered bad practice to use the C++ throw keyword in a function signature?
bool some_func() throw(myExc)
{
...
if (problem_occurred)
{
throw myExc("problem occurred");
}
...
}
What is the technical reason why it is considered bad practice to use the C++ throw keyword in a function signature?
bool some_func() throw(myExc)
{
...
if (problem_occurred)
{
throw myExc("problem occurred");
}
...
}
No, it is not considered good practice. On the contrary, it is generally considered a bad idea.
http://www.gotw.ca/publications/mill22.htm goes into a lot more detail about why, but the problem is partly that the compiler is unable to enforce this, so it has to be checked at runtime, which is usually undesirable. And it is not well supported in any case. (MSVC ignores exception specifications, except throw(), which it interprets as a guarantee that no exception will be thrown.
Jalf already linked to it, but the GOTW puts it quite nicely why exception specifications are not as useful as one might hope:
int Gunc() throw(); // will throw nothing (?)
int Hunc() throw(A,B); // can only throw A or B (?)
Are the comments correct? Not quite.
Gunc()may indeed throw something, andHunc()may well throw something other than A or B! The compiler just guarantees to beat them senseless if they do… oh, and to beat your program senseless too, most of the time.
That's just what it comes down to, you probably just will end up with a call to terminate() and your program dying a quick but painful death.
The GOTWs conclusion is:
So here’s what seems to be the best advice we as a community have learned as of today:
- Moral #1: Never write an exception specification.
- Moral #2: Except possibly an empty one, but if I were you I’d avoid even that.
The only practical effect of the throw specifier is that if something different from myExc is thrown by your function, std::unexpected will be called (instead of the normal unhandled exception mechanism).
To document the kind of exceptions that a function can throw, I typically do this:
bool
some_func() /* throw (myExc) */ {
}
When throw specifications were added to the language it was with the best intentions, but practice has borne out a more practical approach.
With C++, my general rule of thumb is to only use throw specifications to indicate that a method can't throw. This is a strong guarantee. Otherwise, assume it could throw anything.