The functions std::terminate() ([except.terminate]) and std::unexpected() ([except.unexpected]) are used by the exception handling mechanism for coping with errors related to the exception handling mechanism itself. The function std::current_exception() ([propagation]) and the class std::nested_exception ([except.nested]) can be used by a program to capture the currently handled exception.
In some situations exception handling must be abandoned for less subtle error handling techniques. [ Note: These situations are:
when the exception handling mechanism, after completing the initialization of the exception object but before activation of a handler for the exception ([except.throw]), calls a function that exits via an exception, or
when the exception handling mechanism cannot find a handler for a thrown exception ([except.handle]), or
when the search for a handler ([except.handle]) encounters the outermost block of a function with a noexcept-specification that does not allow the exception ([except.spec]), or
when the destruction of an object during stack unwinding ([except.ctor]) terminates by throwing an exception, or
when initialization of a non-local variable with static or thread storage duration ([basic.start.init]) exits via an exception, or
when destruction of an object with static or thread storage duration exits via an exception ([basic.start.term]), or
when execution of a function registered with std::atexit or std::at_quick_exit exits via an exception ([support.start.term]), or
when a throw-expression with no operand attempts to rethrow an exception and no exception is being handled ([except.throw]), or
when std::unexpected throws an exception which is not allowed by the previously violated dynamic-exception-specification, and std::bad_exception is not included in that dynamic-exception-specifica-tion ([except.unexpected]), or
when the implementation's default unexpected exception handler is called ([unexpected.handler]), or
when the function std::nested_exception::rethrow_nested is called for an object that has captured no exception ([except.nested]), or
when execution of the initial function of a thread exits via an exception ([thread.thread.constr]), or
when the destructor or the copy assignment operator is invoked on an object of type std::thread that refers to a joinable thread ([thread.thread.destr], [thread.thread.assign]).
— end note ]
In such cases, std::terminate() is called ([exception.terminate]). In the situation where no matching handler is found, it is implementation-defined whether or not the stack is unwound before std::terminate() is called. In the situation where the search for a handler ([except.handle]) encounters the outermost block of a function with a noexcept-specification that does not allow the exception ([except.spec]), it is implementation-defined whether the stack is unwound, unwound partially, or not unwound at all before std::terminate() is called. In all other situations, the stack shall not be unwound before std::terminate() is called. An implementation is not permitted to finish stack unwinding prematurely based on a determination that the unwind process will eventually cause a call to std::terminate().
If a function with a dynamic-exception-specification throws an exception that is not listed in the dynamic-exception-specification, the function std::unexpected() is called ([exception.unexpected]) immediately after completing the stack unwinding for the former function.
[ Note: By default, std::unexpected() calls std::terminate(), but a program can install its own handler function ([set.unexpected]). In either case, the constraints in the following paragraph apply. — end note ]
The std::unexpected() function shall not return, but it can throw (or re-throw) an exception. If it throws a new exception which is allowed by the exception specification which previously was violated, then the search for another handler will continue at the call of the function whose exception specification was violated. If it throws or rethrows an exception that the dynamic-exception-specification does not allow then the following happens: If the dynamic-exception-specification does not include the class std::bad_exception ([bad.exception]) then the function std::terminate() is called, otherwise the thrown exception is replaced by an implementation-defined object of the type std::bad_exception and the search for another handler will continue at the call of the function whose dynamic-exception-specification was violated.
Thus, a dynamic-exception-specification guarantees that only the listed exceptions will be thrown. If the dynamic-exception-specification includes the type std::bad_exception then any exception not on the list may be replaced by std::bad_exception within the function std::unexpected().
The function std::uncaught_exception() returns true after completing the initialization of the exception object ([except.throw]) until completing the activation of a handler for the exception ([except.handle], [uncaught]). This includes stack unwinding. If the exception is rethrown ([except.throw]), std::uncaught_exception() returns true from the point of rethrow until the rethrown exception is caught again.