I just saw this question and its related answers. Considering I never ran into this way of using
throws before, I was quite surprised to find out this is even possible.
- What's the logic behind allowing (almost) anything to be thrown and caught?
- Is there a use of the throw-catch syntax that goes beyond exception/error signaling? And if so, is that considered bad practice or are there "common" usages of this I was never aware of?
This is hard to answer without speculation, but Bjarne's 1998 paper "An Overview of the C++ Programming Language" uses arbitrary types when describing exception handling, and suggests creating a hierarchy of said types for convenient/semantics. It would seem that he did not have a "base class" of
exception in mind for any of these in the beginning.
It's possible that the notion of having a standard hierarchy (based on
std::exception) began life as an "addition", a convenient way to approach Bjarne's suggested use of exceptions, rather than the building-blocks on which everyone's use of exceptions should be based. That contemporary practice is to derive all exceptions from
std::exception would seem to have come along later.
Nowadays, I can't think of a good reason not to do that, if for no other reason than people using your code will probably expect a top-level
catch (const std::exception&) to suck up anything useful. I do also tend to put a
catch (...) in
main, though, just in case.
Speaking more practically, if this weren't the case, there would have to be additional rules constraining
throw to only be "valid" on expressions with type deriving from
std::exception, which would not seem to have any real-world benefit sufficient to justify the additional rules. C++, believe it or not, comes from a place of minimalism in terms of the question "why don't we have such-and-such a rule", although obviously its bloat would seem to contradict this after all these years.
I doubt this has anything to do with using
throw for non-exceptional things, because that has always been considered bad practice. The way Bjarne describes this feature is:
Exceptions are used to transfer control from a place where an error is detected to some caller that hasexpressed interest in handling that kind of errors. Clearly, this is a mechanism that should be used only for errors that cannot be handled locally. [..] Exceptions can be used to make error handling more stylized and regular.
So it's clear that at least the original design intent (and, again, this is still common wisdom) is to use exceptions for exceptional/errory cases only.