throw non-exception objects
From a viewpoint of practicality, there is almost1 no application for throwing string
s, int
s, or anything else that isn't derived from std::exception
.
This isn't because there's no indication for doing so, but because there are contra-indications that suggest why you shouldn't.
There are two main reasons why you wouldn't want to throw anything that's not derived from std::exception
:
- Exception safety. If you throw, for example, a
std::string
and the construction or copy of thatstring
raises another exception,terminate
will be called and your process will cease to exist. You'll never get a chance tocatch
thatstd::string
. - Usability. Throwing derivitaves of
std::exception
makes it possible tocatch (const std::exception&)
in a generic fashion. If you throw something else, you will need acatch
for that case.
A good discussion of exceptions can be found here.
1 Almost no application [...]: There are exclusions to every rule, but even in acknowledging this, I have never seen a legitimate exclusion to throwing a derivitave of std::exception
.
I'm not sure what prompted the question, since you are free to choose the "application" in such cases as you see fit.
The purpose of an exception of object is to indicate the fact that an exception occurred and, usually, to carry some exception-specific information with it from the thrower to the handler. If some type is sufficient for that purpose in your application, then you can use that type as "exception" type. You can throw int
values, std::string
values and anything else, if you want. It is entirely up to you.
If all you want to carry from the thrower to the handler is an int
value, then type int
will serve that purpose as an "exception" type. That's all there is to it.
C++ does not impose any specific requirements on the types you can throw. For this reason, there is really no such thing as "exception" type or "non-exception" type. What is "exception type" and what is not is determined by you and only by you in your code. You can throw anything, as long as you know how to catch it and how to interpret what you caught.
The first benefit of using class types to represent exceptions is that class types are freely user-definable, i.e. you can easily define as many exception types as you want. Then you can use many independent, non-interfering exception "flows" that throw and catch only exceptions of their respective types.
The second benefit of using class types to represent exceptions is that class types are easily extensible. I.e. at any moment you can add an additional "payload" information to your exception type, and that payload will be carried from the point where the exception was thrown to the point where it is caught and handled.
If you are not interested in any of these benefits, you can simply throw and catch values of type int
to represent your exceptions. This will work. But I'm almost sure you will quickly run into the limitations of this approach with regard to both maintenance and extensibility.
More of a hack rather than a language feature, you could throw an object and then catch it to force a function to "return" something different than its normal return type.
int aFunc()
{
throw foo(); // if you catch that foo, you 've imitated returning foo
return 0; // ok just an int
}
This would ofcourse be a terrible design choice and a violation of type safety offered by C++ but say you have a function heavily used in a huge code base and you want to try some change (which involves altering the return type) then that would be dirty way of trying something out before actually implementing the change (and grep the whole code base to do changes)
EDIT:
You should read the post more carefully. I 've said "a terrible design choice" and "a violation of type safety offered by C++" and "before actually implementing the change". If that is not enough of a warning I don't think those comments or downvotes would be.
On the other hand try altering the return type of a function used 666 times in a code base of 6e06 lines to find out that it's not what you want after you've uploaded it on your version control system and broke the compile multiple times for developers working on other plattforms than you.
If there was a shortcut wouldn't you want to know about it? Wouldn't you use it until implementing the change and actually posting it to your code base?
Even if the answer to those questions is "NO" I thought this post was about exploring possibilities, and just mentioning one is not per se 'evil'. I personally heard this one from a Bjarne's talk http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/Keynote-Bjarne-Stroustrup-Cpp11-Style who afterwards said the same things about not using such things.
You throw whatever you wants, it will always be an exception as you throw it. The standard library use classes inherited from std::exception and this is a design choice.
If you feel like throwing an enumeration is enough for needs, as an example, why enforce you to throw an object…