1. Changelog
1.1. r0 -> r1
- 
     Added handle_or_rethrow() 
- 
     Added EWG poll from Rapperswil 
- 
     Fixed minor typos and clarified a few points 
2. Introduction
This proposal suggests adding methods to 
I have a proof of implementability without ABI breakage here. It
is an implementation of the proposed methods for both MSVC and libstdc++. On Linux, it is 385 times faster than using 
3. Polls
3.1. EWG Rapperswil 2018
EWG reviewed the paper for the general concept and how it interacts with exceptions, but not the specific API proposed here. This is reflected in the poll wording.
Does EWG want a non throwing mechanism to get to the exception held by 
| SF | F | N | A | SA | 
|---|---|---|---|---|
| 16 | 8 | 1 | 0 | 0 | 
4. Proposal
This is an informal description of the methods I propose adding to 
All pointers returned by this API are valid until this 
Calling any of these methods on a null 
4.1. High-level API
4.1.1. handle()
template < typename ... Handlers > /*see below*/ handle ( Handlers && ... handlers ) const ; bool handle () const { return false; } 
Handles the contained exception as if there were a sequence of 
The return type of 
using CommonReturnType = common_type_t < result_of_t < Handlers > ... > ; using ReturnType = conditional_t < is_void_v < CommonReturnType > , bool , optional < CommonReturnType >> ; 
If none of the handlers match the contained exception type, the call to false or an empty true or an 
This method does not "activate" the exception, so it will not be available to 
This API is inspired by folly::exception_wrapper. It can be implemented in the standard today, albeit without the performance benefits. Additionally, I think the valid lifetimes of the references would be shorter than is proposed here.
4.1.2. handle_or_rethrow()
template < typename ... Handlers > common_type_t < result_of_t < Handlers > ... > handle_or_terminate ( Handlers && ... handlers ) const ; 
Similar to handle(), but calls 
4.1.3. handle_or_terminate()
template < typename ... Handlers > common_type_t < result_of_t < Handlers > ... > handle_or_terminate ( Handlers && ... handlers ) const ; 
Similar to handle(), but calls terminate_with_active() if no handler matches the current exception. Unwraps the return type since if it returns, a handler must have matched.
4.1.4. try_catch()
template < typename T > requires is_reference_v < T > add_pointer_t < T > try_catch () const ; template < typename T > requires is_pointer_v < T > optional < T > try_catch () const ; 
If the contained exception is catchable by a 
The pointer case is a bit odd and throwing/catching pointer is fairly rare so it could use some
explanation for why it is both different and the same as the reference case. They have different
return types because returning 
if ( auto ex = ex_ptr . try_catch < CatchT > ()) { use ( * ex ); } 
Using today’s API this would be:
try { rethrow_exception ( ex_ptr ); } catch ( CatchT & ex ) { use ( ex ); } catch (...) { // ignore } 
4.1.5. terminate_with_active()
[[ noreturn ]] void terminate_with_active () const noexcept ; 
Equivalent to:
try { rethrow_exception ( * this ); } catch (...) { terminate (); } 
Invokes the terminate handler with the contained exception active to allow it to provide useful information for debugging.
Note: I believe this definition is exactly equivalent to just calling 
4.2. Low-level API
This is the low-level API that is intended for library authors building their own high-level API, rather than direct use by end users.
4.2.1. type()
type_info * type () const ; 
Returns the 
4.2.2. get_raw_ptr()
void * get_raw_ptr () const ; 
Returns the address of the exception held by this 
5. Use Cases
5.1. Lippincott Functions
Here is a lightly-modified example from our code base that shows a 100x speedup on Linux:
| Now | With this proposal | 
|---|---|
| 
 | 
 | 
|  |  | 
Windows shows only a 2x speedup (1488ns -> 744ns) due to the DecodePointer() issue mentioned
above (160ns), as well as 
5.2. Terminate Handlers
It is common practice to use terminate handlers to provide useful debugging information about the
failure. libstdc++ has a default handler that prints the type of the thrown exception using it’s
privileged access to the EH internals. Unfortunately, there is no way to do that in the general case
in a user-defined terminate handler. type() makes that information available from 
As a historical sidenote, that message from the terminate handler is what initially got me looking into the ABI for exception handling to figure out how that was done. If whoever wrote that code is reading this, thanks!
5.3. std :: expected 
   These types become more useful with the ability to interact with the exception directly without rethrowing.
5.4. Error Handling in Futures
Error handling in Future chains naturally involves passing error objects into callbacks as
arguments. There has been an active discussion around avoiding 
6. It sounds like you just want faster exception handling. Why isn’t this just a QoI issue?
It has been 30 years since C++98 was finalized. Compilers seem to actively avoid optimizing for
speed in codepaths that involve throwing, which is usually a good choice. But this means that even
in trivial cases, they aren’t able to work their usual magic. Here is an example function that
should be reduced to a constant value of 
int shouldBeTrivial () { try { throw 0 ; } catch ( int ex ) { return ex ; } return 1 ; }; 
Given how universal the poor handling of exceptions is, I don’t see much hope for improvement to the
extent proposed here in the realistic, non-trivial cases. Additionally, I think the ergonomics are
better if the exception object is made directly available than requiring the 
Additionally, as mentioned in §3.1 EWG Rapperswil 2018, EWG strongly favors adding this functionality to 
7. Related Future Work
These are related ideas that are not part of this proposal. If this proposal is well received, I’d like a straw poll of these to gauge the interest for future proposals.
7.1. Support dynamic dynamic_cast type_info 
   My initial implementation plan called for adding casting facilities to 
template < typename T > bool convertable_to () template < typename T > T * dynamic_dynamic_cast ( void * ptr ); 
7.2. dynamic_any_cast 
   Currently 
7.3. Less copies in std :: make_exception_ptr ( E  e ) 
   I noticed that the current definition takes the exception by value and is defined as copying it. Should it take the exception object by forwarding reference and forward it? If consensus is yes, I’d be happy to either submit a new paper or just add that to the proposed wording here.