Search code examples
c++try-catchrethrow

Can I still rethrow an exception from within a function called within a catch block?


I have the following structure in the legacy codebase:

try{
...
}
catch(Type1&){
...
}
catch(Type2&){
...
}
...

And with copy-paste development, the same catch blocks show up everywhere. Now, I would write a function like this:

void catchErrors(){
  try{
    throw;
  }
  catch(Type1&){
    ...
  }
  ...
}

and put it into the code like this:

try{
  ...
}
catch(...){
  catchErrors();
}

Will this be a valid refactor, resulting in the same functionality?
(And do you have any better suggestion for the refactor?)


Solution

  • Yes, that's valid.

    [C++14: 15.1/8]: A throw-expression with no operand rethrows the currently handled exception (15.3). The exception is reactivated with the existing exception object; no new exception object is created. The exception is no longer considered to be caught; therefore, the value of std::uncaught_exception() will again be true.

    [ Example: code that must be executed because of an exception yet cannot completely handle the exception can be written like this:

    try {
      // ...
    } catch (...) { // catch all exceptions
      // respond (partially) to exception
      throw; // pass the exception to some
      // other handler
    }
    

    —end example ]

    [C++14: 15.1/9]: If no exception is presently being handled, executing a throw-expression with no operand calls std::terminate() (15.5.1).

    Although the throw-expression has been moved into its own function, during its execution an exception is still being handled, so it still works:

    #include <iostream>
    
    void bar()
    {
        try {
            throw;
        }
        catch (int x) {
            std::cerr << "Damn " << x << "!\n";
        }
    }
    
    void foo()
    {
        try {
            throw 42;
        }
        catch (...) {
            bar();
        }
    }
    
    int main()
    {
        foo();
    }
    
    // Output: Damn 42!
    

    (live demo)