4

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).

bob
  • 1,941
  • 6
  • 26
  • 36
  • Why do you need to provide multiple error codes? Perhaps if you give us more information about the usage pattern of such a function, the reason for multiple error codes, or whatnot, the perhaps someone has a better solution for you. – Lasse V. Karlsen Jun 01 '09 at 21:44
  • 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). – bob Jun 01 '09 at 21:49

9 Answers9

7

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?

Jordan Parmer
  • 36,042
  • 30
  • 97
  • 119
  • An object is a nice solution as you can return essentially anything you want, e.g. error codes, error strings etc. – Soo Wei Tan Jun 01 '09 at 21:45
6

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.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
  • 4
    While I have nothing against exceptions, sometimes it's better to use error codes. I think saying you "should use" exceptions goes a bit too far. – David Thornley Jun 01 '09 at 21:57
  • And an exception class can carry all that detail information the OP asked for as attributes. – lothar Jun 01 '09 at 22:00
  • 1
    Exceptions are usfull when the context of the error does not provide enough information to handle the problem. By using an exception you can transfer the error handling to a higher level with more context. BUT if you have enough context at the current level then error code are fine and are preferable ot exceptions. – Martin York Jun 02 '09 at 00:34
  • 1
    See: http://stackoverflow.com/questions/106586/what-are-the-principles-guiding-your-exception-handling-policy/106749#106749 for more comments on when to use exceptions. – Martin York Jun 02 '09 at 00:37
  • I agree with the sentiment of this answer - exceptions should generally be considered first and rejected only with good reason, which the author alluded to in his answer. Using exceptions generally results in cleaner and more maintainable code. – markh44 Jun 02 '09 at 12:00
  • @markh44: I agree for public methods. For private methods I would reverse the logic (but only for following the logic I explained above). – Martin York Jun 02 '09 at 13:25
6

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;
Martin Cote
  • 28,864
  • 15
  • 75
  • 99
  • 1
    You can use tiers to ungroup the touple: http://www.boost.org/doc/libs/1_39_0/libs/tuple/doc/tuple_users_guide.html#tiers – Martin York Jun 02 '09 at 00:32
4

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

James Curran
  • 101,701
  • 37
  • 181
  • 258
3

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.
}
maxaposteriori
  • 7,267
  • 4
  • 28
  • 25
2

You need to return them as output parameters:

 bool function(int& error1, int& error2, stringx& errorText, int& error3);
jmucchiello
  • 18,754
  • 7
  • 41
  • 61
2

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

Josef Pfleger
  • 74,165
  • 16
  • 97
  • 99
  • +1 Good idea for limited count of errors, maybe you could expand your answer with some code... – Daniel Wedlund Jun 01 '09 at 22:01
  • To solve the readability, you can always use bit fields which provides names for each flag, allows "normal" boolean operators instead of bit shift operators, and takes the same space as an int. – Max Lybbert Jun 01 '09 at 23:05
  • This is the pro way and it does not cost a thing in CPU time to implement. – toto Jun 02 '09 at 03:48
2

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.

young
  • 2,163
  • 12
  • 19
0

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.

Igor
  • 26,650
  • 27
  • 89
  • 114