bob
bob

Reputation: 2011

how to return multiple error codes from C++ function

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

Answers (10)

teksturi
teksturi

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

young
young

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

Martin Cote
Martin Cote

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

maxaposteriori
maxaposteriori

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

Igor
Igor

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

Dietrich Epp
Dietrich Epp

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

Josef Pfleger
Josef Pfleger

Reputation: 74527

You can use an integer with bit manipulation (aka flags).

Upvotes: 2

jmucchiello
jmucchiello

Reputation: 18984

You need to return them as output parameters:

 bool function(int& error1, int& error2, stringx& errorText, int& error3);

Upvotes: 2

James Curran
James Curran

Reputation: 103505

The simplest way to return two values is with the std::pair<> template:

Upvotes: 4

Jordan Parmer
Jordan Parmer

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

Related Questions