Reputation: 399
I have a function that returns a 'vector'. However, sometimes during runtime the function can encounter an error in which it should not return the vector but instead return a value that can be checked by caller. Should I handle this by throwing an exception and catching it in the caller or should I change the return type of the function to 'std::pair' that stores a return value (0 or 1) and the vector. I don't want to exit the program with 'std::runtime 'error if the conditions occurs.
std::vector<int> function() {
std::vector ans;
//do stuff
if (something happens)
return -1;
return ans;
}
Upvotes: 1
Views: 1411
Reputation: 38209
My first choice would be a std::variant
(it is better then std::optional
since it can provide extra information in case of error and this is always beneficial in the future):
usign ErrorType = int;
using ReturnType = std::variant<std::vector<int>, ErrorType>
ReturnType function() {
std::vector ans;
//do stuff
if (something happens)
return -1;
return ans;
}
If your error is quite rare and exception could be cough in deeper caller level then exception is also a good/better way:
class MyException : public std::exception {
public:
MyException(int errorCode) : exception("MyException"), errorCode(errorCode)
{}
int code() const { return errorCode; }
private:
int errorCode;
};
std::vector<int> function() {
std::vector ans;
//do stuff
if (something happens)
throw MyException{ -1 };
return ans;
}
Please remember that in C++ exceptions are design in such way that they are zero cost when nothing is thrown. Trade of is that when something exception is thrown unwinding a stack is extremely slow (on some cpp-con someone said that it is x40 slower, I didn't measure it). This is the reason use of std::optional
or std::variant
instead of exception can be so beneficial.
AFAIK standard comity is working on new kind of exceptions mechanism which will behave like std::variant
(similar how this is made in Swift).
Upvotes: 3
Reputation: 385405
This sounds like a good time for an exception. Make a throwable type that can have a constructor argument, some sort of code that explains the problem. The catcher can check that code.
People will suggest std::variant
and such instead, but that gets messy quite quickly and causes your function's signature to balloon. It also complicates the code at the callsite. There's no need for it here. Exceptions were literally designed for this use case.
Upvotes: 4