Reputation: 2011
What is a good way to return success or one or more error codes from a C++ function?
I have this member function called save(), which saves to each of the member variables, there are at least ten of these member variables that are saved-to, for the call to save(), I want to find out if the call failed, and if so, on which member variable (some are hard failures, some are soft).
Upvotes: 4
Views: 4333
Reputation: 99
Vector should store multiple errors. Then by simplest way to check if vector is empty.
Example in godbolt: https://godbolt.org/z/TzhhEsGbf
#include <iostream>
#include <vector>
#include <string>
enum class ErrorCode {
None,
MemberVar1Error,
MemberVar2Error
};
struct Error {
ErrorCode code;
std::string message;
Error(ErrorCode code, const std::string& message)
: code(code), message(message) {}
};
class MyClass {
public:
std::vector<Error> save() {
std::vector<Error> errors;
if (!saveMemberVar1()) {
errors.emplace_back(ErrorCode::MemberVar1Error, "Failed to save memberVar1");
}
if (!saveMemberVar2()) {
errors.emplace_back(ErrorCode::MemberVar2Error, "Failed to save memberVar2");
}
return errors;
}
private:
bool saveMemberVar1() {
// Simulate a failure
return false;
}
bool saveMemberVar2() {
return true;
}
};
int main() {
MyClass myObject;
if (auto errors = myObject.save(); !errors.empty()) {
std::cout << "Save operation failed with the following errors:\n";
for (const auto& error : errors) {
std::cout << "Error: " << static_cast<int>(error.code) << " - " << error.message << "\n";
}
} else {
std::cout << "Save operation succeeded\n";
}
return 0;
}
Upvotes: 0
Reputation: 2181
I probably try to throw an exception first but it depends on your coding paradigm. Please check some books or articles about reasons why c++ exception handling might be better.
If I really need to stick to retrun-error-code style, I would define a eunm type for specifying errors with bit operations..
enum error
{
NO_ERROR = 0,
MEMBER_0_NOT_SAVED = 1,
MEMBER_1_NOT_SAVED = 1 << 1,
MEMBER_2_NOT_SAVED = 1 << 2,
// etc..
};
int save()
{
int ret = NO_ERROR;
// fail to save member_0
ret |= MEMBER_0_NOT_SAVED;
// fail to save member_1
ret |= MEMBER_1_NOT_SAVED;
// ....
return ret;
}
int main(void)
{
int ret = save();
if( ret == NO_ERROR)
{
// good.
}
else
{
if(ret & MEMBER_0_NOT_SAVED)
{
// do something
}
if(ret & MEMBER_1_NOT_SAVED)
{
// do something
}
// check the other errors...
}
}
This is just a rough example. It's better to put this into a class or use a namespace.
Upvotes: 2
Reputation: 29852
I usually use a boost::tuple
:
typedef boost::tuple<int,int> return_value;
return_value r = my_function();
int first_value = boost::get<0>( r );
int second_valud = boost::get<1>( r );
EDIT
You can also use boost::tie
to extract the values from a tuple:
boost::tie( first_value, second_value ) = r;
Upvotes: 6
Reputation: 7337
I would use a bitset if you're intention is to purely return error states. e.g.
const bitset<10> a_not_set(1);
const bitset<10> b_not_set(2);
const bitset<10> c_not_set(4);
...
bitset<10> foo(T& a, T& b, T& c, ...)
{
bitset<10> error_code = 0;
...
if ( /* a can't be set */ )
{
error_code |= a_not_set;
}
...
if ( /* b can't be set */ )
{
error_code |= b_not_set;
}
...
// etc etc
return error_code;
}
bitset<10> err = foo(a, b, c, ... );
if (err && a_not_set)
{
// Blah.
}
Upvotes: 3
Reputation: 27250
I am not familiar with the internals and constrains of your project, but if possible, try to use exceptions instead of error codes.
The reasons are listed here, at C++ FAQ lite, and they conclude with:
So compared to error reporting via return-codes and if, using try / catch / throw is likely to result in code that has fewer bugs, is less expensive to develop, and has faster time-to-market.
Upvotes: 0
Reputation: 213338
I know this doesn't really answer your question, but...
In C++ you should use exceptions instead of returning error codes. Error codes are most commonly used by libraries which don't want to force the library user to use a particular error handling convention, but in C++, we already have stdexcept. Of course, there might be reasons you don't use exceptions, such as if you're writing embedded code or kernel extensions.
Upvotes: 6
Reputation: 18984
You need to return them as output parameters:
bool function(int& error1, int& error2, stringx& errorText, int& error3);
Upvotes: 2
Reputation: 103505
The simplest way to return two values is with the std::pair<> template:
Upvotes: 4
Reputation: 37174
You can either return an object that has multiple error fields or you can use 'out'parameters.
How you do this depends on your design and what exactly you are trying to return back. A common scenario is when you need to report back a status code along with a message of sorts. This is sometimes done where the function returns the status code as the return value and then returns the message status via an 'out' parameter.
If you are simply returning a set of 'codes', it might make more sense to construct a struct type and return that. In that case, I would be prone to pass it in as an out parameter and have the method internally update it instead of allocating a new one each time.
Are you planning on doing this once or many times?
Upvotes: 7