Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a macro to catch a set of exceptions at different places fine?

I have a set of functions and need to convert potentially thrown exceptions into error codes.

To this end I have wrapped the actual calls with try/catch statements:

int f_with_error_codes()
{
  try {
    f(); // wrapped function call

    return E_SUCCESS;
  }
  catch (error1&) {
    return E_ERROR1;
  }
  catch (error2&) {
    return E_ERROR2;
  }
}

int g_with_error_codes(int a);
{
  try {
    G g(a);        // wrapped expressions
    g.print();

    return E_SUCCESS;
  }
  catch (error1&) {
    return E_ERROR1;
  }
  catch (error2&) {
    return E_ERROR2;
  }
}

...

These catch statmements repeat themselves. Additionally whenever a new exception is added a new catch clause has to be added to every call wrapper.

Is a macro like below for replacing the catch statements appropriate?

#define CATCH_ALL_EXCEPTIONS  \
catch (error1&) {             \
  return E_ERROR1;            \
}                             \
catch (error2&) {             \
  return E_ERROR2;            \
}

Which would results in:

int f_with_error_codes()
{
  try {
    f(); // the wrapped

    return E_SUCCESS;
  }
  CATCH_ALL_EXCEPTIONS
like image 699
Micha Wiedenmann Avatar asked Oct 22 '12 08:10

Micha Wiedenmann


2 Answers

You can use a function instead of a macro like this:

int f_with_error_codes() 
{ 
  try { 
    f(); // wrapped function call 

    return E_SUCCESS; 
  } 
  catch (...) { 
    return error_code();
  } 
}

int error_code()
{
  try { 
    throw;
  } 
  catch (error1&) { 
    return E_ERROR1; 
  } 
  catch (error2&) { 
    return E_ERROR2; 
  } 
}
like image 141
Henrik Avatar answered Sep 28 '22 02:09

Henrik


For your case, you don't need any macro.
Just a simple base class containing virtual function will be sufficient.

class error : public std::exception { // std::exception is your wish
  const char* what () throw(); // needed if std::exception is based
  virtual int GetValue () const = 0;  // <--- This is the core part
}

Now, inherit this class with all the error# classes:

class error1 : public error {
  virtual int GetValue () const { return E_ERROR1; } // <--- override
};
// ...

Finally your code is as easy as this:

void f_with_error_codes()
{
  try {
    f(); // wrapped function call
    return E_SUCCESS;
  }
  catch (error& e) {  // <--- base handle
    return e.GetValue();
  }
}

Don't bother about the cost of virtual function here. Because it's minimal and also exceptions are rare events; a very small cost of virtualness is worth for making your code maintainable and extendable.

like image 34
iammilind Avatar answered Sep 28 '22 03:09

iammilind