Using throw to replace return in C++ non-void functions
In C++ functions, is it a good practice to replace return
with throw
? For example, I have the following code
// return indices of two numbers whose sum is equal to target
vector<int> twoSum(vector<int>& nums, int target) {
for(int i=0; i<nums.size()-1; ++i)
for(int j=i+1; j<nums.size(); ++j)
{
if(nums[i] + nums[j] == target) return vector<int>{i, j};
}
// return vector<int>{};
throw "no solution";
}
The code above compiles with my GCC 7.2.
c++ exception-handling
|
show 8 more comments
In C++ functions, is it a good practice to replace return
with throw
? For example, I have the following code
// return indices of two numbers whose sum is equal to target
vector<int> twoSum(vector<int>& nums, int target) {
for(int i=0; i<nums.size()-1; ++i)
for(int j=i+1; j<nums.size(); ++j)
{
if(nums[i] + nums[j] == target) return vector<int>{i, j};
}
// return vector<int>{};
throw "no solution";
}
The code above compiles with my GCC 7.2.
c++ exception-handling
12
It really just depends on if finding a result is an exceptional situation or not and on how you want your function to behave.
– François Andrieux
Feb 15 at 16:21
3
Good practice,maybe.std::optional
is my preferred solution if no result isn't exceptional.
– NathanOliver
Feb 15 at 16:21
25
Exceptions are for exceptional situations. So it depends on your function. If your function is always expected to return a result, then throwing would make sense. Otherwise, if "nothing found" is a valid result, then you are better off with something likestd::optional
.
– 0x5453
Feb 15 at 16:21
6
Is this really an exceptional case? If there was nothing to do then no results (i.e., an emptyvector
) conveys that. This is completely different than an internal failure that caused computing the results to fail.
– James Adkison
Feb 15 at 16:22
9
Note that if what you are actually doing is replacing areturn
with athrow
in the sense that you want to return a result viathrow
, then it's a very bad idea. This is not what you are doing here.throw
is being used to signal a failure which is what it's designed for.
– François Andrieux
Feb 15 at 16:22
|
show 8 more comments
In C++ functions, is it a good practice to replace return
with throw
? For example, I have the following code
// return indices of two numbers whose sum is equal to target
vector<int> twoSum(vector<int>& nums, int target) {
for(int i=0; i<nums.size()-1; ++i)
for(int j=i+1; j<nums.size(); ++j)
{
if(nums[i] + nums[j] == target) return vector<int>{i, j};
}
// return vector<int>{};
throw "no solution";
}
The code above compiles with my GCC 7.2.
c++ exception-handling
In C++ functions, is it a good practice to replace return
with throw
? For example, I have the following code
// return indices of two numbers whose sum is equal to target
vector<int> twoSum(vector<int>& nums, int target) {
for(int i=0; i<nums.size()-1; ++i)
for(int j=i+1; j<nums.size(); ++j)
{
if(nums[i] + nums[j] == target) return vector<int>{i, j};
}
// return vector<int>{};
throw "no solution";
}
The code above compiles with my GCC 7.2.
c++ exception-handling
c++ exception-handling
edited Feb 15 at 20:32
mrflash818
6861218
6861218
asked Feb 15 at 16:19
user27490user27490
34837
34837
12
It really just depends on if finding a result is an exceptional situation or not and on how you want your function to behave.
– François Andrieux
Feb 15 at 16:21
3
Good practice,maybe.std::optional
is my preferred solution if no result isn't exceptional.
– NathanOliver
Feb 15 at 16:21
25
Exceptions are for exceptional situations. So it depends on your function. If your function is always expected to return a result, then throwing would make sense. Otherwise, if "nothing found" is a valid result, then you are better off with something likestd::optional
.
– 0x5453
Feb 15 at 16:21
6
Is this really an exceptional case? If there was nothing to do then no results (i.e., an emptyvector
) conveys that. This is completely different than an internal failure that caused computing the results to fail.
– James Adkison
Feb 15 at 16:22
9
Note that if what you are actually doing is replacing areturn
with athrow
in the sense that you want to return a result viathrow
, then it's a very bad idea. This is not what you are doing here.throw
is being used to signal a failure which is what it's designed for.
– François Andrieux
Feb 15 at 16:22
|
show 8 more comments
12
It really just depends on if finding a result is an exceptional situation or not and on how you want your function to behave.
– François Andrieux
Feb 15 at 16:21
3
Good practice,maybe.std::optional
is my preferred solution if no result isn't exceptional.
– NathanOliver
Feb 15 at 16:21
25
Exceptions are for exceptional situations. So it depends on your function. If your function is always expected to return a result, then throwing would make sense. Otherwise, if "nothing found" is a valid result, then you are better off with something likestd::optional
.
– 0x5453
Feb 15 at 16:21
6
Is this really an exceptional case? If there was nothing to do then no results (i.e., an emptyvector
) conveys that. This is completely different than an internal failure that caused computing the results to fail.
– James Adkison
Feb 15 at 16:22
9
Note that if what you are actually doing is replacing areturn
with athrow
in the sense that you want to return a result viathrow
, then it's a very bad idea. This is not what you are doing here.throw
is being used to signal a failure which is what it's designed for.
– François Andrieux
Feb 15 at 16:22
12
12
It really just depends on if finding a result is an exceptional situation or not and on how you want your function to behave.
– François Andrieux
Feb 15 at 16:21
It really just depends on if finding a result is an exceptional situation or not and on how you want your function to behave.
– François Andrieux
Feb 15 at 16:21
3
3
Good practice,maybe.
std::optional
is my preferred solution if no result isn't exceptional.– NathanOliver
Feb 15 at 16:21
Good practice,maybe.
std::optional
is my preferred solution if no result isn't exceptional.– NathanOliver
Feb 15 at 16:21
25
25
Exceptions are for exceptional situations. So it depends on your function. If your function is always expected to return a result, then throwing would make sense. Otherwise, if "nothing found" is a valid result, then you are better off with something like
std::optional
.– 0x5453
Feb 15 at 16:21
Exceptions are for exceptional situations. So it depends on your function. If your function is always expected to return a result, then throwing would make sense. Otherwise, if "nothing found" is a valid result, then you are better off with something like
std::optional
.– 0x5453
Feb 15 at 16:21
6
6
Is this really an exceptional case? If there was nothing to do then no results (i.e., an empty
vector
) conveys that. This is completely different than an internal failure that caused computing the results to fail.– James Adkison
Feb 15 at 16:22
Is this really an exceptional case? If there was nothing to do then no results (i.e., an empty
vector
) conveys that. This is completely different than an internal failure that caused computing the results to fail.– James Adkison
Feb 15 at 16:22
9
9
Note that if what you are actually doing is replacing a
return
with a throw
in the sense that you want to return a result via throw
, then it's a very bad idea. This is not what you are doing here. throw
is being used to signal a failure which is what it's designed for.– François Andrieux
Feb 15 at 16:22
Note that if what you are actually doing is replacing a
return
with a throw
in the sense that you want to return a result via throw
, then it's a very bad idea. This is not what you are doing here. throw
is being used to signal a failure which is what it's designed for.– François Andrieux
Feb 15 at 16:22
|
show 8 more comments
10 Answers
10
active
oldest
votes
The concepts of this answer are taken from the C++ Programming language by Bjarne Stroustrup.
SHORT ANSWER
Yes, exception-throwing can be used as returning value method. An example is the following for a binary tree search function:
void fnd(Tree∗ p, const string& s)
{
if (s == p−>str) throw p; // found s
if (p−>left) fnd(p−>left,s);
if (p−>right) fnd(p−>right,s);
}
Tree∗ find(Tree∗ p, const string& s)
{
try {
fnd(p,s);
}
catch (Tree∗ q) {
// q->str==s
return q;
}
return 0;
}
However, it should be avoided because:
- they allow you to separate error code from "ordinary code" making your program much more readable, comprehensible and manageable. If you use them as return method, this does not hold anymore.
- there might be inefficiencies because exception implementations rely on the assumption that they are used as error-handling methods.
Apart from that, there are further limitations:
- exceptions must be of copy-able type
- exceptions can handle only synchronous events
- they should be avoided in a time-critical system
- they should be avoided in large old programs in which resource management is an ad hoc mess (free store is unsystematically managed using naked pointers, news and delete) rather than relying on some systematic scheme such as resource handles (strings vectors).
Longer answer
An exception is an object thrown to represent the occurrence of an error. It can be of any type that can be copied but it is strongly recommended to use only user-defined types specifically defined for that purpose. Exceptions allow the programmer to explicitly separate error-handling code from "ordinary code" making the program more readable.
First of all, exceptions are for managing synchronous events, not asynchronous ones. This is one first limitation.
One might think of the exception-handling mechanisms as simply another control structure, an alternative way of returning a value to a caller.
This has some charm but should be avoided because it is likely to cause confusion and inefficiencies. Stroustrup suggests:
When at all possible stick to the "exception handling is an error
handling" view. When this is done code is separated into two categories:
ordinary code and error handling code. This makes the code more
comprehensible. Furthermore, the implementations of the exception
mechanisms are optimized based on the assumption that this simple
model underlies the use of the exception.
So basically using exceptions to return value should be avoided because
exception implementation is optimized assuming they are used for error-handling and not for returning values hence they might be inefficient for that;- They allow separating error code from ordinary code making the code much more readable and comprehensible. Anything that helps preserve a clear model of what is an error and how it is handled should be treasured.
There are programs that for practical or historical reasons cannot use exceptions (neither as error handling so even less):
- A time-critical component of an embedded system where operation must be guaranteed to complete in a specified maximum time. In the absence of tools that can accurately estimate the maximum time for an exception to propagate from
throw
tocatch
alternative error handling methods must be used. - A large old program in which resource management is an ad hoc mess (free store is unsystematically managed using naked pointers,
news
anddelete
) rather than relying on some systematic scheme such as resource handles (string
svector
s).
In the above cases, traditional pre-exception methods are preferred.
Couldn’t you just replace your throw with a return and your calls tofnd
withreturn fnd(...)
?
– Cole Johnson
2 days ago
The question is about exception throwing as returning method. This is an example about it
– Francesco Boi
2 days ago
add a comment |
In C++ functions, is it a good practice to replace return with throw?
Return is not something that can be replaced by a throw in general.
In exceptional cases where you have nothing to return, throwing an exception can be a valid way to exit the function.
Whether it is "good practice", and what case is "exceptional" are subjective. For example, for a search function such as yours, it's hardly a surprise that there might not be a solution, and I would argue that throwing would not be appropriate.
There are often other alternatives to throwing. Compare your algorithm with something like std::string::find
that returns the index of the start of a substring. In case where substring does not exist, it returns a "non-value" std::string::npos
. You could do the same and decide that the index -1 is returned when a result is not found. There is also a generic way to add non-value representation to a type in cases where none of the existing representations can be reserved for the purpose: std::optional
.
P.S. A vector is probably not a good choice for returning a pair of numbers. std::pair
might be better, or a custom class if you have good names for the numbers.
4
Well, I've seen a small codebase once with void functions that returned results by throwing them, andtry-catch
was used as a sort of pattern matching tool. Quite a bizarre design, I have to admit, but it shows how to replacereturn
withthrow
in general.
– Joker_vD
Feb 15 at 18:03
@Joker_vD frankly, I've never seen a function whose all return paths were throws (except "not implemented" style exceptions). But I admit that it would be technically legal C++. So, I've technically lied a bit when I said that returns cannot be replaced.
– eerorika
Feb 15 at 18:09
6
@Joker_vD: it's possible, but would perform like crap on "normal" implementations. Unless they can optimize away the throw/catch, firing up the stack-unwinding exception dispatch code (which has to go read.eh_frame
metadata) is vastly more expensive than aret
instruction.
– Peter Cordes
Feb 15 at 20:45
This would be one of the few situations where I'd agree with usingstd::pair
- where the two elements are more or less interchangeable. On a tangent: I disagree with a lot of the places the standard library usesstd::pair
- for example, think how much more readable code would be if you would writeauto result = m_multiplicities.emplace(k, 1); if (!result.inserted) ++(result.location->value);
as opposed toif (!result.second) ++(result.first->second);
– Daniel Schepler
Feb 15 at 23:49
1
of course, returning an error value likestd::string::npos
means the caller might completely forget to check for it and pass it along to some other code, eventually producing nonsense that's hard to trace back to the original cause. this problem is the entire reason for exceptions (or optional types).
– Eevee
Feb 16 at 8:41
add a comment |
return
and throw
have two different purposes and should not be considered interchangeable. Use return
when you have a valid result to send back to the caller. On the other hand, use throw
when some exceptional behavior occurs. You can get an idea of how other programmers use throw
by using functions from the standard library and taking note of when they throw exceptions.
add a comment |
In addition to the other answers, there's also performance: Catching an exception incurs a run-time overhead (see this answer) compared to an if
clause.
(Of course, we're talking about microseconds... Whether or not this is relevant depends on your specific use case.)
7
Function call/ret takes about a nanosecond on a 3 to 4 GHz CPU, and can overlap with surrounding work. About 1000x slower sounds plausible. But remember, microseconds is thousands of clock cycles on modern CPUs (during which time they could have executed maybe 1 to 3 instructions per clock, or even more in high-ILP code), and ~ten times longer than even a cache miss that went all the way RAM and stalled out-of-order execution. try/catch instead of return might not optimize away even after inlining, so you will end up with far more of it than you wouldcall
/ret
instructions.
– Peter Cordes
Feb 15 at 20:53
add a comment |
A function should throw an exception when it is unable to meet its postcondition. (Some functions may also throw exceptions when their preconditions are not met; that's a different topic that I won't get into here.) Therefore, if your function must return a pair of integers from the vector summing to the given target, then it has no choice but to throw an exception when it can't find one. But if the function's contract allows it to return a value to indicate it was unable to find such a pair, then it should not throw an exception, since it has the ability to fulfill the contract.
In your case:
- You can make your function return an empty vector when it can't find two integers summing to the given target. Then, it never needs to throw an exception.
- Or, you can make your function return
std::optional<std::pair<int, int>>
. It never needs to throw an exception because it can just return an empty optional when it can't find an appropriate pair. - If, however, you make it return
std::pair<int, int>
, then it should throw an exception because there is no sensible value to return when it can't find an appropriate pair.
Generally, C++ programmers prefer to write functions that don't need to throw exceptions in order to report mere "disappointments", such as search failures, that are easily anticipated and handled locally. The advantages of returning values rather than throwing exceptions are discussed extensively elsewhere so I won't rehash that discussion here.
Thus, declaring "failure" by throwing an exception is usually limited to the following cases:
- The function is a constructor and it's simply not able to establish its class's invariant. It must throw an exception in order to ensure that the calling code doesn't see a broken object.
- An "exceptional" condition arises that should be handled at some higher level than that of the caller. The caller is likely to not know how to recover from the condition. In such cases, the use of the exception mechanism frees up the caller from having to figure out how to proceed when the exceptional condition occurs.
add a comment |
What you have mentioned is not good programming practice. Replacing a return
statement with throw
is not acceptable in production-level code, especially with automated testing platforms that generate lists of all exceptions as a way of proving or disproving certain functionality. You have to take into consideration the needs of Software Testers when designing your code. throw
is simply not interchangeable with return
. throw
is used to signal that a program error has occurred by some unexpected phenomena. return
is used to signal method completion. It is common to use return
to transmit error codes, but return values do not cause the program to be interrupted in the same way as throw
does. Additionally, throw
has the power to terminate a program if it is not handled correctly.
Essentially, it is good practice to use throw
when a significant error is detected within the method, but there should always be a clean return if such an error is not detected. Can you make that substitution? Maybe, and maybe it will work logically...but it's not good practice and certainly not a popular implementation.
add a comment |
No, throw
is not a good semantic replacement for return
. You only want to use throw
when your code has done something that it should not be doing, not to signify the perfectly valid negative result of a function.
As a general rule, exceptions are meant to signify when something abnormal or unexpected has happened during the execution of your code. Looking at the purpose of your function, the occurrence of no two integers in the passed vector summing to target
is a very possible result of the function, so that result is not abnormal and therefore should not be treated as exceptional.
add a comment |
Just because the function is throwing as the last call, doesn't mean it is replacing return. It is just the flow of logic.
The question shouldn't be :
is it a good practice to replace return with throw?
Instead it should be about how to define your API and contracts.
If You want to guarantee to the users of the function that vector
is never empty, then throwing an exception is a good idea.
If you want to guarantee that your function doesn't throw exceptions instead returns an empty vector
on certain conditions, then throwing is a bad idea.
In both cases, the user has to know, what actions they have to take to correctly use your function.
add a comment |
Your question is language agnostic.
Return and Throw have different purposes.
- Return is for returning a value; while,
- Throw is for throwing an exception; and,
- An exception should be thrown in truly exceptional conditions.
Bonus Content (from Steve McConnell’s Code Complete 2)
Here are all the alternatives available to you when you encounter a situation where you cannot return normally:
Return a neutral value like -1 from a method that’s supposed to return count of something;
Return the closest legal value like 0 on the digital speedometer of a car when it is going in reverse;
Return same value as previous call like a temperature reading on a thermometer when you are reading every second and you know that the readings do not differ drastically in such a short interval;
Return the next valid piece of data like when you are reading rows from a table and a specific row is corrupt;
Set/Return an error status/code/object found pretty commonly in C++ library calls;
Display a message in an alert box but be careful to not give out too much that can assist a malicious actor;
Log to a file;
Throw an exception like you are pondering upon;
Call a central error handler/routine if that is how your system is designed;
Shutdown.
Further, you do not need to pick only one of the above options. You can do a combination like, for example, logging to file and displaying a message to the user.
What approach you should take is a question of Correctness vs Robustness. Do you want your program to be absolutely correct and shutdown when an erroneous situation is encountered or do you want your program to be robust and continue with execution when at some point it fails to follow the desired path?
add a comment |
I think it is the wrong question asking if return can be replaced by throw. return and throw are doing two very different things:
return is used to return regular results of a functions.
throw is the preferred method to react on error conditions when a result value does not exist.
The alternative reaction on errors could be to return special error code values. This has some disadvantages, e.g.:
- Using a function gets more difficult if you always have to keep error codes etc. in mind.
- The caller might forget to handle the error. When you forget an exception handler, you will get unhandled exception. It is very likely that you will detect this bug.
- The error might be too complex to be expressed by a single error code properly. An exception can be an object containing all the information you need.
- The errors are handled at a well-defined position (the exception handler). This will make your code much clearer than checking the return value for special values after each call.
In your example the answer depends on the semantics of the function:
If an empty vector is an acceptable return value, then you should use return if no pair is found.
If it is expected that there MUST be matching pairs always, then finding no pair obviously is an error. You should use throw in this case.
New contributor
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54713231%2fusing-throw-to-replace-return-in-c-non-void-functions%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
10 Answers
10
active
oldest
votes
10 Answers
10
active
oldest
votes
active
oldest
votes
active
oldest
votes
The concepts of this answer are taken from the C++ Programming language by Bjarne Stroustrup.
SHORT ANSWER
Yes, exception-throwing can be used as returning value method. An example is the following for a binary tree search function:
void fnd(Tree∗ p, const string& s)
{
if (s == p−>str) throw p; // found s
if (p−>left) fnd(p−>left,s);
if (p−>right) fnd(p−>right,s);
}
Tree∗ find(Tree∗ p, const string& s)
{
try {
fnd(p,s);
}
catch (Tree∗ q) {
// q->str==s
return q;
}
return 0;
}
However, it should be avoided because:
- they allow you to separate error code from "ordinary code" making your program much more readable, comprehensible and manageable. If you use them as return method, this does not hold anymore.
- there might be inefficiencies because exception implementations rely on the assumption that they are used as error-handling methods.
Apart from that, there are further limitations:
- exceptions must be of copy-able type
- exceptions can handle only synchronous events
- they should be avoided in a time-critical system
- they should be avoided in large old programs in which resource management is an ad hoc mess (free store is unsystematically managed using naked pointers, news and delete) rather than relying on some systematic scheme such as resource handles (strings vectors).
Longer answer
An exception is an object thrown to represent the occurrence of an error. It can be of any type that can be copied but it is strongly recommended to use only user-defined types specifically defined for that purpose. Exceptions allow the programmer to explicitly separate error-handling code from "ordinary code" making the program more readable.
First of all, exceptions are for managing synchronous events, not asynchronous ones. This is one first limitation.
One might think of the exception-handling mechanisms as simply another control structure, an alternative way of returning a value to a caller.
This has some charm but should be avoided because it is likely to cause confusion and inefficiencies. Stroustrup suggests:
When at all possible stick to the "exception handling is an error
handling" view. When this is done code is separated into two categories:
ordinary code and error handling code. This makes the code more
comprehensible. Furthermore, the implementations of the exception
mechanisms are optimized based on the assumption that this simple
model underlies the use of the exception.
So basically using exceptions to return value should be avoided because
exception implementation is optimized assuming they are used for error-handling and not for returning values hence they might be inefficient for that;- They allow separating error code from ordinary code making the code much more readable and comprehensible. Anything that helps preserve a clear model of what is an error and how it is handled should be treasured.
There are programs that for practical or historical reasons cannot use exceptions (neither as error handling so even less):
- A time-critical component of an embedded system where operation must be guaranteed to complete in a specified maximum time. In the absence of tools that can accurately estimate the maximum time for an exception to propagate from
throw
tocatch
alternative error handling methods must be used. - A large old program in which resource management is an ad hoc mess (free store is unsystematically managed using naked pointers,
news
anddelete
) rather than relying on some systematic scheme such as resource handles (string
svector
s).
In the above cases, traditional pre-exception methods are preferred.
Couldn’t you just replace your throw with a return and your calls tofnd
withreturn fnd(...)
?
– Cole Johnson
2 days ago
The question is about exception throwing as returning method. This is an example about it
– Francesco Boi
2 days ago
add a comment |
The concepts of this answer are taken from the C++ Programming language by Bjarne Stroustrup.
SHORT ANSWER
Yes, exception-throwing can be used as returning value method. An example is the following for a binary tree search function:
void fnd(Tree∗ p, const string& s)
{
if (s == p−>str) throw p; // found s
if (p−>left) fnd(p−>left,s);
if (p−>right) fnd(p−>right,s);
}
Tree∗ find(Tree∗ p, const string& s)
{
try {
fnd(p,s);
}
catch (Tree∗ q) {
// q->str==s
return q;
}
return 0;
}
However, it should be avoided because:
- they allow you to separate error code from "ordinary code" making your program much more readable, comprehensible and manageable. If you use them as return method, this does not hold anymore.
- there might be inefficiencies because exception implementations rely on the assumption that they are used as error-handling methods.
Apart from that, there are further limitations:
- exceptions must be of copy-able type
- exceptions can handle only synchronous events
- they should be avoided in a time-critical system
- they should be avoided in large old programs in which resource management is an ad hoc mess (free store is unsystematically managed using naked pointers, news and delete) rather than relying on some systematic scheme such as resource handles (strings vectors).
Longer answer
An exception is an object thrown to represent the occurrence of an error. It can be of any type that can be copied but it is strongly recommended to use only user-defined types specifically defined for that purpose. Exceptions allow the programmer to explicitly separate error-handling code from "ordinary code" making the program more readable.
First of all, exceptions are for managing synchronous events, not asynchronous ones. This is one first limitation.
One might think of the exception-handling mechanisms as simply another control structure, an alternative way of returning a value to a caller.
This has some charm but should be avoided because it is likely to cause confusion and inefficiencies. Stroustrup suggests:
When at all possible stick to the "exception handling is an error
handling" view. When this is done code is separated into two categories:
ordinary code and error handling code. This makes the code more
comprehensible. Furthermore, the implementations of the exception
mechanisms are optimized based on the assumption that this simple
model underlies the use of the exception.
So basically using exceptions to return value should be avoided because
exception implementation is optimized assuming they are used for error-handling and not for returning values hence they might be inefficient for that;- They allow separating error code from ordinary code making the code much more readable and comprehensible. Anything that helps preserve a clear model of what is an error and how it is handled should be treasured.
There are programs that for practical or historical reasons cannot use exceptions (neither as error handling so even less):
- A time-critical component of an embedded system where operation must be guaranteed to complete in a specified maximum time. In the absence of tools that can accurately estimate the maximum time for an exception to propagate from
throw
tocatch
alternative error handling methods must be used. - A large old program in which resource management is an ad hoc mess (free store is unsystematically managed using naked pointers,
news
anddelete
) rather than relying on some systematic scheme such as resource handles (string
svector
s).
In the above cases, traditional pre-exception methods are preferred.
Couldn’t you just replace your throw with a return and your calls tofnd
withreturn fnd(...)
?
– Cole Johnson
2 days ago
The question is about exception throwing as returning method. This is an example about it
– Francesco Boi
2 days ago
add a comment |
The concepts of this answer are taken from the C++ Programming language by Bjarne Stroustrup.
SHORT ANSWER
Yes, exception-throwing can be used as returning value method. An example is the following for a binary tree search function:
void fnd(Tree∗ p, const string& s)
{
if (s == p−>str) throw p; // found s
if (p−>left) fnd(p−>left,s);
if (p−>right) fnd(p−>right,s);
}
Tree∗ find(Tree∗ p, const string& s)
{
try {
fnd(p,s);
}
catch (Tree∗ q) {
// q->str==s
return q;
}
return 0;
}
However, it should be avoided because:
- they allow you to separate error code from "ordinary code" making your program much more readable, comprehensible and manageable. If you use them as return method, this does not hold anymore.
- there might be inefficiencies because exception implementations rely on the assumption that they are used as error-handling methods.
Apart from that, there are further limitations:
- exceptions must be of copy-able type
- exceptions can handle only synchronous events
- they should be avoided in a time-critical system
- they should be avoided in large old programs in which resource management is an ad hoc mess (free store is unsystematically managed using naked pointers, news and delete) rather than relying on some systematic scheme such as resource handles (strings vectors).
Longer answer
An exception is an object thrown to represent the occurrence of an error. It can be of any type that can be copied but it is strongly recommended to use only user-defined types specifically defined for that purpose. Exceptions allow the programmer to explicitly separate error-handling code from "ordinary code" making the program more readable.
First of all, exceptions are for managing synchronous events, not asynchronous ones. This is one first limitation.
One might think of the exception-handling mechanisms as simply another control structure, an alternative way of returning a value to a caller.
This has some charm but should be avoided because it is likely to cause confusion and inefficiencies. Stroustrup suggests:
When at all possible stick to the "exception handling is an error
handling" view. When this is done code is separated into two categories:
ordinary code and error handling code. This makes the code more
comprehensible. Furthermore, the implementations of the exception
mechanisms are optimized based on the assumption that this simple
model underlies the use of the exception.
So basically using exceptions to return value should be avoided because
exception implementation is optimized assuming they are used for error-handling and not for returning values hence they might be inefficient for that;- They allow separating error code from ordinary code making the code much more readable and comprehensible. Anything that helps preserve a clear model of what is an error and how it is handled should be treasured.
There are programs that for practical or historical reasons cannot use exceptions (neither as error handling so even less):
- A time-critical component of an embedded system where operation must be guaranteed to complete in a specified maximum time. In the absence of tools that can accurately estimate the maximum time for an exception to propagate from
throw
tocatch
alternative error handling methods must be used. - A large old program in which resource management is an ad hoc mess (free store is unsystematically managed using naked pointers,
news
anddelete
) rather than relying on some systematic scheme such as resource handles (string
svector
s).
In the above cases, traditional pre-exception methods are preferred.
The concepts of this answer are taken from the C++ Programming language by Bjarne Stroustrup.
SHORT ANSWER
Yes, exception-throwing can be used as returning value method. An example is the following for a binary tree search function:
void fnd(Tree∗ p, const string& s)
{
if (s == p−>str) throw p; // found s
if (p−>left) fnd(p−>left,s);
if (p−>right) fnd(p−>right,s);
}
Tree∗ find(Tree∗ p, const string& s)
{
try {
fnd(p,s);
}
catch (Tree∗ q) {
// q->str==s
return q;
}
return 0;
}
However, it should be avoided because:
- they allow you to separate error code from "ordinary code" making your program much more readable, comprehensible and manageable. If you use them as return method, this does not hold anymore.
- there might be inefficiencies because exception implementations rely on the assumption that they are used as error-handling methods.
Apart from that, there are further limitations:
- exceptions must be of copy-able type
- exceptions can handle only synchronous events
- they should be avoided in a time-critical system
- they should be avoided in large old programs in which resource management is an ad hoc mess (free store is unsystematically managed using naked pointers, news and delete) rather than relying on some systematic scheme such as resource handles (strings vectors).
Longer answer
An exception is an object thrown to represent the occurrence of an error. It can be of any type that can be copied but it is strongly recommended to use only user-defined types specifically defined for that purpose. Exceptions allow the programmer to explicitly separate error-handling code from "ordinary code" making the program more readable.
First of all, exceptions are for managing synchronous events, not asynchronous ones. This is one first limitation.
One might think of the exception-handling mechanisms as simply another control structure, an alternative way of returning a value to a caller.
This has some charm but should be avoided because it is likely to cause confusion and inefficiencies. Stroustrup suggests:
When at all possible stick to the "exception handling is an error
handling" view. When this is done code is separated into two categories:
ordinary code and error handling code. This makes the code more
comprehensible. Furthermore, the implementations of the exception
mechanisms are optimized based on the assumption that this simple
model underlies the use of the exception.
So basically using exceptions to return value should be avoided because
exception implementation is optimized assuming they are used for error-handling and not for returning values hence they might be inefficient for that;- They allow separating error code from ordinary code making the code much more readable and comprehensible. Anything that helps preserve a clear model of what is an error and how it is handled should be treasured.
There are programs that for practical or historical reasons cannot use exceptions (neither as error handling so even less):
- A time-critical component of an embedded system where operation must be guaranteed to complete in a specified maximum time. In the absence of tools that can accurately estimate the maximum time for an exception to propagate from
throw
tocatch
alternative error handling methods must be used. - A large old program in which resource management is an ad hoc mess (free store is unsystematically managed using naked pointers,
news
anddelete
) rather than relying on some systematic scheme such as resource handles (string
svector
s).
In the above cases, traditional pre-exception methods are preferred.
edited Feb 19 at 7:30
eFarzad
576721
576721
answered Feb 15 at 18:05
Francesco BoiFrancesco Boi
2,45222342
2,45222342
Couldn’t you just replace your throw with a return and your calls tofnd
withreturn fnd(...)
?
– Cole Johnson
2 days ago
The question is about exception throwing as returning method. This is an example about it
– Francesco Boi
2 days ago
add a comment |
Couldn’t you just replace your throw with a return and your calls tofnd
withreturn fnd(...)
?
– Cole Johnson
2 days ago
The question is about exception throwing as returning method. This is an example about it
– Francesco Boi
2 days ago
Couldn’t you just replace your throw with a return and your calls to
fnd
with return fnd(...)
?– Cole Johnson
2 days ago
Couldn’t you just replace your throw with a return and your calls to
fnd
with return fnd(...)
?– Cole Johnson
2 days ago
The question is about exception throwing as returning method. This is an example about it
– Francesco Boi
2 days ago
The question is about exception throwing as returning method. This is an example about it
– Francesco Boi
2 days ago
add a comment |
In C++ functions, is it a good practice to replace return with throw?
Return is not something that can be replaced by a throw in general.
In exceptional cases where you have nothing to return, throwing an exception can be a valid way to exit the function.
Whether it is "good practice", and what case is "exceptional" are subjective. For example, for a search function such as yours, it's hardly a surprise that there might not be a solution, and I would argue that throwing would not be appropriate.
There are often other alternatives to throwing. Compare your algorithm with something like std::string::find
that returns the index of the start of a substring. In case where substring does not exist, it returns a "non-value" std::string::npos
. You could do the same and decide that the index -1 is returned when a result is not found. There is also a generic way to add non-value representation to a type in cases where none of the existing representations can be reserved for the purpose: std::optional
.
P.S. A vector is probably not a good choice for returning a pair of numbers. std::pair
might be better, or a custom class if you have good names for the numbers.
4
Well, I've seen a small codebase once with void functions that returned results by throwing them, andtry-catch
was used as a sort of pattern matching tool. Quite a bizarre design, I have to admit, but it shows how to replacereturn
withthrow
in general.
– Joker_vD
Feb 15 at 18:03
@Joker_vD frankly, I've never seen a function whose all return paths were throws (except "not implemented" style exceptions). But I admit that it would be technically legal C++. So, I've technically lied a bit when I said that returns cannot be replaced.
– eerorika
Feb 15 at 18:09
6
@Joker_vD: it's possible, but would perform like crap on "normal" implementations. Unless they can optimize away the throw/catch, firing up the stack-unwinding exception dispatch code (which has to go read.eh_frame
metadata) is vastly more expensive than aret
instruction.
– Peter Cordes
Feb 15 at 20:45
This would be one of the few situations where I'd agree with usingstd::pair
- where the two elements are more or less interchangeable. On a tangent: I disagree with a lot of the places the standard library usesstd::pair
- for example, think how much more readable code would be if you would writeauto result = m_multiplicities.emplace(k, 1); if (!result.inserted) ++(result.location->value);
as opposed toif (!result.second) ++(result.first->second);
– Daniel Schepler
Feb 15 at 23:49
1
of course, returning an error value likestd::string::npos
means the caller might completely forget to check for it and pass it along to some other code, eventually producing nonsense that's hard to trace back to the original cause. this problem is the entire reason for exceptions (or optional types).
– Eevee
Feb 16 at 8:41
add a comment |
In C++ functions, is it a good practice to replace return with throw?
Return is not something that can be replaced by a throw in general.
In exceptional cases where you have nothing to return, throwing an exception can be a valid way to exit the function.
Whether it is "good practice", and what case is "exceptional" are subjective. For example, for a search function such as yours, it's hardly a surprise that there might not be a solution, and I would argue that throwing would not be appropriate.
There are often other alternatives to throwing. Compare your algorithm with something like std::string::find
that returns the index of the start of a substring. In case where substring does not exist, it returns a "non-value" std::string::npos
. You could do the same and decide that the index -1 is returned when a result is not found. There is also a generic way to add non-value representation to a type in cases where none of the existing representations can be reserved for the purpose: std::optional
.
P.S. A vector is probably not a good choice for returning a pair of numbers. std::pair
might be better, or a custom class if you have good names for the numbers.
4
Well, I've seen a small codebase once with void functions that returned results by throwing them, andtry-catch
was used as a sort of pattern matching tool. Quite a bizarre design, I have to admit, but it shows how to replacereturn
withthrow
in general.
– Joker_vD
Feb 15 at 18:03
@Joker_vD frankly, I've never seen a function whose all return paths were throws (except "not implemented" style exceptions). But I admit that it would be technically legal C++. So, I've technically lied a bit when I said that returns cannot be replaced.
– eerorika
Feb 15 at 18:09
6
@Joker_vD: it's possible, but would perform like crap on "normal" implementations. Unless they can optimize away the throw/catch, firing up the stack-unwinding exception dispatch code (which has to go read.eh_frame
metadata) is vastly more expensive than aret
instruction.
– Peter Cordes
Feb 15 at 20:45
This would be one of the few situations where I'd agree with usingstd::pair
- where the two elements are more or less interchangeable. On a tangent: I disagree with a lot of the places the standard library usesstd::pair
- for example, think how much more readable code would be if you would writeauto result = m_multiplicities.emplace(k, 1); if (!result.inserted) ++(result.location->value);
as opposed toif (!result.second) ++(result.first->second);
– Daniel Schepler
Feb 15 at 23:49
1
of course, returning an error value likestd::string::npos
means the caller might completely forget to check for it and pass it along to some other code, eventually producing nonsense that's hard to trace back to the original cause. this problem is the entire reason for exceptions (or optional types).
– Eevee
Feb 16 at 8:41
add a comment |
In C++ functions, is it a good practice to replace return with throw?
Return is not something that can be replaced by a throw in general.
In exceptional cases where you have nothing to return, throwing an exception can be a valid way to exit the function.
Whether it is "good practice", and what case is "exceptional" are subjective. For example, for a search function such as yours, it's hardly a surprise that there might not be a solution, and I would argue that throwing would not be appropriate.
There are often other alternatives to throwing. Compare your algorithm with something like std::string::find
that returns the index of the start of a substring. In case where substring does not exist, it returns a "non-value" std::string::npos
. You could do the same and decide that the index -1 is returned when a result is not found. There is also a generic way to add non-value representation to a type in cases where none of the existing representations can be reserved for the purpose: std::optional
.
P.S. A vector is probably not a good choice for returning a pair of numbers. std::pair
might be better, or a custom class if you have good names for the numbers.
In C++ functions, is it a good practice to replace return with throw?
Return is not something that can be replaced by a throw in general.
In exceptional cases where you have nothing to return, throwing an exception can be a valid way to exit the function.
Whether it is "good practice", and what case is "exceptional" are subjective. For example, for a search function such as yours, it's hardly a surprise that there might not be a solution, and I would argue that throwing would not be appropriate.
There are often other alternatives to throwing. Compare your algorithm with something like std::string::find
that returns the index of the start of a substring. In case where substring does not exist, it returns a "non-value" std::string::npos
. You could do the same and decide that the index -1 is returned when a result is not found. There is also a generic way to add non-value representation to a type in cases where none of the existing representations can be reserved for the purpose: std::optional
.
P.S. A vector is probably not a good choice for returning a pair of numbers. std::pair
might be better, or a custom class if you have good names for the numbers.
edited Feb 15 at 16:37
answered Feb 15 at 16:24
eerorikaeerorika
83k661127
83k661127
4
Well, I've seen a small codebase once with void functions that returned results by throwing them, andtry-catch
was used as a sort of pattern matching tool. Quite a bizarre design, I have to admit, but it shows how to replacereturn
withthrow
in general.
– Joker_vD
Feb 15 at 18:03
@Joker_vD frankly, I've never seen a function whose all return paths were throws (except "not implemented" style exceptions). But I admit that it would be technically legal C++. So, I've technically lied a bit when I said that returns cannot be replaced.
– eerorika
Feb 15 at 18:09
6
@Joker_vD: it's possible, but would perform like crap on "normal" implementations. Unless they can optimize away the throw/catch, firing up the stack-unwinding exception dispatch code (which has to go read.eh_frame
metadata) is vastly more expensive than aret
instruction.
– Peter Cordes
Feb 15 at 20:45
This would be one of the few situations where I'd agree with usingstd::pair
- where the two elements are more or less interchangeable. On a tangent: I disagree with a lot of the places the standard library usesstd::pair
- for example, think how much more readable code would be if you would writeauto result = m_multiplicities.emplace(k, 1); if (!result.inserted) ++(result.location->value);
as opposed toif (!result.second) ++(result.first->second);
– Daniel Schepler
Feb 15 at 23:49
1
of course, returning an error value likestd::string::npos
means the caller might completely forget to check for it and pass it along to some other code, eventually producing nonsense that's hard to trace back to the original cause. this problem is the entire reason for exceptions (or optional types).
– Eevee
Feb 16 at 8:41
add a comment |
4
Well, I've seen a small codebase once with void functions that returned results by throwing them, andtry-catch
was used as a sort of pattern matching tool. Quite a bizarre design, I have to admit, but it shows how to replacereturn
withthrow
in general.
– Joker_vD
Feb 15 at 18:03
@Joker_vD frankly, I've never seen a function whose all return paths were throws (except "not implemented" style exceptions). But I admit that it would be technically legal C++. So, I've technically lied a bit when I said that returns cannot be replaced.
– eerorika
Feb 15 at 18:09
6
@Joker_vD: it's possible, but would perform like crap on "normal" implementations. Unless they can optimize away the throw/catch, firing up the stack-unwinding exception dispatch code (which has to go read.eh_frame
metadata) is vastly more expensive than aret
instruction.
– Peter Cordes
Feb 15 at 20:45
This would be one of the few situations where I'd agree with usingstd::pair
- where the two elements are more or less interchangeable. On a tangent: I disagree with a lot of the places the standard library usesstd::pair
- for example, think how much more readable code would be if you would writeauto result = m_multiplicities.emplace(k, 1); if (!result.inserted) ++(result.location->value);
as opposed toif (!result.second) ++(result.first->second);
– Daniel Schepler
Feb 15 at 23:49
1
of course, returning an error value likestd::string::npos
means the caller might completely forget to check for it and pass it along to some other code, eventually producing nonsense that's hard to trace back to the original cause. this problem is the entire reason for exceptions (or optional types).
– Eevee
Feb 16 at 8:41
4
4
Well, I've seen a small codebase once with void functions that returned results by throwing them, and
try-catch
was used as a sort of pattern matching tool. Quite a bizarre design, I have to admit, but it shows how to replace return
with throw
in general.– Joker_vD
Feb 15 at 18:03
Well, I've seen a small codebase once with void functions that returned results by throwing them, and
try-catch
was used as a sort of pattern matching tool. Quite a bizarre design, I have to admit, but it shows how to replace return
with throw
in general.– Joker_vD
Feb 15 at 18:03
@Joker_vD frankly, I've never seen a function whose all return paths were throws (except "not implemented" style exceptions). But I admit that it would be technically legal C++. So, I've technically lied a bit when I said that returns cannot be replaced.
– eerorika
Feb 15 at 18:09
@Joker_vD frankly, I've never seen a function whose all return paths were throws (except "not implemented" style exceptions). But I admit that it would be technically legal C++. So, I've technically lied a bit when I said that returns cannot be replaced.
– eerorika
Feb 15 at 18:09
6
6
@Joker_vD: it's possible, but would perform like crap on "normal" implementations. Unless they can optimize away the throw/catch, firing up the stack-unwinding exception dispatch code (which has to go read
.eh_frame
metadata) is vastly more expensive than a ret
instruction.– Peter Cordes
Feb 15 at 20:45
@Joker_vD: it's possible, but would perform like crap on "normal" implementations. Unless they can optimize away the throw/catch, firing up the stack-unwinding exception dispatch code (which has to go read
.eh_frame
metadata) is vastly more expensive than a ret
instruction.– Peter Cordes
Feb 15 at 20:45
This would be one of the few situations where I'd agree with using
std::pair
- where the two elements are more or less interchangeable. On a tangent: I disagree with a lot of the places the standard library uses std::pair
- for example, think how much more readable code would be if you would write auto result = m_multiplicities.emplace(k, 1); if (!result.inserted) ++(result.location->value);
as opposed to if (!result.second) ++(result.first->second);
– Daniel Schepler
Feb 15 at 23:49
This would be one of the few situations where I'd agree with using
std::pair
- where the two elements are more or less interchangeable. On a tangent: I disagree with a lot of the places the standard library uses std::pair
- for example, think how much more readable code would be if you would write auto result = m_multiplicities.emplace(k, 1); if (!result.inserted) ++(result.location->value);
as opposed to if (!result.second) ++(result.first->second);
– Daniel Schepler
Feb 15 at 23:49
1
1
of course, returning an error value like
std::string::npos
means the caller might completely forget to check for it and pass it along to some other code, eventually producing nonsense that's hard to trace back to the original cause. this problem is the entire reason for exceptions (or optional types).– Eevee
Feb 16 at 8:41
of course, returning an error value like
std::string::npos
means the caller might completely forget to check for it and pass it along to some other code, eventually producing nonsense that's hard to trace back to the original cause. this problem is the entire reason for exceptions (or optional types).– Eevee
Feb 16 at 8:41
add a comment |
return
and throw
have two different purposes and should not be considered interchangeable. Use return
when you have a valid result to send back to the caller. On the other hand, use throw
when some exceptional behavior occurs. You can get an idea of how other programmers use throw
by using functions from the standard library and taking note of when they throw exceptions.
add a comment |
return
and throw
have two different purposes and should not be considered interchangeable. Use return
when you have a valid result to send back to the caller. On the other hand, use throw
when some exceptional behavior occurs. You can get an idea of how other programmers use throw
by using functions from the standard library and taking note of when they throw exceptions.
add a comment |
return
and throw
have two different purposes and should not be considered interchangeable. Use return
when you have a valid result to send back to the caller. On the other hand, use throw
when some exceptional behavior occurs. You can get an idea of how other programmers use throw
by using functions from the standard library and taking note of when they throw exceptions.
return
and throw
have two different purposes and should not be considered interchangeable. Use return
when you have a valid result to send back to the caller. On the other hand, use throw
when some exceptional behavior occurs. You can get an idea of how other programmers use throw
by using functions from the standard library and taking note of when they throw exceptions.
answered Feb 15 at 16:24
Code-ApprenticeCode-Apprentice
47.9k1490176
47.9k1490176
add a comment |
add a comment |
In addition to the other answers, there's also performance: Catching an exception incurs a run-time overhead (see this answer) compared to an if
clause.
(Of course, we're talking about microseconds... Whether or not this is relevant depends on your specific use case.)
7
Function call/ret takes about a nanosecond on a 3 to 4 GHz CPU, and can overlap with surrounding work. About 1000x slower sounds plausible. But remember, microseconds is thousands of clock cycles on modern CPUs (during which time they could have executed maybe 1 to 3 instructions per clock, or even more in high-ILP code), and ~ten times longer than even a cache miss that went all the way RAM and stalled out-of-order execution. try/catch instead of return might not optimize away even after inlining, so you will end up with far more of it than you wouldcall
/ret
instructions.
– Peter Cordes
Feb 15 at 20:53
add a comment |
In addition to the other answers, there's also performance: Catching an exception incurs a run-time overhead (see this answer) compared to an if
clause.
(Of course, we're talking about microseconds... Whether or not this is relevant depends on your specific use case.)
7
Function call/ret takes about a nanosecond on a 3 to 4 GHz CPU, and can overlap with surrounding work. About 1000x slower sounds plausible. But remember, microseconds is thousands of clock cycles on modern CPUs (during which time they could have executed maybe 1 to 3 instructions per clock, or even more in high-ILP code), and ~ten times longer than even a cache miss that went all the way RAM and stalled out-of-order execution. try/catch instead of return might not optimize away even after inlining, so you will end up with far more of it than you wouldcall
/ret
instructions.
– Peter Cordes
Feb 15 at 20:53
add a comment |
In addition to the other answers, there's also performance: Catching an exception incurs a run-time overhead (see this answer) compared to an if
clause.
(Of course, we're talking about microseconds... Whether or not this is relevant depends on your specific use case.)
In addition to the other answers, there's also performance: Catching an exception incurs a run-time overhead (see this answer) compared to an if
clause.
(Of course, we're talking about microseconds... Whether or not this is relevant depends on your specific use case.)
answered Feb 15 at 17:08
Pedro LMPedro LM
650310
650310
7
Function call/ret takes about a nanosecond on a 3 to 4 GHz CPU, and can overlap with surrounding work. About 1000x slower sounds plausible. But remember, microseconds is thousands of clock cycles on modern CPUs (during which time they could have executed maybe 1 to 3 instructions per clock, or even more in high-ILP code), and ~ten times longer than even a cache miss that went all the way RAM and stalled out-of-order execution. try/catch instead of return might not optimize away even after inlining, so you will end up with far more of it than you wouldcall
/ret
instructions.
– Peter Cordes
Feb 15 at 20:53
add a comment |
7
Function call/ret takes about a nanosecond on a 3 to 4 GHz CPU, and can overlap with surrounding work. About 1000x slower sounds plausible. But remember, microseconds is thousands of clock cycles on modern CPUs (during which time they could have executed maybe 1 to 3 instructions per clock, or even more in high-ILP code), and ~ten times longer than even a cache miss that went all the way RAM and stalled out-of-order execution. try/catch instead of return might not optimize away even after inlining, so you will end up with far more of it than you wouldcall
/ret
instructions.
– Peter Cordes
Feb 15 at 20:53
7
7
Function call/ret takes about a nanosecond on a 3 to 4 GHz CPU, and can overlap with surrounding work. About 1000x slower sounds plausible. But remember, microseconds is thousands of clock cycles on modern CPUs (during which time they could have executed maybe 1 to 3 instructions per clock, or even more in high-ILP code), and ~ten times longer than even a cache miss that went all the way RAM and stalled out-of-order execution. try/catch instead of return might not optimize away even after inlining, so you will end up with far more of it than you would
call
/ret
instructions.– Peter Cordes
Feb 15 at 20:53
Function call/ret takes about a nanosecond on a 3 to 4 GHz CPU, and can overlap with surrounding work. About 1000x slower sounds plausible. But remember, microseconds is thousands of clock cycles on modern CPUs (during which time they could have executed maybe 1 to 3 instructions per clock, or even more in high-ILP code), and ~ten times longer than even a cache miss that went all the way RAM and stalled out-of-order execution. try/catch instead of return might not optimize away even after inlining, so you will end up with far more of it than you would
call
/ret
instructions.– Peter Cordes
Feb 15 at 20:53
add a comment |
A function should throw an exception when it is unable to meet its postcondition. (Some functions may also throw exceptions when their preconditions are not met; that's a different topic that I won't get into here.) Therefore, if your function must return a pair of integers from the vector summing to the given target, then it has no choice but to throw an exception when it can't find one. But if the function's contract allows it to return a value to indicate it was unable to find such a pair, then it should not throw an exception, since it has the ability to fulfill the contract.
In your case:
- You can make your function return an empty vector when it can't find two integers summing to the given target. Then, it never needs to throw an exception.
- Or, you can make your function return
std::optional<std::pair<int, int>>
. It never needs to throw an exception because it can just return an empty optional when it can't find an appropriate pair. - If, however, you make it return
std::pair<int, int>
, then it should throw an exception because there is no sensible value to return when it can't find an appropriate pair.
Generally, C++ programmers prefer to write functions that don't need to throw exceptions in order to report mere "disappointments", such as search failures, that are easily anticipated and handled locally. The advantages of returning values rather than throwing exceptions are discussed extensively elsewhere so I won't rehash that discussion here.
Thus, declaring "failure" by throwing an exception is usually limited to the following cases:
- The function is a constructor and it's simply not able to establish its class's invariant. It must throw an exception in order to ensure that the calling code doesn't see a broken object.
- An "exceptional" condition arises that should be handled at some higher level than that of the caller. The caller is likely to not know how to recover from the condition. In such cases, the use of the exception mechanism frees up the caller from having to figure out how to proceed when the exceptional condition occurs.
add a comment |
A function should throw an exception when it is unable to meet its postcondition. (Some functions may also throw exceptions when their preconditions are not met; that's a different topic that I won't get into here.) Therefore, if your function must return a pair of integers from the vector summing to the given target, then it has no choice but to throw an exception when it can't find one. But if the function's contract allows it to return a value to indicate it was unable to find such a pair, then it should not throw an exception, since it has the ability to fulfill the contract.
In your case:
- You can make your function return an empty vector when it can't find two integers summing to the given target. Then, it never needs to throw an exception.
- Or, you can make your function return
std::optional<std::pair<int, int>>
. It never needs to throw an exception because it can just return an empty optional when it can't find an appropriate pair. - If, however, you make it return
std::pair<int, int>
, then it should throw an exception because there is no sensible value to return when it can't find an appropriate pair.
Generally, C++ programmers prefer to write functions that don't need to throw exceptions in order to report mere "disappointments", such as search failures, that are easily anticipated and handled locally. The advantages of returning values rather than throwing exceptions are discussed extensively elsewhere so I won't rehash that discussion here.
Thus, declaring "failure" by throwing an exception is usually limited to the following cases:
- The function is a constructor and it's simply not able to establish its class's invariant. It must throw an exception in order to ensure that the calling code doesn't see a broken object.
- An "exceptional" condition arises that should be handled at some higher level than that of the caller. The caller is likely to not know how to recover from the condition. In such cases, the use of the exception mechanism frees up the caller from having to figure out how to proceed when the exceptional condition occurs.
add a comment |
A function should throw an exception when it is unable to meet its postcondition. (Some functions may also throw exceptions when their preconditions are not met; that's a different topic that I won't get into here.) Therefore, if your function must return a pair of integers from the vector summing to the given target, then it has no choice but to throw an exception when it can't find one. But if the function's contract allows it to return a value to indicate it was unable to find such a pair, then it should not throw an exception, since it has the ability to fulfill the contract.
In your case:
- You can make your function return an empty vector when it can't find two integers summing to the given target. Then, it never needs to throw an exception.
- Or, you can make your function return
std::optional<std::pair<int, int>>
. It never needs to throw an exception because it can just return an empty optional when it can't find an appropriate pair. - If, however, you make it return
std::pair<int, int>
, then it should throw an exception because there is no sensible value to return when it can't find an appropriate pair.
Generally, C++ programmers prefer to write functions that don't need to throw exceptions in order to report mere "disappointments", such as search failures, that are easily anticipated and handled locally. The advantages of returning values rather than throwing exceptions are discussed extensively elsewhere so I won't rehash that discussion here.
Thus, declaring "failure" by throwing an exception is usually limited to the following cases:
- The function is a constructor and it's simply not able to establish its class's invariant. It must throw an exception in order to ensure that the calling code doesn't see a broken object.
- An "exceptional" condition arises that should be handled at some higher level than that of the caller. The caller is likely to not know how to recover from the condition. In such cases, the use of the exception mechanism frees up the caller from having to figure out how to proceed when the exceptional condition occurs.
A function should throw an exception when it is unable to meet its postcondition. (Some functions may also throw exceptions when their preconditions are not met; that's a different topic that I won't get into here.) Therefore, if your function must return a pair of integers from the vector summing to the given target, then it has no choice but to throw an exception when it can't find one. But if the function's contract allows it to return a value to indicate it was unable to find such a pair, then it should not throw an exception, since it has the ability to fulfill the contract.
In your case:
- You can make your function return an empty vector when it can't find two integers summing to the given target. Then, it never needs to throw an exception.
- Or, you can make your function return
std::optional<std::pair<int, int>>
. It never needs to throw an exception because it can just return an empty optional when it can't find an appropriate pair. - If, however, you make it return
std::pair<int, int>
, then it should throw an exception because there is no sensible value to return when it can't find an appropriate pair.
Generally, C++ programmers prefer to write functions that don't need to throw exceptions in order to report mere "disappointments", such as search failures, that are easily anticipated and handled locally. The advantages of returning values rather than throwing exceptions are discussed extensively elsewhere so I won't rehash that discussion here.
Thus, declaring "failure" by throwing an exception is usually limited to the following cases:
- The function is a constructor and it's simply not able to establish its class's invariant. It must throw an exception in order to ensure that the calling code doesn't see a broken object.
- An "exceptional" condition arises that should be handled at some higher level than that of the caller. The caller is likely to not know how to recover from the condition. In such cases, the use of the exception mechanism frees up the caller from having to figure out how to proceed when the exceptional condition occurs.
answered Feb 15 at 21:14
BrianBrian
65.1k796183
65.1k796183
add a comment |
add a comment |
What you have mentioned is not good programming practice. Replacing a return
statement with throw
is not acceptable in production-level code, especially with automated testing platforms that generate lists of all exceptions as a way of proving or disproving certain functionality. You have to take into consideration the needs of Software Testers when designing your code. throw
is simply not interchangeable with return
. throw
is used to signal that a program error has occurred by some unexpected phenomena. return
is used to signal method completion. It is common to use return
to transmit error codes, but return values do not cause the program to be interrupted in the same way as throw
does. Additionally, throw
has the power to terminate a program if it is not handled correctly.
Essentially, it is good practice to use throw
when a significant error is detected within the method, but there should always be a clean return if such an error is not detected. Can you make that substitution? Maybe, and maybe it will work logically...but it's not good practice and certainly not a popular implementation.
add a comment |
What you have mentioned is not good programming practice. Replacing a return
statement with throw
is not acceptable in production-level code, especially with automated testing platforms that generate lists of all exceptions as a way of proving or disproving certain functionality. You have to take into consideration the needs of Software Testers when designing your code. throw
is simply not interchangeable with return
. throw
is used to signal that a program error has occurred by some unexpected phenomena. return
is used to signal method completion. It is common to use return
to transmit error codes, but return values do not cause the program to be interrupted in the same way as throw
does. Additionally, throw
has the power to terminate a program if it is not handled correctly.
Essentially, it is good practice to use throw
when a significant error is detected within the method, but there should always be a clean return if such an error is not detected. Can you make that substitution? Maybe, and maybe it will work logically...but it's not good practice and certainly not a popular implementation.
add a comment |
What you have mentioned is not good programming practice. Replacing a return
statement with throw
is not acceptable in production-level code, especially with automated testing platforms that generate lists of all exceptions as a way of proving or disproving certain functionality. You have to take into consideration the needs of Software Testers when designing your code. throw
is simply not interchangeable with return
. throw
is used to signal that a program error has occurred by some unexpected phenomena. return
is used to signal method completion. It is common to use return
to transmit error codes, but return values do not cause the program to be interrupted in the same way as throw
does. Additionally, throw
has the power to terminate a program if it is not handled correctly.
Essentially, it is good practice to use throw
when a significant error is detected within the method, but there should always be a clean return if such an error is not detected. Can you make that substitution? Maybe, and maybe it will work logically...but it's not good practice and certainly not a popular implementation.
What you have mentioned is not good programming practice. Replacing a return
statement with throw
is not acceptable in production-level code, especially with automated testing platforms that generate lists of all exceptions as a way of proving or disproving certain functionality. You have to take into consideration the needs of Software Testers when designing your code. throw
is simply not interchangeable with return
. throw
is used to signal that a program error has occurred by some unexpected phenomena. return
is used to signal method completion. It is common to use return
to transmit error codes, but return values do not cause the program to be interrupted in the same way as throw
does. Additionally, throw
has the power to terminate a program if it is not handled correctly.
Essentially, it is good practice to use throw
when a significant error is detected within the method, but there should always be a clean return if such an error is not detected. Can you make that substitution? Maybe, and maybe it will work logically...but it's not good practice and certainly not a popular implementation.
edited Feb 15 at 17:34
Ted Lyngmo
2,9672518
2,9672518
answered Feb 15 at 16:46
armitusarmitus
1497
1497
add a comment |
add a comment |
No, throw
is not a good semantic replacement for return
. You only want to use throw
when your code has done something that it should not be doing, not to signify the perfectly valid negative result of a function.
As a general rule, exceptions are meant to signify when something abnormal or unexpected has happened during the execution of your code. Looking at the purpose of your function, the occurrence of no two integers in the passed vector summing to target
is a very possible result of the function, so that result is not abnormal and therefore should not be treated as exceptional.
add a comment |
No, throw
is not a good semantic replacement for return
. You only want to use throw
when your code has done something that it should not be doing, not to signify the perfectly valid negative result of a function.
As a general rule, exceptions are meant to signify when something abnormal or unexpected has happened during the execution of your code. Looking at the purpose of your function, the occurrence of no two integers in the passed vector summing to target
is a very possible result of the function, so that result is not abnormal and therefore should not be treated as exceptional.
add a comment |
No, throw
is not a good semantic replacement for return
. You only want to use throw
when your code has done something that it should not be doing, not to signify the perfectly valid negative result of a function.
As a general rule, exceptions are meant to signify when something abnormal or unexpected has happened during the execution of your code. Looking at the purpose of your function, the occurrence of no two integers in the passed vector summing to target
is a very possible result of the function, so that result is not abnormal and therefore should not be treated as exceptional.
No, throw
is not a good semantic replacement for return
. You only want to use throw
when your code has done something that it should not be doing, not to signify the perfectly valid negative result of a function.
As a general rule, exceptions are meant to signify when something abnormal or unexpected has happened during the execution of your code. Looking at the purpose of your function, the occurrence of no two integers in the passed vector summing to target
is a very possible result of the function, so that result is not abnormal and therefore should not be treated as exceptional.
answered Feb 15 at 18:50
Abion47Abion47
6,51821639
6,51821639
add a comment |
add a comment |
Just because the function is throwing as the last call, doesn't mean it is replacing return. It is just the flow of logic.
The question shouldn't be :
is it a good practice to replace return with throw?
Instead it should be about how to define your API and contracts.
If You want to guarantee to the users of the function that vector
is never empty, then throwing an exception is a good idea.
If you want to guarantee that your function doesn't throw exceptions instead returns an empty vector
on certain conditions, then throwing is a bad idea.
In both cases, the user has to know, what actions they have to take to correctly use your function.
add a comment |
Just because the function is throwing as the last call, doesn't mean it is replacing return. It is just the flow of logic.
The question shouldn't be :
is it a good practice to replace return with throw?
Instead it should be about how to define your API and contracts.
If You want to guarantee to the users of the function that vector
is never empty, then throwing an exception is a good idea.
If you want to guarantee that your function doesn't throw exceptions instead returns an empty vector
on certain conditions, then throwing is a bad idea.
In both cases, the user has to know, what actions they have to take to correctly use your function.
add a comment |
Just because the function is throwing as the last call, doesn't mean it is replacing return. It is just the flow of logic.
The question shouldn't be :
is it a good practice to replace return with throw?
Instead it should be about how to define your API and contracts.
If You want to guarantee to the users of the function that vector
is never empty, then throwing an exception is a good idea.
If you want to guarantee that your function doesn't throw exceptions instead returns an empty vector
on certain conditions, then throwing is a bad idea.
In both cases, the user has to know, what actions they have to take to correctly use your function.
Just because the function is throwing as the last call, doesn't mean it is replacing return. It is just the flow of logic.
The question shouldn't be :
is it a good practice to replace return with throw?
Instead it should be about how to define your API and contracts.
If You want to guarantee to the users of the function that vector
is never empty, then throwing an exception is a good idea.
If you want to guarantee that your function doesn't throw exceptions instead returns an empty vector
on certain conditions, then throwing is a bad idea.
In both cases, the user has to know, what actions they have to take to correctly use your function.
answered Feb 16 at 16:42
Robert AndrzejukRobert Andrzejuk
2,95621425
2,95621425
add a comment |
add a comment |
Your question is language agnostic.
Return and Throw have different purposes.
- Return is for returning a value; while,
- Throw is for throwing an exception; and,
- An exception should be thrown in truly exceptional conditions.
Bonus Content (from Steve McConnell’s Code Complete 2)
Here are all the alternatives available to you when you encounter a situation where you cannot return normally:
Return a neutral value like -1 from a method that’s supposed to return count of something;
Return the closest legal value like 0 on the digital speedometer of a car when it is going in reverse;
Return same value as previous call like a temperature reading on a thermometer when you are reading every second and you know that the readings do not differ drastically in such a short interval;
Return the next valid piece of data like when you are reading rows from a table and a specific row is corrupt;
Set/Return an error status/code/object found pretty commonly in C++ library calls;
Display a message in an alert box but be careful to not give out too much that can assist a malicious actor;
Log to a file;
Throw an exception like you are pondering upon;
Call a central error handler/routine if that is how your system is designed;
Shutdown.
Further, you do not need to pick only one of the above options. You can do a combination like, for example, logging to file and displaying a message to the user.
What approach you should take is a question of Correctness vs Robustness. Do you want your program to be absolutely correct and shutdown when an erroneous situation is encountered or do you want your program to be robust and continue with execution when at some point it fails to follow the desired path?
add a comment |
Your question is language agnostic.
Return and Throw have different purposes.
- Return is for returning a value; while,
- Throw is for throwing an exception; and,
- An exception should be thrown in truly exceptional conditions.
Bonus Content (from Steve McConnell’s Code Complete 2)
Here are all the alternatives available to you when you encounter a situation where you cannot return normally:
Return a neutral value like -1 from a method that’s supposed to return count of something;
Return the closest legal value like 0 on the digital speedometer of a car when it is going in reverse;
Return same value as previous call like a temperature reading on a thermometer when you are reading every second and you know that the readings do not differ drastically in such a short interval;
Return the next valid piece of data like when you are reading rows from a table and a specific row is corrupt;
Set/Return an error status/code/object found pretty commonly in C++ library calls;
Display a message in an alert box but be careful to not give out too much that can assist a malicious actor;
Log to a file;
Throw an exception like you are pondering upon;
Call a central error handler/routine if that is how your system is designed;
Shutdown.
Further, you do not need to pick only one of the above options. You can do a combination like, for example, logging to file and displaying a message to the user.
What approach you should take is a question of Correctness vs Robustness. Do you want your program to be absolutely correct and shutdown when an erroneous situation is encountered or do you want your program to be robust and continue with execution when at some point it fails to follow the desired path?
add a comment |
Your question is language agnostic.
Return and Throw have different purposes.
- Return is for returning a value; while,
- Throw is for throwing an exception; and,
- An exception should be thrown in truly exceptional conditions.
Bonus Content (from Steve McConnell’s Code Complete 2)
Here are all the alternatives available to you when you encounter a situation where you cannot return normally:
Return a neutral value like -1 from a method that’s supposed to return count of something;
Return the closest legal value like 0 on the digital speedometer of a car when it is going in reverse;
Return same value as previous call like a temperature reading on a thermometer when you are reading every second and you know that the readings do not differ drastically in such a short interval;
Return the next valid piece of data like when you are reading rows from a table and a specific row is corrupt;
Set/Return an error status/code/object found pretty commonly in C++ library calls;
Display a message in an alert box but be careful to not give out too much that can assist a malicious actor;
Log to a file;
Throw an exception like you are pondering upon;
Call a central error handler/routine if that is how your system is designed;
Shutdown.
Further, you do not need to pick only one of the above options. You can do a combination like, for example, logging to file and displaying a message to the user.
What approach you should take is a question of Correctness vs Robustness. Do you want your program to be absolutely correct and shutdown when an erroneous situation is encountered or do you want your program to be robust and continue with execution when at some point it fails to follow the desired path?
Your question is language agnostic.
Return and Throw have different purposes.
- Return is for returning a value; while,
- Throw is for throwing an exception; and,
- An exception should be thrown in truly exceptional conditions.
Bonus Content (from Steve McConnell’s Code Complete 2)
Here are all the alternatives available to you when you encounter a situation where you cannot return normally:
Return a neutral value like -1 from a method that’s supposed to return count of something;
Return the closest legal value like 0 on the digital speedometer of a car when it is going in reverse;
Return same value as previous call like a temperature reading on a thermometer when you are reading every second and you know that the readings do not differ drastically in such a short interval;
Return the next valid piece of data like when you are reading rows from a table and a specific row is corrupt;
Set/Return an error status/code/object found pretty commonly in C++ library calls;
Display a message in an alert box but be careful to not give out too much that can assist a malicious actor;
Log to a file;
Throw an exception like you are pondering upon;
Call a central error handler/routine if that is how your system is designed;
Shutdown.
Further, you do not need to pick only one of the above options. You can do a combination like, for example, logging to file and displaying a message to the user.
What approach you should take is a question of Correctness vs Robustness. Do you want your program to be absolutely correct and shutdown when an erroneous situation is encountered or do you want your program to be robust and continue with execution when at some point it fails to follow the desired path?
answered Feb 16 at 5:16
displayNamedisplayName
8,97333556
8,97333556
add a comment |
add a comment |
I think it is the wrong question asking if return can be replaced by throw. return and throw are doing two very different things:
return is used to return regular results of a functions.
throw is the preferred method to react on error conditions when a result value does not exist.
The alternative reaction on errors could be to return special error code values. This has some disadvantages, e.g.:
- Using a function gets more difficult if you always have to keep error codes etc. in mind.
- The caller might forget to handle the error. When you forget an exception handler, you will get unhandled exception. It is very likely that you will detect this bug.
- The error might be too complex to be expressed by a single error code properly. An exception can be an object containing all the information you need.
- The errors are handled at a well-defined position (the exception handler). This will make your code much clearer than checking the return value for special values after each call.
In your example the answer depends on the semantics of the function:
If an empty vector is an acceptable return value, then you should use return if no pair is found.
If it is expected that there MUST be matching pairs always, then finding no pair obviously is an error. You should use throw in this case.
New contributor
add a comment |
I think it is the wrong question asking if return can be replaced by throw. return and throw are doing two very different things:
return is used to return regular results of a functions.
throw is the preferred method to react on error conditions when a result value does not exist.
The alternative reaction on errors could be to return special error code values. This has some disadvantages, e.g.:
- Using a function gets more difficult if you always have to keep error codes etc. in mind.
- The caller might forget to handle the error. When you forget an exception handler, you will get unhandled exception. It is very likely that you will detect this bug.
- The error might be too complex to be expressed by a single error code properly. An exception can be an object containing all the information you need.
- The errors are handled at a well-defined position (the exception handler). This will make your code much clearer than checking the return value for special values after each call.
In your example the answer depends on the semantics of the function:
If an empty vector is an acceptable return value, then you should use return if no pair is found.
If it is expected that there MUST be matching pairs always, then finding no pair obviously is an error. You should use throw in this case.
New contributor
add a comment |
I think it is the wrong question asking if return can be replaced by throw. return and throw are doing two very different things:
return is used to return regular results of a functions.
throw is the preferred method to react on error conditions when a result value does not exist.
The alternative reaction on errors could be to return special error code values. This has some disadvantages, e.g.:
- Using a function gets more difficult if you always have to keep error codes etc. in mind.
- The caller might forget to handle the error. When you forget an exception handler, you will get unhandled exception. It is very likely that you will detect this bug.
- The error might be too complex to be expressed by a single error code properly. An exception can be an object containing all the information you need.
- The errors are handled at a well-defined position (the exception handler). This will make your code much clearer than checking the return value for special values after each call.
In your example the answer depends on the semantics of the function:
If an empty vector is an acceptable return value, then you should use return if no pair is found.
If it is expected that there MUST be matching pairs always, then finding no pair obviously is an error. You should use throw in this case.
New contributor
I think it is the wrong question asking if return can be replaced by throw. return and throw are doing two very different things:
return is used to return regular results of a functions.
throw is the preferred method to react on error conditions when a result value does not exist.
The alternative reaction on errors could be to return special error code values. This has some disadvantages, e.g.:
- Using a function gets more difficult if you always have to keep error codes etc. in mind.
- The caller might forget to handle the error. When you forget an exception handler, you will get unhandled exception. It is very likely that you will detect this bug.
- The error might be too complex to be expressed by a single error code properly. An exception can be an object containing all the information you need.
- The errors are handled at a well-defined position (the exception handler). This will make your code much clearer than checking the return value for special values after each call.
In your example the answer depends on the semantics of the function:
If an empty vector is an acceptable return value, then you should use return if no pair is found.
If it is expected that there MUST be matching pairs always, then finding no pair obviously is an error. You should use throw in this case.
New contributor
New contributor
answered 20 hours ago
berniebernie
11
11
New contributor
New contributor
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54713231%2fusing-throw-to-replace-return-in-c-non-void-functions%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
12
It really just depends on if finding a result is an exceptional situation or not and on how you want your function to behave.
– François Andrieux
Feb 15 at 16:21
3
Good practice,maybe.
std::optional
is my preferred solution if no result isn't exceptional.– NathanOliver
Feb 15 at 16:21
25
Exceptions are for exceptional situations. So it depends on your function. If your function is always expected to return a result, then throwing would make sense. Otherwise, if "nothing found" is a valid result, then you are better off with something like
std::optional
.– 0x5453
Feb 15 at 16:21
6
Is this really an exceptional case? If there was nothing to do then no results (i.e., an empty
vector
) conveys that. This is completely different than an internal failure that caused computing the results to fail.– James Adkison
Feb 15 at 16:22
9
Note that if what you are actually doing is replacing a
return
with athrow
in the sense that you want to return a result viathrow
, then it's a very bad idea. This is not what you are doing here.throw
is being used to signal a failure which is what it's designed for.– François Andrieux
Feb 15 at 16:22