How can I abstract out a repeating try catch pattern in C++

Viewed 9534

I have a pattern that repeats for several member functions that looks like this:

int myClass::abstract_one(int sig1)
{
  try {
    return _original->abstract_one(sig1);
  } catch (std::exception& err) {
    handleException(err);
  } catch (...) {
    handleException();
  }
}

bool myClass::abstract_two(int sig2)
{
  try {
    return _original->abstract_two(sig2);
  } catch (std::exception& err) {
    handleException(err);
  } catch (...) {
    handleException();
  }
}

[...]

int myClass::abstract_n(bool sig3a, short sig3b)
{
  try {
    return _original->abstract_n(sig3a, sig3b);
  } catch (std::exception& err) {
    handleException(err);
  } catch (...) {
    handleException();
  }
}

Where abstract one through n are methods of a pure virtual abstract interface for which myClass and _original are concrete implementations.

I don't like that this pattern repeats in the code and would like to find a way to eliminate the repeating try / catch pattern and code as a single abstraction, but I can't think of a good way to do this in C++ without macros. I would think that there is a way with templates to do this better.

Please suggest a clean way to refactor this code to abstract out the repeated pattern.

8 Answers

A bit of an old question, but these days we can also craft an elegant generic solution with variadic templates and std::invoke. (Requires C++17)

template<typename Action, typename... Args>
int MyClass::abstract(Action action, Args&&... args)
{
    try {
        return std::invoke(action, std::forward<Args>(args)...);
    } catch (std::exception& err) {
        handleException(err);
    } catch (...) {
        handleException();
    }
}

Here action can be a lambda, function pointer, or even member function pointers thanks to std::invoke. For example:

my_class->abstract(&Original::abstract_n, original, sig3a, sig3b);
Related