Reputation: 27592
C++
allows throw
ing any kind of objects. From exception
s to string
and even int
.
But I've never seen any real world application of throw
ing anything other than exception
s.
My question is, what is the application for throw
ing non-exception
objects?
Upvotes: 15
Views: 4363
Reputation: 2671
I do not agree with the general notion that only derivatives of std::exception
should be thrown. Of course I can agree that throwing objects with complex data or behaviour can be very problematic and should only be done with great care.
However that neither implies any restriction on the inheritance hierarchy of the thrown type, nor on the way (or the reasons why) stack unwinding is employed by your application. And the throw
operation is just that: a clean and well-defined way of unwinding the stack up to a defined point (the matching catch
) without having to involve explicit handlers in the intermediate frames.
And of course there are legitimate use cases for throwing that do not imply that an error or anything exception
-al is happening. Think for example of a simple language interpreter, where the host language stack corresponds to the guest language stack. To implement interleaved parallelism in the guest language, stack unwinding is exactly what you need to do when a guest operation blocks (or yields). You want to unwind up to the starting point of the parallelism and try the next of the parallel branches. That situation is neither exceptional nor an error of any kind.
Observe that the keywords are called throw
/catch
and that the exception
concept is not baked into the language in any way. This is (one of) the reason(s) for that.
Upvotes: 0
Reputation: 31519
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.
Upvotes: 6
Reputation: 153919
In general, any object which is thrown should derive from
std::exception
. There are exceptions, however. The most
obvious: I've worked on projects which preferred throwing an
int
to calling exit()
. Of course, this only works if
main
follows the convention of catching int
and returning
it. (The advantage of this is that all local variables will be
destructed, where as they won't if you call exit()
.)
And in small throw-away test programs, I'll often just throw
a string literal (which can be caught with char const*
), which
can be immediately output. (This is not a good solution for
any production code, but when you're experimenting in order to
learn something, it seems acceptable.)
Upvotes: 2
Reputation: 320531
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.
Upvotes: 1
Reputation: 101456
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
:
std::string
and the construction or copy of that string
raises another exception, terminate
will be called and your process will cease to exist. You'll never get a chance to catch
that std::string
. std::exception
makes it possible to catch (const std::exception&)
in a generic fashion. If you throw something else, you will need a catch
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
.
Upvotes: 13
Reputation: 18864
As @galop1n answered, you can throw anything you like. But
throw(type())
---> catch(type const& e)
as a resultcatch(std::exception const& e)
. Though you may contradict that they should not be catching anything that they are not aware of what it is.Upvotes: 0
Reputation: 8824
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…
Upvotes: 0