<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.10">
<title>Zero-Overhead Deterministic Exceptions: Catching Values</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/* Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment @import statement to use as custom stylesheet */
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
abbr[title]{border-bottom:1px dotted}
b,strong{font-weight:bold}
dfn{font-style:italic}
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
abbr{text-transform:none}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
blockquote cite::before{content:"\2014 \0020"}
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}
:not(pre)>code.nobreak{word-wrap:normal}
:not(pre)>code.nowrap{white-space:nowrap}
pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre>code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:"[";padding:0 3px 0 2px}
b.button::after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:"\00a0\2013\00a0"}
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:100%;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details>summary:first-of-type{cursor:pointer;display:list-item;outline:none;margin-bottom:.75em}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
.paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6)}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border-style:solid;border-width:1px;border-color:#dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;-webkit-border-radius:4px;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock>.content>pre{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class="highlight"],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock>.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos{border-right:1px solid currentColor;opacity:.35;padding-right:.5em}
pre.pygments .lineno{border-right:1px solid currentColor;opacity:.35;display:inline-block;margin-right:.75em}
pre.pygments .lineno::before{content:"";margin-right:-.125em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;text-align:left;margin-right:0}
table.tableblock{max-width:100%;border-collapse:separate}
p.tableblock:last-child{margin-bottom:0}
td.tableblock>.content>:last-child{margin-bottom:-1.25em}
td.tableblock>.content>:last-child.sidebarblock{margin-bottom:0}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}
table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}
table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}
table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px}
table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0}
table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}
table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}
table.frame-all{border-width:1px}
table.frame-sides{border-width:0 1px}
table.frame-topbot,table.frame-ends{border-width:1px 0}
table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd),table.stripes-even tr:nth-of-type(even),table.stripes-hover tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
ul.checklist{margin-left:.625em}
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em}
ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline>li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
.gist .file-data>table td.line-data{width:99%}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon>.fa{cursor:default}
a span.icon>.fa{cursor:inherit}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]::after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body class="article">
<div id="header">
<h1>Zero-Overhead Deterministic Exceptions:<br/> Catching Values</h1>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<table class="tableblock frame-all grid-none stretch">
<colgroup>
<col style="width: 10%;">
<col style="width: 20%;">
<col style="width: 40%;">
<col style="width: 10%;">
<col style="width: 20%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Document&#xa0;Number:</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">P2232 R0</p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Date:</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">2021&#8209;1&#8209;17</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Reply-to:</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Emil Dotchevski<br>
<a href="mailto:emildotchevski@gmail.com">emildotchevski@gmail.com</a></p></td>
<td class="tableblock halign-left valign-top"></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Audience:</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">EWG</p></td>
</tr>
</tbody>
</table>
<div id="toc" class="toc">
<div id="toctitle" class="title">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#_abstract">Abstract</a></li>
<li><a href="#catching_values">Catching Values</a></li>
<li><a href="#catching_more_values">Catching More Values</a></li>
<li><a href="#dynamic_error_classification">Dynamic Error Classification</a></li>
<li><a href="#_a_few_important_details">A Few Important Details</a>
<ul class="sectlevel2">
<li><a href="#_propagation_of_unmatched_exception_objects">Propagation of Unmatched Exception Objects</a></li>
<li><a href="#_error_id">Error ID</a></li>
<li><a href="#_communication_of_the_failure_flag">Communication of the Failure Flag</a></li>
</ul>
</li>
<li><a href="#_efficiency_considerations">Efficiency Considerations</a></li>
<li><a href="#_implementation">Implementation</a></li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_abstract">Abstract</h2>
<div class="sectionbody">
<div class="paragraph">
<p>P0709<sup class="footnote">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup> states that "[d]ivergent error handling has fractured the C&#43;&#43; community into incompatible dialects, because of long-standing unresolved problems in C&#43;&#43; exception handling", and proposes a new, efficient mechanism, communicating the exception object in terms of an alternative function return value, which must be of the new type <code>std::error</code>.</p>
</div>
<div class="paragraph">
<p>This solution would enable teams that at present use error codes, to transition to using the <code>try</code>/<code>catch</code> syntax. While it is difficult to imagine the <code>-fno-exceptions</code> crowd to agree to throwing exceptions, it is true that the transition could in theory be made without any loss of functionality or efficiency.</p>
</div>
<div class="paragraph">
<p>To indicate different error conditions, teams that at present use exception handling would have to transition from throwing objects of different types, to throwing objects with different values of type <code>std::error</code>. However, exception objects can carry custom state as well. For example, an object of a user-defined exception type may hold a relevant file name, or a port number or any other data relevant to a failure. This can not be supported if exception objects are required to be of type <code>std::error</code>.</p>
</div>
<div class="paragraph">
<p>This means that P0709 effectively introduces a new error-handling dialect, further fracturing the C&#43;&#43; community.</p>
</div>
<div class="paragraph">
<p>This paper presents a different approach that allows exception objects of arbitrary types to be transported efficiently when the program uses catch-by-value. We also introduce a novel exception handling approach which can be used in place of exception type hierarchies to classify error conditions dynamically. In new programs, this would remove any need to use catch-by-reference (which of course will be supported for compatibility with legacy programs).</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="catching_values">Catching Values</h2>
<div class="sectionbody">
<div class="paragraph">
<p>It is possible to addresses exception handling overhead to a degree comparable to what P0709 proposes, while preserving the ability to throw objects of arbitrary types. To this end, we will make two assumptions that will appear unreasonable at first. This will later be extended to a complete system for dynamic matching of error conditions without a loss of functionality, compared to the current catch-by-reference approach.</p>
</div>
<div class="paragraph">
<p>For now:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>We will only use catch-by-value, e.g. <code>catch( E e )</code> rather than <code>catch( E&amp; e )</code>.</p>
</li>
<li>
<p>We change the semantics of <code>catch( E e )</code>: it now matches exception objects by their static, rather than dynamic type.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>With this in mind, the first thing to notice is that the exception object can use automatic storage duration, in the scope of the <code>try</code> / <code>catch</code> block. Consider:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">try
{
	f(); // Throws
}
catch( E1 e1 )
{
	// Use e1
}
catch( E2 e2 )
{
	// Use e2
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Due to our assumptions, the type of the exception objects is known statically, and we can reserve storage on the stack, suitable for storing <code>e1</code> and <code>e2</code>. We will need the ability to know if each of <code>e1</code> and <code>e2</code> is available (thrown), so instead of storing objects of type <code>E1</code> or <code>E2</code>, we will be storing objects of type <code>optional&lt;E1&gt;</code> and <code>optional&lt;E2&gt;</code> (or some equivalent).</p>
</div>
<div class="paragraph">
<p>Next, we need a mechanism to enable a <code>throw E1{}</code> or <code>throw E2{},</code> invoked from within <code>f</code>, to access that storage efficiently. This is possible by means of thread local storage. In the <code>try</code> block, before invoking <code>f</code>, we set a thread-local pointer <code>p<sub>E1</sub></code> of type <code>optional&lt;E1&gt;</code> to point the storage reserved for <code>e1</code>, and another thread-local pointer <code>p<sub>E2</sub></code> of type <code>optional&lt;E2&gt;</code> to point the storage reserved for <code>e2</code>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Current exception handling implementations use thread-local storage as well.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>To implement e.g. <code>throw E1{}</code>, we access the thread-local pointer <code>p<sub>E1</sub></code>:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>If <code>p<sub>E1</sub></code> is null, this means that no <code>catch( E1 e1 )</code> statement is currently available in the call stack; in this case we simply invoke the legacy throw machinery.</p>
</li>
<li>
<p>Otherwise, we initialize an object of type <code>E1</code> in the storage pointed by <code>p<sub>E1</sub></code>.</p>
</li>
</ul>
</div>
<div id="stack_unwinding" class="paragraph">
<p>Now we need to unwind the stack to the top-most exception-handling scope. This could be implemented just as proposed by P0709, except that what needs to be communicated as an alternative return value is no longer an exception object, but rather the <em>failure flag</em>,<sup class="footnote">[<a id="_footnoteref_2" class="footnote" href="#_footnotedef_2" title="View footnote.">2</a>]</sup> the single bit of information that indicates success or failure.</p>
</div>
<div class="paragraph">
<p>When we reach a <code>try</code>..<code>catch</code> scope, we examine each of the <code>optional&lt;&gt;</code> objects, <span class="underline">in order</span>; in this case we first examine the object storing <code>e1</code> and, if it is not empty, we execute that scope. Otherwise we examine the object storing <code>e2</code>, and so on. If we can&#8217;t find a suitable <code>catch</code>, we simply continue unwinding the stack (we know we will eventually find a suitable catch, or else we would have invoked the legacy throw mechanism).</p>
</div>
<div class="paragraph">
<p>In addition to the faster stack unwinding, efficiency is further improved because our <code>catch</code> statements effectively match error objects by their static, rather than dynamic type. However, we still want a <code>catch( E e )</code> to match objects of type <code>E</code> as well as of any other type that derives from <code>E</code>. Therefore, a <code>throw E{}</code> doesn&#8217;t only examine the thread-local pointer <code>p<sub>E</sub></code> but also the thread-local pointers <code>p<sub>B</sub></code> that correspond to each of the public bases of <code>E</code>. If any of them are non-null, we initialize each pointed <code>optional&lt;B&gt;</code> object via slicing using the copy constructor. For example, consider the following type hierarchy:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">struct file_error { };

struct file_open_error: file_error
{
	std::string file_name;
};

....
throw file_open_error { "file.txt" };</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>throw</code> statement above will first initialize a <code>file_open_error</code> object, and then examine the thread-local pointer to <code>optional&lt;file_open_error&gt;</code> <span class="underline">and</span> the thread-local pointer to <code>optional&lt;file_error&gt;</code>, and if either is non-null, initialize each corresponding object (by slicing, if needed). That way, the thrown exception could be handled by either <code>catch( file_error )</code> or <code>catch( file_open_error )</code>, even though at that time the type is matched statically. Effectively, we&#8217;re slicing at the point of the throw rather than at the point of the catch, but the behavior is otherwise equivalent.</p>
</div>
<div class="paragraph">
<p>This implementation should be similar to what P0709 proposes in terms of stack unwinding efficiency, but probably better because the alternative return value is not burdened with transporting a <code>std::error</code>. We just need to communicate the <em>failure flag</em>, while each exception object is initialized directly by the <code>throw</code> statement, regardless of how deep the call stack is at that point.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="catching_more_values">Catching More Values</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The presented system of exception handling can be easily extended to allow a single catch-by-value statement to work with more than one object. Consider:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">try
{
	f(); // throws
}
catch( E1 e1, E2 e2 )
{
	// Use e1 and e2
}
catch( E1 e1 )
{
	// Use e1
}
catch( E2 e2 )
{
	// Use e2
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>When the stack unwinding reaches the error handling scope above, the catch statements are examined in order. The first one will be matched if both the <code>optional&lt;E1&gt;</code> and <code>optional&lt;E2&gt;</code> are non-empty (see <a href="#catching_values">Catching Values</a>), while the others require only one of them to be non-empty.</p>
</div>
<div class="paragraph">
<p>The <code>throw</code> statement can be similarly extended to allow multiple objects of different types to be thrown simultaneously, using the following syntax:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">throw { E1{}, E2{} }; // Throws both objects</code></pre>
</div>
</div>
<div class="paragraph">
<p>Why is this useful? Because it can render exception type hierarchies&#8201;&#8212;&#8201;and all inefficiencies associated with them&#8201;&#8212;&#8201;unnecessary. Let&#8217;s consider an example.</p>
</div>
<div class="paragraph">
<p>Using the exception type hierarchy from the previous section, we could write the following function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">std::shared_ptr&lt;FILE&gt; open_file( char const * name )
{
	assert( name != 0 );

	if( FILE * f = std::fopen( name, "rb" ) )
		return std::shared_ptr&lt;FILE&gt;( f, &amp;std::fclose );

	throw file_open_error { name };
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>throw</code> statement above effectively classifies the failure as "file error" as well as "open error". To handle such failures, we could use the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">try
{
	auto f = open_file( n );
	....
}
catch( file_open_error &amp; e )
{
	// Handle a "file error" that is also an "open error".
	std::cerr &lt;&lt; "Failed to open file " &lt;&lt; e.file_name &lt;&lt; std::endl;
}
catch( file_error &amp; )
{
	// Handle any "file error".
	std::cerr &lt;&lt; "Failed to access file" &lt;&lt; std::endl;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Can the proposed catch-by-value semantics be used to similarly classify failures dynamically? It very much can, minus the cost of the memory allocation and the dynamic cast. We simply eliminate the exception type hierarchy, and replace it with individual types:</p>
</div>
<div id="file_open_example" class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">struct file_error { };
struct open_error { };
struct file_name { std::string value; };</code></pre>
</div>
</div>
<div class="paragraph">
<p>With this in place, to classify the error as what would have previously been <code>file_open_error</code>, <code>open_file</code> would now look like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">std::shared_ptr&lt;FILE&gt; open_file( char const * name )
{
	assert( name != 0 );

	if( FILE * f = std::fopen( name, "rb" ) )
		return std::shared_ptr&lt;FILE&gt;( f, &amp;std::fclose );

	throw { file_error{}, open_error{}, file_name { name } };
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>To handle such failures, we could use the following catch statements:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">try
{
	f(); // Calls open_file internally
}
catch( file_error, open_error, file_name fn )
{
	// Handle a "file error" that is also an "open error" and has an associated file name.
	std::cerr &lt;&lt; "Failed to open file " &lt;&lt; fn.value &lt;&lt; std::endl;
}
catch( file_error, file_name fn )
{
	// Handle any "file error" that has an associated file name.
	std::cerr &lt;&lt; "Failed to to access file " &lt;&lt; fn.value &lt;&lt; std::endl;
}
catch( file_error )
{
	// Handle any "file error".
	std::cerr &lt;&lt; "Failed to access file" &lt;&lt; std::endl;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that we always catch by value, but because we can <code>throw</code> and <code>catch</code> multiple values of different types, this novel error-classification system is more suitable than a type hierarchy in describing what went wrong: we can now associate a <code>file_name</code> with any failure, not only with "file open" errors.</p>
</div>
<div class="paragraph">
<p>In fact, we will now demonstrate that it is even more powerful, because it allows the program to refine the classification of failures dynamically, after the initial <code>throw</code>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="dynamic_error_classification">Dynamic Error Classification</h2>
<div class="sectionbody">
<div class="paragraph">
<p>A new standard function, <code>std::on_error</code>, could be used in any scope to either refine the classification of an active failure or to associate additional state with it. Let&#8217;s rewrite the <code>open_file</code> function from the previous section:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">std::shared_ptr&lt;FILE&gt; open_file( char const * name )
{
	assert( name != 0 );

	auto attach = std::on_error( file_error{}, file_name{ name } );

	if( FILE * f = std::fopen( name, "rb" ) )
		return std::shared_ptr&lt;FILE&gt;( f, &amp;std::fclose );

	throw open_error{};
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>std::on_error</code> function returns an object of unspecified type which caches, in a <code>std::tuple</code>, all of the values passed as arguments. In that object&#8217;s destructor, if there was no error (detected by means of e.g. <code>std::uncaught_exceptions</code>), all of the cached values are simply discarded. But if we&#8217;re unwinding the stack due to an exception, each of the cached values is "thrown" in addition to whatever other values were passed to the <code>throw</code> statement that put us on the exception path.</p>
</div>
<div class="paragraph">
<p>In this case, the effect is that any error that escapes the <code>open_file</code> function:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Is classified as a <code>file_error</code>, in addition to any previous classification; and</p>
</li>
<li>
<p>A <code>file_name</code> object will be available for catch-by-value at any exception-handling scope.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>The key point here is that <code>on_error</code> is dynamic, it is able to "attach" additional state to any failure. As another example, consider this <code>parse_file</code> function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">parsed_info parse_file( FILE &amp; f )
{
	auto attach = std::on_error( parse_error{} ); // Additionally classify as parse_error...

	std::string s = read_line( f ); // ...any exception thrown by read_line.
	....
	....
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_a_few_important_details">A Few Important Details</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_propagation_of_unmatched_exception_objects">Propagation of Unmatched Exception Objects</h3>
<div class="paragraph">
<p>It is important to consider the case when a <code>try</code> / <code>catch</code> block fails to match the current exception:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">try
{
	try
	{
		throw E1{};
	}
	catch( E1 e1, E2 e2 )
	{
	}
}
catch( E1 e1 )
{
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>As explained in <a href="#catching_more_values">Catching More Values</a>, the <code>throw</code> statement will initialize the <code>e1</code> object in the scope of the inner <code>try</code> / <code>catch</code> block. However, that <code>catch</code> block will not be matched, because it requires two exception objects, one of type <code>E1</code> and another of type <code>E2</code>.</p>
</div>
<div class="paragraph">
<p>Since no <code>catch</code> statement in the inner block matches the failure, the <code>e1</code> object initialized in that scope needs to be moved in the storage reserved for that type by an outer scope&#8201;&#8212;&#8201;or discarded if no such storage exists. This works as described in <a href="#catching_values">Catching Values</a>: for each available exception object in the inner scope, we check the thread-local pointer that corresponds to its type, and if it is non-null, we move the exception object into that storage.</p>
</div>
<div class="paragraph">
<p>A special case of this behavior is when rethrowing the original exception(s) in a <code>catch</code> statement. For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">struct Base { };
struct Derived: Base { };

try
{
	try
	{
		throw Derived{};
	}
	catch( Base b )
	{
		throw;
	}
}
catch( Derived d )
{
}
catch( Base b )
{
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The inner scope provides storage for a <code>Base</code> object, but not for a <code>Derived</code> object. Therefore, the <code>throw</code> statement will initialize both the <code>b</code> object in the inner scope <span class="underline">and</span> the <code>d</code> object in the outer scope. When we rethrow, the <code>b</code> object in the outer scope is initialized by moving from the <code>b</code> object in the inner scope.</p>
</div>
</div>
<div class="sect2">
<h3 id="_error_id">Error ID</h3>
<div class="paragraph">
<p>We need a way to uniquely identify a specific failure initiated by a <code>throw</code> statement. Consider:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">try
{
	try
	{
		throw { A{}, B{} };
	}
	catch( A a )
	{
		throw C{};
	}
}
catch( B b )
{
}
catch( C c )
{
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The first <code>throw</code> statement will initialize the <code>a</code> object in the scope of the inner <code>try</code> / <code>catch</code>, and the <code>b</code> object in the scope of the outer <code>try</code> / <code>catch</code>. Then, the second <code>throw</code> statement initializes the <code>c</code> object, also in the outer scope.</p>
</div>
<div class="paragraph">
<p>When handling exceptions in the outer scope, if we simply check whether an object of type <code>B</code> is available by examining the <code>optional&lt;B&gt;</code> object, we would execute the <code>catch( B b )</code> scope. This is incorrect, because there is no <code>B</code> object passed to the second <code>throw</code> statement.</p>
</div>
<div class="paragraph">
<p>The solution is to assign each failure a unique integer identifier, and store it together with each exception object initialized (in the scope of the corresponding <code>catch</code> statement) at the time of the <code>throw</code>. This enables the <code>catch( B b )</code> in the outer scope to determine that the <code>B</code> object it does contain is in fact <span class="underline">not</span> associated with the current failure (because the error identifier stored with <code>b</code> does not match the current error identifier). The unique identifier can be implemented in terms of a thread-local counter incremented by <code>throw</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_communication_of_the_failure_flag">Communication of the Failure Flag</h3>
<div class="paragraph">
<p>Like P0709, we need the ability to communicate an alternative "return value" in case of an error. Unlike P0709, this return value is simply the <em>failure flag</em>, a single bit of information.</p>
</div>
<div class="paragraph">
<p>In short, after calling a function, we need to be able to check if a failure has occurred. In the previous section, we explained that we also need to associate a unique integer Error ID value with each failure.</p>
</div>
<div class="paragraph">
<p>Current ABIs are already able to associate data with the current failure. This data uses the following <code>struct</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">struct __cxa_eh_globals
{
	__cxa_exception * caughtExceptions;
	unsigned int uncaughtExceptions;
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>This struct uses TLS. We can add the Error ID in this same <code>struct</code>, without breaking existing programs:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">struct __cxa_eh_globals
{
	__cxa_exception * caughtExceptions;
	unsigned int uncaughtExceptions;
	unsigned int errorID;
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>When we <code>throw</code> a new exception, we generate a unique value and store it in the <code>errorID</code>. When the exception is handled, we simply set the <code>errorID</code> to zero.</p>
</div>
<div class="paragraph">
<p>With this in place, strictly speaking we don&#8217;t even need to use the return value to communicate the <em>failure flag</em>; after we call a function, we can simply compare the <code>errorID</code> with zero to check for errors.</p>
</div>
<div class="paragraph">
<p>One possible way to communicate the <em>failure flag</em> in a new binary calling convention is to use one of the CPU flags, for example the Carry flag. However, the CPU instructions used to manipulate the frame pointer and the stack pointer usually modify the Carry flag, so it remains to be seen if this is a good idea or not.</p>
</div>
<div class="paragraph">
<p>This functionality&#8201;&#8212;&#8201;the ability to communicate the <em>failure flag</em> efficiently&#8201;&#8212;&#8201;is probably the most important problem that has to be solved to deliver maximum-performance on the "sad" path. Perhaps this functionality should be implemented in silicone in the future (e.g. a special failure flag bit).</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_efficiency_considerations">Efficiency Considerations</h2>
<div class="sectionbody">
<div class="paragraph">
<p>P0709 claims that "today&#8217;s dynamic exception types violate the zero-overhead principle", but this is only valid when the speed overhead on the "sad" path matters. Let&#8217;s not forget that the current ABIs in fact have zero overhead on the "happy" path. From this point of view, the approach of using alternative return values to communicate the exception objects is the one that violates the zero-overhead principle.</p>
</div>
<div class="paragraph">
<p>It is a fact that there are existing users of C&#43;&#43; exception handling which are happy with the legacy tradeoff of zero overhead on the "happy" at the cost of very inefficient "sad" path. Therefore, the existing implementations should be extended rather than replaced; and we need a way for users to select which convention to use.</p>
</div>
<div class="paragraph">
<p>Presumably, the way to deal with this is the proposed <code>throws</code> exception specification. But a wise man once taught us that exception specifications are impractical, regardless of how they are implemented:</p>
</div>
<div class="quoteblock">
<blockquote>
The short answer is that nobody knows how to fix exception specifications in any language, because the dynamic enforcement C&#43;&#43; chose has only different (not greater or fewer) problems than the static enforcement Java chose. &#8230;&#8203; When you go down the Java path, people love exception specifications until they find themselves all too often encouraged, or even forced, to add <code>throws Exception</code>, which immediately renders the exception specification entirely meaningless. (Example: Imagine writing a Java generic that manipulates an arbitrary type <code>T</code>).<sup class="footnote">[<a id="_footnoteref_3" class="footnote" href="#_footnotedef_3" title="View footnote.">3</a>]</sup>
</blockquote>
<div class="attribution">
&#8212; Herb Sutter
</div>
</div>
<div class="paragraph">
<p>Exception specifications are indeed incompatible with generic programming&#8201;&#8212;&#8201;and therefore with C&#43;&#43;. But even if we ignore this ancient wisdom, the introduction of a new exception specification will add yet another "incompatible dialect" and further fracture the C&#43;&#43; community.</p>
</div>
<div class="paragraph">
<p>Besides, it is not practical to specify statically whether or not a function which may fail should throw using the legacy (zero overhead on the "happy" path), or the new (minimal overhead on the "happy" and the "sad" path) mechanism. Consider that a library author is not in a position to make this determination: different users of the same library may have different preferences on this issue.</p>
</div>
<div class="paragraph">
<p>Indeed, the best case scenario is if the <span class="underline">caller</span> of a function which may fail can choose which exception-handling strategy should be used. The implementation strategy outlined in this paper in fact provides a natural way for the programmer to express this preference:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>If exceptions are handled using catch-by-reference, this requests the legacy (zero overhead on the "happy" path) mechanism.</p>
</li>
<li>
<p>If exceptions are handled using catch-by-value, the new (minimal overhead on the "happy" and the "sad" path) is requested.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>This places the decision firmly in the hands of the application programmer (where it belongs), while library authors don&#8217;t need to be concerned with it.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_implementation">Implementation</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The proposed catch-by-value semantics are implemented in C++11 library format by Boost LEAF<sup class="footnote">[<a id="_footnoteref_4" class="footnote" href="#_footnotedef_4" title="View footnote.">4</a>]</sup> introduced with Boost 1.75.</p>
</div>
<div class="paragraph">
<p>The <code>open_file</code> <a href="#file_open_example">example</a> from the <a href="#catching_more_values">Catching More Values</a> section can be written in terms of Boost LEAF using the following syntax:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">struct file_error { };
struct open_error { };
struct file_name { std::string value; };

std::shared_ptr&lt;FILE&gt; open_file( char const * name )
{
	assert( name != 0 );

	if( FILE * f = std::fopen( name, "rb" ) )
		return std::shared_ptr&lt;FILE&gt;( f, &amp;std::fclose );

	throw leaf::exception( file_error{}, open_error{}, file_name { name } );
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The communication of the error objects passed to <code>leaf::exception</code> is implemented using the TLS technique described in <a href="#catching_values">Catching Values</a>. Error handling uses the following syntax:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">leaf::try_catch(
	[]
	{
		auto f = open_file( n );
		....
	},
	[]( file_error, open_error, file_name fn )
	{
		// Handle a "file error" that is also an "open error" and has an associated file name.
		std::cerr &lt;&lt; "Failed to open file " &lt;&lt; fn &lt;&lt; std::endl;
	}
	[]( file_error, file_name fn )
	{
		// Handle any "file error" that has an associated file name.
		std::cerr &lt;&lt; "Failed to to access file " &lt;&lt; fn &lt;&lt; std::endl;
	}
	[]( file_error )
	{
		// Handle any "file error".
		std::cerr &lt;&lt; "Failed to access file" &lt;&lt; std::endl;
	} );</code></pre>
</div>
</div>
<div class="paragraph">
<p>The library supports the <a href="#dynamic_error_classification">Dynamic Error Classification</a> technique described in this proposal. The documentation <a href="https://boostorg.github.io/leaf/#tutorial-classification">elaborates on this idea</a>, demonstrating that it is even possible to handle errors uniformly, regardless of whether the <em>error flag</em> is communicated implicitly by throwing an exception, or explicitly in terms of some <code>result&lt;T&gt;</code> type.</p>
</div>
</div>
</div>
</div>
<div id="footnotes">
<hr>
<div class="footnote" id="_footnotedef_1">
<a href="#_footnoteref_1">1</a>. Sutter, "Zero-overhead deterministic exceptions: Throwing values", <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2018/p0709r0.pdf" class="bare">http://open-std.org/JTC1/SC22/WG21/docs/papers/2018/p0709r0.pdf</a>
</div>
<div class="footnote" id="_footnotedef_2">
<a href="#_footnoteref_2">2</a>. Dotchevski, "Error Handling Principles and Practices", <a href="https://github.com/boostorg/leaf/blob/master/doc/whitepaper.md" class="bare">https://github.com/boostorg/leaf/blob/master/doc/whitepaper.md</a>
</div>
<div class="footnote" id="_footnotedef_3">
<a href="#_footnoteref_3">3</a>. Sutter, "Sutter’s Mill", <a href="https://herbsutter.com/2007/01/24/questions-about-exception-specifications/" class="bare">https://herbsutter.com/2007/01/24/questions-about-exception-specifications/</a>
</div>
<div class="footnote" id="_footnotedef_4">
<a href="#_footnoteref_4">4</a>. Dotchevski, "Lightweight Error Augmentation Framework", <a href="https://boostorg.github.io/leaf/" class="bare">https://boostorg.github.io/leaf/</a>
</div>
</div>
<div id="footer">
<div id="footer-text">
</div>
</div>
</body>
</html>