18 Exception handling [except]

18.3 Handling an exception [except.handle]

The exception-declaration in a handler describes the type(s) of exceptions that can cause that handler to be entered.
The exception-declaration shall not denote an incomplete type, an abstract class type, or an rvalue reference type.
The exception-declaration shall not denote a pointer or reference to an incomplete type, other than void*, const void*, volatile void*, or const volatile void*.
A handler of type “array of T” or function type T is adjusted to be of type “pointer to T.
A handler is a match for an exception object of type E if
[Note
:
A throw-expression whose operand is an integer literal with value zero does not match a handler of pointer or pointer-to-member type.
A handler of reference to array or function type is never a match for any exception object ([expr.throw]).
end note
]
[Example
:
class Matherr { /* ... */ virtual void vf(); };
class Overflow: public Matherr { /* ... */ };
class Underflow: public Matherr { /* ... */ };
class Zerodivide: public Matherr { /* ... */ };

void f() {
  try {
    g();
  } catch (Overflow oo) {
    // ...
  } catch (Matherr mm) {
    // ...
  }
}
Here, the Overflow handler will catch exceptions of type Overflow and the Matherr handler will catch exceptions of type Matherr and of all types publicly derived from Matherr including exceptions of type Underflow and Zerodivide.
end example
]
The handlers for a try block are tried in order of appearance.
[Note
:
This makes it possible to write handlers that can never be executed, for example by placing a handler for a final derived class after a handler for a corresponding unambiguous public base class.
end note
]
A ... in a handler's exception-declaration functions similarly to ... in a function parameter declaration; it specifies a match for any exception.
If present, a ... handler shall be the last handler for its try block.
If no match is found among the handlers for a try block, the search for a matching handler continues in a dynamically surrounding try block of the same thread.
A handler is considered active when initialization is complete for the parameter (if any) of the catch clause.
[Note
:
The stack will have been unwound at that point.
end note
]
Also, an implicit handler is considered active when std​::​terminate() is entered due to a throw.
A handler is no longer considered active when the catch clause exits.
The exception with the most recently activated handler that is still active is called the currently handled exception.
If no matching handler is found, the function std​::​terminate() is called; whether or not the stack is unwound before this call to std​::​terminate() is implementation-defined ([except.terminate]).
Referring to any non-static member or base class of an object in the handler for a function-try-block of a constructor or destructor for that object results in undefined behavior.
The scope and lifetime of the parameters of a function or constructor extend into the handlers of a function-try-block.
Exceptions thrown in destructors of objects with static storage duration or in constructors of namespace-scope objects with static storage duration are not caught by a function-try-block on the main function.
Exceptions thrown in destructors of objects with thread storage duration or in constructors of namespace-scope objects with thread storage duration are not caught by a function-try-block on the initial function of the thread.
If a return statement appears in a handler of the function-try-block of a constructor, the program is ill-formed.
The currently handled exception is rethrown if control reaches the end of a handler of the function-try-block of a constructor or destructor.
Otherwise, flowing off the end of the compound-statement of a handler of a function-try-block is equivalent to flowing off the end of the compound-statement of that function (see [stmt.return]).
The variable declared by the exception-declaration, of type cv T or cv T&, is initialized from the exception object, of type E, as follows:
The lifetime of the variable ends when the handler exits, after the destruction of any automatic objects initialized within the handler.
When the handler declares an object, any changes to that object will not affect the exception object.
When the handler declares a reference to an object, any changes to the referenced object are changes to the exception object and will have effect should that object be rethrown.