Using `throw;` on a modified exception

C++ExceptionException HandlingLanguage LawyerThrow

C++ Problem Overview


I have a function foo that can throw a bar exception.

In another function I call foo but I have the ability to add some more detail to the bar exception if thrown. (I'd rather not pass such information as a parameter to foo as it doesn't really belong there due to the generic nature of that function.)

So I do this in the caller:

try {
    foo();
} catch (bar& ex){
    ex.addSomeMoreInformation(...);
    throw;
}

Will throw re-throw the modified exception or do I need to use throw ex;? The latter would presumably take a value copy so I'd rather not do that. Would throw take a value copy too? I suspect it wouldn't.

(I'm aware I could verify but I'm concerned about stumbling on an unspecified or undefined construct so would like to know for sure).

C++ Solutions


Solution 1 - C++

Actually, the standard is very precise here. [except.handle]/17:

> When the handler declares a reference to a non-constant object, any > changes to the referenced object are changes to the temporary object > initialized when the throw-expression was executed and will have > effect should that object be rethrown.

And [except.throw]/8:

> A throw-expression with no operand rethrows the currently handled > exception (15.3).

Solution 2 - C++

C++11 §15.1/8:

> A throw-expression with no operand rethrows the currently handled exception (15.3). The exception is reactivated with the existing temporary; no new temporary exception object is created.

Solution 3 - C++

throw (without an exception object) will rethrow the current exception. (must be inside catch block, otherwise std::terminate is called). Because you changed the reference of current exception object, you don't need to explicilty throw the object and throw re-throw the modified exception and no new temporary object is created.

Solution 4 - C++

In this case you should use throw to get the desired behavior...i.e throw would throw the modified exception as the exception was caught by reference.

Let me try to make difference between these throw explicit through examples:-

class exception
{
};

class MyException : public exception
{
};

void func()
{
  try
  {
    throw MyException();
  }
  catch( exception& e )
  {
    //do some modification.
    throw;                    //Statement_1
    throw e;                  //Statement_2
   }
}

Statment_1:-

What throw does is it just re-throws what the current exception is i.e it doesn't make further copies ( as was made when exception was thrown initially). So if you make any changes to the caught exception here...it would also be there in the caller routine.

Statement_2:-

This is throwing the "exception" which was originally caught as MyException i.e it would make the copy again. So, just forget about changes you made it won't even passes or*ginal exception to the caller. It throws "exception" to the caller routine.

Hope I am clear ( and RIGHT ON TRACK OF C++ STANDARD )enough...

Solution 5 - C++

according to this,throwing exceptions in c++ can be done in two ways:

  1. throw expression: First, copy-initializes the exception object from expression (this may call the move constructor for rvalue expression, and the copy/move may be subject to copy elision), then transfers control to the exception handler with the matching type whose compound statement or member initializer list was most recently entered and not exited by this thread of execution.
  2. throw: Rethrows the currently handled exception. Abandons the execution of the current catch block and passes control to the next matching exception handler (but not to another catch clause after the same try block: its compound-statement is considered to have been 'exited'), reusing the existing exception object: no new objects are made. This form is only allowed when an exception is presently being handled (it calls std::terminate if used otherwise). The catch clause associated with a function-try-block must exit via rethrowing if used on a constructor.

So to underline my answer, throw should be fine in your case.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionP45 ImminentView Question on Stackoverflow
Solution 1 - C++ColumboView Answer on Stackoverflow
Solution 2 - C++Cheers and hth. - AlfView Answer on Stackoverflow
Solution 3 - C++Gyapti JainView Answer on Stackoverflow
Solution 4 - C++raviView Answer on Stackoverflow
Solution 5 - C++PandreiView Answer on Stackoverflow