<!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, user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="mobile-web-app-capable" content="yes">
    <title>
        Structured binding declaration as a _condition_ - HackMD
    </title>
    <link rel="icon" type="image/png" href="https://hackmd.io/favicon.png">
    <link rel="apple-touch-icon" href="https://hackmd.io/apple-touch-icon.png">

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha256-916EbMg70RQy9LHiGkXzG8hSg9EdNy97GazNG/aiY1w=" crossorigin="anonymous" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha256-eZrrJcwDc/3uDhsdt61sL2oOBY362qM3lon1gyExkL0=" crossorigin="anonymous" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css" integrity="sha256-3iu9jgsy9TpTwXKb7bNQzqWekRX7pPK+2OLj3R922fo=" crossorigin="anonymous" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/octicons/3.5.0/octicons.min.css" integrity="sha256-QiWfLIsCT02Sdwkogf6YMiQlj4NE84MKkzEMkZnMGdg=" crossorigin="anonymous" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.5.1/themes/prism.min.css" integrity="sha256-vtR0hSWRc3Tb26iuN2oZHt3KRUomwTufNIf5/4oeCyg=" crossorigin="anonymous" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@hackmd/emojify.js@2.1.0/dist/css/basic/emojify.min.css" integrity="sha256-UOrvMOsSDSrW6szVLe8ZDZezBxh5IoIfgTwdNDgTjiU=" crossorigin="anonymous" />
    <style>
        @import url(https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,500,500i|Source+Code+Pro:300,400,500|Source+Sans+Pro:300,300i,400,400i,600,600i|Source+Serif+Pro&subset=latin-ext);.hljs{background:#fff;color:#333;display:block;overflow-x:auto;padding:.5em}.hljs-comment,.hljs-meta{color:#969896}.hljs-emphasis,.hljs-quote,.hljs-string,.hljs-strong,.hljs-template-variable,.hljs-variable{color:#df5000}.hljs-keyword,.hljs-selector-tag,.hljs-type{color:#a71d5d}.hljs-attribute,.hljs-bullet,.hljs-literal,.hljs-number,.hljs-symbol{color:#0086b3}.hljs-built_in,.hljs-builtin-name{color:#005cc5}.hljs-name,.hljs-section{color:#63a35c}.hljs-tag{color:#333}.hljs-attr,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-selector-pseudo,.hljs-title{color:#795da3}.hljs-addition{background-color:#eaffea;color:#55a532}.hljs-deletion{background-color:#ffecec;color:#bd2c00}.hljs-link{text-decoration:underline}.markdown-body{word-wrap:break-word;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;font-size:16px;line-height:1.5}.markdown-body:after,.markdown-body:before{content:"";display:table}.markdown-body:after{clear:both}.markdown-body>:first-child{margin-top:0!important}.markdown-body>:last-child{margin-bottom:0!important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body .absent{color:#c00}.markdown-body .anchor{float:left;line-height:1;margin-left:-20px;padding-right:4px}.markdown-body .anchor:focus{outline:none}.markdown-body blockquote,.markdown-body dl,.markdown-body ol,.markdown-body p,.markdown-body pre,.markdown-body table,.markdown-body ul{margin-bottom:16px;margin-top:0}.markdown-body hr{background-color:#e7e7e7;border:0;height:.25em;margin:24px 0;padding:0}.markdown-body blockquote{border-left:.25em solid #ddd;color:#777;font-size:16px;padding:0 1em}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body kbd,.popover kbd{background-color:#fcfcfc;border:1px solid;border-color:#ccc #ccc #bbb;border-radius:3px;box-shadow:inset 0 -1px 0 #bbb;color:#555;display:inline-block;font-size:11px;line-height:10px;padding:3px 5px;vertical-align:middle}.markdown-body .loweralpha{list-style-type:lower-alpha}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{font-weight:600;line-height:1.25;margin-bottom:16px;margin-top:24px}.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link{color:#000;vertical-align:middle;visibility:hidden}.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor{text-decoration:none}.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link{visibility:visible}.markdown-body h1 code,.markdown-body h1 tt,.markdown-body h2 code,.markdown-body h2 tt,.markdown-body h3 code,.markdown-body h3 tt,.markdown-body h4 code,.markdown-body h4 tt,.markdown-body h5 code,.markdown-body h5 tt,.markdown-body h6 code,.markdown-body h6 tt{font-size:inherit}.markdown-body h1{font-size:2em}.markdown-body h1,.markdown-body h2{border-bottom:1px solid #eee;padding-bottom:.3em}.markdown-body h2{font-size:1.5em}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:.875em}.markdown-body h6{color:#777;font-size:.85em}.markdown-body ol,.markdown-body ul{padding-left:2em}.markdown-body ol.no-list,.markdown-body ul.no-list{list-style-type:none;padding:0}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-bottom:0;margin-top:0}.markdown-body li>p{margin-top:16px}.markdown-body li+li{padding-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{font-size:1em;font-style:italic;font-weight:700;margin-top:16px;padding:0}.markdown-body dl dd{margin-bottom:16px;padding:0 16px}.markdown-body table{display:block;overflow:auto;width:100%;word-break:normal;word-break:keep-all}.markdown-body table th{font-weight:700}.markdown-body table td,.markdown-body table th{border:1px solid #ddd}.markdown-body table tr{background-color:#fff;border-top:1px solid #ccc}.markdown-body table tr:nth-child(2n){background-color:#f8f8f8}.markdown-body img{background-color:#fff;box-sizing:initial;max-width:100%}.markdown-body img[align=right]{padding-left:20px}.markdown-body img[align=left]{padding-right:20px}.markdown-body .emoji{background-color:initial;max-width:none;vertical-align:text-top}.markdown-body span.frame{display:block;overflow:hidden}.markdown-body span.frame>span{border:1px solid #ddd;display:block;float:left;margin:13px 0 0;overflow:hidden;padding:7px;width:auto}.markdown-body span.frame span img{display:block;float:left}.markdown-body span.frame span span{clear:both;color:#333;display:block;padding:5px 0 0}.markdown-body span.align-center{clear:both;display:block;overflow:hidden}.markdown-body span.align-center>span{display:block;margin:13px auto 0;overflow:hidden;text-align:center}.markdown-body span.align-center span img{margin:0 auto;text-align:center}.markdown-body span.align-right{clear:both;display:block;overflow:hidden}.markdown-body span.align-right>span{display:block;margin:13px 0 0;overflow:hidden;text-align:right}.markdown-body span.align-right span img{margin:0;text-align:right}.markdown-body span.float-left{display:block;float:left;margin-right:13px;overflow:hidden}.markdown-body span.float-left span{margin:13px 0 0}.markdown-body span.float-right{display:block;float:right;margin-left:13px;overflow:hidden}.markdown-body span.float-right>span{display:block;margin:13px auto 0;overflow:hidden;text-align:right}.markdown-body code,.markdown-body tt{background-color:#0000000a;border-radius:3px;font-size:85%;margin:0;padding:.2em 0}.markdown-body code:after,.markdown-body code:before,.markdown-body tt:after,.markdown-body tt:before{content:"\00a0";letter-spacing:-.2em}.markdown-body code br,.markdown-body tt br{display:none}.markdown-body del code{text-decoration:inherit}.markdown-body pre{word-wrap:normal}.markdown-body pre>code{background:#0000;border:0;font-size:100%;margin:0;padding:0;white-space:pre;word-break:normal}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{border-radius:3px;font-size:85%;line-height:1.45;overflow:auto}.markdown-body:not(.next-editor) pre{padding:16px}.markdown-body pre code,.markdown-body pre tt{word-wrap:normal;background-color:initial;border:0;display:inline;line-height:inherit;margin:0;max-width:auto;overflow:visible;padding:0}.markdown-body pre code:after,.markdown-body pre code:before,.markdown-body pre tt:after,.markdown-body pre tt:before{content:normal}.markdown-body .csv-data td,.markdown-body .csv-data th{font-size:12px;line-height:1;overflow:hidden;padding:5px;text-align:left;white-space:nowrap}.markdown-body .csv-data .blob-line-num{background:#fff;border:0;padding:10px 8px 9px;text-align:right}.markdown-body .csv-data tr{border-top:0}.markdown-body .csv-data th{background:#f8f8f8;border-top:0;font-weight:700}.news .alert .markdown-body blockquote{border:0;padding:0 0 0 40px}.activity-tab .news .alert .commits,.activity-tab .news .markdown-body blockquote{padding-left:0}.task-list-item{list-style-type:none}.task-list-item label{font-weight:400}.task-list-item.enabled label{cursor:pointer}.task-list-item+.task-list-item{margin-top:3px}.task-list-item-checkbox{cursor:default!important;float:left;margin:.31em 0 .2em -1.3em!important;vertical-align:middle}.markdown-alert{border-left-style:solid;border-left-width:4px;color:inherit;margin-bottom:16px;padding:8px 16px}.markdown-alert .markdown-alert-title{align-items:center;display:flex;font-weight:500;line-height:1;white-space:break-spaces}.markdown-body .markdown-alert>*{margin-bottom:0;margin-top:16px}.markdown-body .markdown-alert .selection-popover,.markdown-body .markdown-alert>:first-child{margin-top:0}.markdown-alert.markdown-alert-note{border-left-color:#0969da}.markdown-alert.markdown-alert-note .markdown-alert-title{fill:currentColor;color:#0969da}.markdown-alert.markdown-alert-tip{border-left-color:#1a7f37}.markdown-alert.markdown-alert-tip .markdown-alert-title{fill:currentColor;color:#1a7f37}.markdown-alert.markdown-alert-important{border-left-color:#8250df}.markdown-alert.markdown-alert-important .markdown-alert-title{fill:currentColor;color:#8250df}.markdown-alert.markdown-alert-warning{border-left-color:#9a6700}.markdown-alert.markdown-alert-warning .markdown-alert-title{fill:currentColor;color:#9a6700}.markdown-alert.markdown-alert-caution{border-left-color:#d1242f}.markdown-alert.markdown-alert-caution .markdown-alert-title{fill:currentColor;color:#d1242f}:root[theme=dark] :not([theme])>*>.markdown-body,:root[theme] [theme=dark] .markdown-body{color:#f4f4f5}:root[theme=dark] :not([theme])>*>.markdown-body h1,:root[theme=dark] :not([theme])>*>.markdown-body h2,:root[theme] [theme=dark] .markdown-body h1,:root[theme] [theme=dark] .markdown-body h2{border-bottom-color:#52525b}:root[theme=dark] :not([theme])>*>.markdown-body h6,:root[theme] [theme=dark] .markdown-body h6{color:#a1a1aa}:root[theme=dark] :not([theme])>*>.markdown-body details,:root[theme] [theme=dark] .markdown-body details{background-color:#303036;color:#f4f4f5}:root[theme=dark] :not([theme])>*>.markdown-body details summary::marker:first-child,:root[theme] [theme=dark] .markdown-body details summary::marker:first-child{color:#f4f4f5}:root[theme=dark] :not([theme])>*>.markdown-body details:hover,:root[theme] [theme=dark] .markdown-body details:hover{background:#303036}:root[theme=dark] :not([theme])>*>.markdown-body details code,:root[theme=dark] :not([theme])>*>.markdown-body details[open]:hover,:root[theme] [theme=dark] .markdown-body details code,:root[theme] [theme=dark] .markdown-body details[open]:hover{background-color:#303036}:root[theme=dark] :not([theme])>*>.markdown-body hr,:root[theme] [theme=dark] .markdown-body hr{background-color:#52525b}:root[theme=dark] :not([theme])>*>.markdown-body blockquote,:root[theme] [theme=dark] .markdown-body blockquote{border-left-color:#71717a;color:#a1a1aa}:root[theme=dark] :not([theme])>*>.markdown-body blockquote a span,:root[theme] [theme=dark] .markdown-body blockquote a span{color:#9894f9}:root[theme=dark] :not([theme])>*>.markdown-body a.mention-anchor.user-card-popover,:root[theme] [theme=dark] .markdown-body a.mention-anchor.user-card-popover{background-color:#453aff26;color:#9894f9}:root[theme=dark] :not([theme])>*>.markdown-body ::selection,:root[theme] [theme=dark] .markdown-body ::selection{background-color:#453aff99}:root[theme=dark] :not([theme])>*>.markdown-body .alert.alert-info,:root[theme] [theme=dark] .markdown-body .alert.alert-info{background-color:#38bdf81a;border-left-color:#0ea5e9;color:#38bdf8}:root[theme=dark] :not([theme])>*>.markdown-body .alert.alert-warning,:root[theme] [theme=dark] .markdown-body .alert.alert-warning{background-color:#fbbf241a;border-left-color:#f59e0b;color:#f59e0b}:root[theme=dark] :not([theme])>*>.markdown-body .alert.alert-success,:root[theme] [theme=dark] .markdown-body .alert.alert-success{background-color:#6db19d26;border-left-color:#55b685;color:#6db19d}:root[theme=dark] :not([theme])>*>.markdown-body .alert.alert-danger,:root[theme] [theme=dark] .markdown-body .alert.alert-danger{background-color:#ef444433;border-left-color:#ef4444;color:#f87171}:root[theme=dark] :not([theme])>*>.markdown-body .mark,:root[theme=dark] :not([theme])>*>.markdown-body mark,:root[theme] [theme=dark] .markdown-body .mark,:root[theme] [theme=dark] .markdown-body mark{background-color:#fbbf241a;color:#f59e0b}:root[theme=dark] :not([theme])>*>.markdown-body .mark span,:root[theme=dark] :not([theme])>*>.markdown-body mark span,:root[theme] [theme=dark] .markdown-body .mark span,:root[theme] [theme=dark] .markdown-body mark span{color:#fbbf24}:root[theme=dark] :not([theme])>*>.markdown-body .highlight pre,:root[theme=dark] :not([theme])>*>.markdown-body pre,:root[theme] [theme=dark] .markdown-body .highlight pre,:root[theme] [theme=dark] .markdown-body pre{background-color:#303036;color:#a1a1aa}:root[theme=dark] :not([theme])>*>.markdown-body .style .token.string,:root[theme=dark] :not([theme])>*>.markdown-body .token.entity,:root[theme=dark] :not([theme])>*>.markdown-body .token.operator,:root[theme=dark] :not([theme])>*>.markdown-body .token.url,:root[theme=dark] :not([theme])>*>.markdown-body.language-css,:root[theme=dark] :not([theme])>*>.markdown-body.token.string,:root[theme] [theme=dark] .markdown-body .style .token.string,:root[theme] [theme=dark] .markdown-body .token.entity,:root[theme] [theme=dark] .markdown-body .token.operator,:root[theme] [theme=dark] .markdown-body .token.url,:root[theme] [theme=dark] .markdown-body.language-css,:root[theme] [theme=dark] .markdown-body.token.string{background:none}:root[theme=dark] :not([theme])>*>.markdown-body :not(pre)>code,:root[theme] [theme=dark] .markdown-body :not(pre)>code{background-color:#3f3f46}:root[theme=dark] :not([theme])>*>.markdown-body code .hljs-tag,:root[theme] [theme=dark] .markdown-body code .hljs-tag{color:#d4d4d8}:root[theme=dark] :not([theme])>*>.markdown-body code .hljs-keyword,:root[theme=dark] :not([theme])>*>.markdown-body code .hljs-selector-tag,:root[theme=dark] :not([theme])>*>.markdown-body code .hljs-type,:root[theme=dark] :not([theme])>*>.markdown-body code .token.boolean,:root[theme=dark] :not([theme])>*>.markdown-body code .token.constant,:root[theme=dark] :not([theme])>*>.markdown-body code .token.deleted,:root[theme=dark] :not([theme])>*>.markdown-body code .token.number,:root[theme=dark] :not([theme])>*>.markdown-body code .token.property,:root[theme=dark] :not([theme])>*>.markdown-body code .token.symbol,:root[theme=dark] :not([theme])>*>.markdown-body code .token.tag,:root[theme] [theme=dark] .markdown-body code .hljs-keyword,:root[theme] [theme=dark] .markdown-body code .hljs-selector-tag,:root[theme] [theme=dark] .markdown-body code .hljs-type,:root[theme] [theme=dark] .markdown-body code .token.boolean,:root[theme] [theme=dark] .markdown-body code .token.constant,:root[theme] [theme=dark] .markdown-body code .token.deleted,:root[theme] [theme=dark] .markdown-body code .token.number,:root[theme] [theme=dark] .markdown-body code .token.property,:root[theme] [theme=dark] .markdown-body code .token.symbol,:root[theme] [theme=dark] .markdown-body code .token.tag{color:#ff70b4}:root[theme=dark] :not([theme])>*>.markdown-body code .hljs-attribute,:root[theme=dark] :not([theme])>*>.markdown-body code .hljs-bullet,:root[theme=dark] :not([theme])>*>.markdown-body code .hljs-literal,:root[theme=dark] :not([theme])>*>.markdown-body code .hljs-number,:root[theme=dark] :not([theme])>*>.markdown-body code .hljs-symbol,:root[theme=dark] :not([theme])>*>.markdown-body code .token.atrule,:root[theme=dark] :not([theme])>*>.markdown-body code .token.attr-value,:root[theme=dark] :not([theme])>*>.markdown-body code .token.keyword,:root[theme] [theme=dark] .markdown-body code .hljs-attribute,:root[theme] [theme=dark] .markdown-body code .hljs-bullet,:root[theme] [theme=dark] .markdown-body code .hljs-literal,:root[theme] [theme=dark] .markdown-body code .hljs-number,:root[theme] [theme=dark] .markdown-body code .hljs-symbol,:root[theme] [theme=dark] .markdown-body code .token.atrule,:root[theme] [theme=dark] .markdown-body code .token.attr-value,:root[theme] [theme=dark] .markdown-body code .token.keyword{color:#9894f9}:root[theme=dark] :not([theme])>*>.markdown-body pre.part.plugin-rendered,:root[theme] [theme=dark] .markdown-body pre.part.plugin-rendered{background-color:#fff;color:#000}:root[theme=dark] :not([theme])>*>.markdown-body table,:root[theme] [theme=dark] .markdown-body table{border-color:#52525b}:root[theme=dark] :not([theme])>*>.markdown-body table thead tr,:root[theme] [theme=dark] .markdown-body table thead tr{background-color:#303036;border-bottom-color:#52525b}:root[theme=dark] :not([theme])>*>.markdown-body table td,:root[theme=dark] :not([theme])>*>.markdown-body table th,:root[theme] [theme=dark] .markdown-body table td,:root[theme] [theme=dark] .markdown-body table th{border-left-color:#52525b;border-top-color:#52525b}:root[theme=dark] :not([theme])>*>.markdown-body table tbody tr,:root[theme=dark] :not([theme])>*>.markdown-body table tr:nth-child(2n),:root[theme] [theme=dark] .markdown-body table tbody tr,:root[theme] [theme=dark] .markdown-body table tr:nth-child(2n){background-color:#27272a}:root[theme=light] :not([theme])>*>.markdown-body,:root[theme] [theme=light] .markdown-body{color:#3f3f46}:root[theme=light] :not([theme])>*>.markdown-body h1,:root[theme=light] :not([theme])>*>.markdown-body h2,:root[theme] [theme=light] .markdown-body h1,:root[theme] [theme=light] .markdown-body h2{border-bottom-color:#e4e4e7}:root[theme=light] :not([theme])>*>.markdown-body h6,:root[theme] [theme=light] .markdown-body h6{color:#71717a}:root[theme=light] :not([theme])>*>.markdown-body iframe,:root[theme=light] :not([theme])>*>.markdown-body img:not(.emoji),:root[theme] [theme=light] .markdown-body iframe,:root[theme] [theme=light] .markdown-body img:not(.emoji){border:1px solid #e4e4e7}:root[theme=light] :not([theme])>*>.markdown-body details,:root[theme] [theme=light] .markdown-body details{background-color:#f4f4f5}:root[theme=light] :not([theme])>*>.markdown-body details:hover,:root[theme] [theme=light] .markdown-body details:hover{background:#e4e4e7}:root[theme=light] :not([theme])>*>.markdown-body details[open]:hover,:root[theme] [theme=light] .markdown-body details[open]:hover{background-color:#f4f4f5}:root[theme=light] :not([theme])>*>.markdown-body details code,:root[theme] [theme=light] .markdown-body details code{background-color:#e4e4e7}:root[theme=light] :not([theme])>*>.markdown-body hr,:root[theme] [theme=light] .markdown-body hr{background-color:#d4d4d8}:root[theme=light] :not([theme])>*>.markdown-body blockquote,:root[theme] [theme=light] .markdown-body blockquote{border-left-color:#e4e4e7;color:#71717a}:root[theme=light] :not([theme])>*>.markdown-body blockquote a span,:root[theme] [theme=light] .markdown-body blockquote a span{color:#453aff}:root[theme=light] :not([theme])>*>.markdown-body a.mention-anchor.user-card-popover,:root[theme] [theme=light] .markdown-body a.mention-anchor.user-card-popover{background-color:#ecebfe;color:#453aff}:root[theme=light] :not([theme])>*>.markdown-body ::selection,:root[theme] [theme=light] .markdown-body ::selection{background-color:#cccafc}:root[theme=light] :not([theme])>*>.markdown-body .alert.alert-info,:root[theme] [theme=light] .markdown-body .alert.alert-info{background-color:#e0f2fe;border-left-color:#0284c7;color:#0284c7}:root[theme=light] :not([theme])>*>.markdown-body .alert.alert-warning,:root[theme] [theme=light] .markdown-body .alert.alert-warning{background-color:#fef3c799;border-left-color:#f59e0b;color:#f59e0b}:root[theme=light] :not([theme])>*>.markdown-body .alert.alert-success,:root[theme] [theme=light] .markdown-body .alert.alert-success{background-color:#d9f9e5;border-left-color:#43946c;color:#43946c}:root[theme=light] :not([theme])>*>.markdown-body .alert.alert-danger,:root[theme] [theme=light] .markdown-body .alert.alert-danger{background-color:#fee2e299;border-left-color:#ef4444;color:#ef4444}:root[theme=light] :not([theme])>*>.markdown-body .mark,:root[theme=light] :not([theme])>*>.markdown-body mark,:root[theme] [theme=light] .markdown-body .mark,:root[theme] [theme=light] .markdown-body mark{background-color:#fef3c799;color:#f59e0b}:root[theme=light] :not([theme])>*>.markdown-body .mark span,:root[theme=light] :not([theme])>*>.markdown-body mark span,:root[theme] [theme=light] .markdown-body .mark span,:root[theme] [theme=light] .markdown-body mark span{color:#f59e0b}:root[theme=light] :not([theme])>*>.markdown-body .highlight pre,:root[theme=light] :not([theme])>*>.markdown-body pre,:root[theme] [theme=light] .markdown-body .highlight pre,:root[theme] [theme=light] .markdown-body pre{background-color:#f4f4f5}:root[theme=light] :not([theme])>*>.markdown-body pre.part.plugin-rendered,:root[theme] [theme=light] .markdown-body pre.part.plugin-rendered{background-color:inherit;color:inherit}:root[theme=light] :not([theme])>*>.markdown-body :not(pre)>code,:root[theme] [theme=light] .markdown-body :not(pre)>code{background-color:#0000000a}:root[theme=light] :not([theme])>*>.markdown-body table,:root[theme] [theme=light] .markdown-body table{border-color:#e4e4e7}:root[theme=light] :not([theme])>*>.markdown-body table thead tr,:root[theme] [theme=light] .markdown-body table thead tr{background-color:#f4f4f5;border-bottom-color:#d4d4d8}:root[theme=light] :not([theme])>*>.markdown-body table td,:root[theme=light] :not([theme])>*>.markdown-body table th,:root[theme] [theme=light] .markdown-body table td,:root[theme] [theme=light] .markdown-body table th{border-left-color:#e4e4e7;border-top-color:#e4e4e7}:root[theme=light] :not([theme])>*>.markdown-body table tbody tr,:root[theme=light] :not([theme])>*>.markdown-body table tr:nth-child(2n),:root[theme] [theme=light] .markdown-body table tbody tr,:root[theme] [theme=light] .markdown-body table tr:nth-child(2n){background-color:#fdfdfd}.markdown-body{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;max-width:758px;overflow:visible!important;padding-bottom:40px;padding-top:40px;position:relative}.markdown-body>*{max-width:100%;overflow:auto}.markdown-body .alert a,.markdown-body a{color:var(--hmd-tw-link-text-default)}.markdown-body .alert a:focus,.markdown-body .alert a:hover,.markdown-body a:focus,.markdown-body a:hover{color:var(--hmd-tw-link-text-hover)}.markdown-body .alert a:hover,.markdown-body a:hover{text-decoration-thickness:2px;text-underline-offset:4px}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5{font-family:Readex Pro,-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;font-weight:700}.markdown-body h1,.markdown-body h2{border-bottom:1px solid}.markdown-body iframe,.markdown-body img{background-color:initial;border-radius:6px;margin:.5rem 0}.markdown-body iframe{max-width:100%;width:728px}.markdown-body details{border-radius:4px;margin-bottom:.5rem;padding:.5rem 1rem}.markdown-body details:hover{transition:all .1s}.markdown-body details summary+p{margin-top:.5rem}.markdown-body details p:last-child{margin-bottom:0}.markdown-body hr{height:2px}.markdown-body img.emoji{border:none;height:20px;vertical-align:middle;width:20px}.markdown-body li small{color:#a1a1aa}.markdown-body blockquote{border-left:3px solid}.markdown-body blockquote .small,.markdown-body blockquote small,.markdown-body li small{display:initial;font-size:85%}.markdown-body a.mention-anchor:before{content:"";margin-right:0}.markdown-body a.mention-anchor.user-card-popover{border-radius:4px;padding:1px 4px}.markdown-body .alert{border:none;border-radius:4px;margin-top:10px}.markdown-body .alert h2,.markdown-body .alert h3,.markdown-body .alert h4,.markdown-body .alert h5,.markdown-body .alert h6{margin-top:0}.markdown-body .alert h2{border:none}.markdown-body .alert.alert-danger,.markdown-body .alert.alert-info,.markdown-body .alert.alert-success,.markdown-body .alert.alert-warning{border-left:3px solid}.markdown-body .highlight pre,.markdown-body .mark,.markdown-body mark,.markdown-body pre{border-radius:4px}.markdown-body pre.part.abc,.markdown-body pre.part.flow-chart,.markdown-body pre.part.fretboard,.markdown-body pre.part.graphviz,.markdown-body pre.part.mermaid,.markdown-body pre.part.sequence-diagram,.markdown-body pre.part.vega-embed{border-radius:4px;max-width:100%;overflow:auto}.markdown-body table{border:1px solid;border-radius:4px;width:fit-content}.markdown-body table thead tr{border-bottom:1px solid;border-top:none}.markdown-body table tbody tr,.markdown-body table thead tr th{border-top:none}.markdown-body table tbody tr td:first-child,.markdown-body table thead,.markdown-body table thead th:first-child{border-left:none}.markdown-body table td,.markdown-body table th{border:1px solid;border-bottom:none;border-right:none;padding:6px 13px}.markdown-body.next-editor{overflow-x:hidden!important}.markdown-body pre{border:inherit}.markdown-body code{color:inherit}html[lang^=ja] .markdown-body code code,html[lang^=ja] .markdown-body code kbd,html[lang^=ja] .markdown-body code pre{font-family:Source Code Pro,Consolas,monaco,Meiryo,ＭＳ ゴシック,MS Gothic,monospace}html[lang=zh-tw] .markdown-body code code,html[lang=zh-tw] .markdown-body code kbd,html[lang=zh-tw] .markdown-body code pre{font-family:Source Code Pro,Consolas,monaco,Microsoft JhengHei,微軟正黑,monospace}html[lang=zh-cn] .markdown-body code code,html[lang=zh-cn] .markdown-body code kbd,html[lang=zh-cn] .markdown-body code pre{font-family:Source Code Pro,Consolas,monaco,Microsoft YaHei,微软雅黑,monospace}html .markdown-body code[lang^=ja] code,html .markdown-body code[lang^=ja] kbd,html .markdown-body code[lang^=ja] pre{font-family:Source Code Pro,Consolas,monaco,Meiryo,ＭＳ ゴシック,MS Gothic,monospace}html .markdown-body code[lang=zh-tw] code,html .markdown-body code[lang=zh-tw] kbd,html .markdown-body code[lang=zh-tw] pre{font-family:Source Code Pro,Consolas,monaco,Microsoft JhengHei,微軟正黑,monospace}html .markdown-body code[lang=zh-cn] code,html .markdown-body code[lang=zh-cn] kbd,html .markdown-body code[lang=zh-cn] pre{font-family:Source Code Pro,Consolas,monaco,Microsoft YaHei,微软雅黑,monospace}.markdown-body pre code .wrapper{display:-moz-inline-flex;display:-ms-inline-flex;display:-o-inline-flex;display:inline-flex}.markdown-body pre code .gutter{float:left;overflow:hidden;-webkit-user-select:none;user-select:none}.markdown-body pre code .gutter.linenumber{border-right:2px solid #766df8;box-sizing:initial;color:#a1a1aa;cursor:default;display:inline-block;min-width:20px;padding:0 8px 0 0;position:relative;text-align:right;z-index:4}.markdown-body pre code .gutter.linenumber>span:before{content:attr(data-linenumber)}.markdown-body pre code .code{float:left;margin:0 0 0 16px}.markdown-body .gist .line-numbers{border-bottom:none;border-left:none;border-top:none}.markdown-body .gist .line-data{border:none}.markdown-body .gist table{border-collapse:inherit!important;border-spacing:0}.markdown-body code[data-gist-id]{background:none;padding:0}.markdown-body code[data-gist-id]:after,.markdown-body code[data-gist-id]:before{content:""}.markdown-body code[data-gist-id] .blob-num{border:unset}.markdown-body code[data-gist-id] table{margin-bottom:unset;overflow:unset}.markdown-body code[data-gist-id] table tr{background:unset}.markdown-body[dir=rtl] pre{direction:ltr}.markdown-body[dir=rtl] code{direction:ltr;unicode-bidi:embed}.markdown-body .alert{display:flex;flex-direction:column;gap:16px}.markdown-body .alert>*{margin:0}.markdown-body pre.abc,.markdown-body pre.flow-chart,.markdown-body pre.graphviz,.markdown-body pre.mermaid,.markdown-body pre.sequence-diagram,.markdown-body pre.vega{background-color:inherit;border-radius:0;overflow:visible;text-align:center;white-space:inherit}.markdown-body pre.abc>code,.markdown-body pre.flow-chart>code,.markdown-body pre.graphviz>code,.markdown-body pre.mermaid>code,.markdown-body pre.sequence-diagram>code,.markdown-body pre.vega>code{text-align:left}.markdown-body pre.abc>svg,.markdown-body pre.flow-chart>svg,.markdown-body pre.graphviz>svg,.markdown-body pre.mermaid>svg,.markdown-body pre.sequence-diagram>svg,.markdown-body pre.vega>svg{height:100%;max-width:100%}.markdown-body pre>code.wrap{word-wrap:break-word;white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap}.markdown-body pre.pseudocode{white-space-collapse:collapse}.markdown-body summary{display:list-item}.markdown-body summary:focus{outline:none}.markdown-body details summary{cursor:pointer}.markdown-body details:not([open])>:not(summary){display:none}.markdown-body figure{margin:1em 40px}.markdown-body .mark,.markdown-body mark{background-color:#fff1a7}:root[theme] .markdown-body ::marker,:root[theme] .markdown-body code{color:var(--hmd-tw-text-default)}:root[theme] .markdown-body h1 .octicon-link,:root[theme] .markdown-body h2 .octicon-link,:root[theme] .markdown-body h3 .octicon-link,:root[theme] .markdown-body h4 .octicon-link,:root[theme] .markdown-body h5 .octicon-link,:root[theme] .markdown-body h6 .octicon-link{color:var(--hmd-tw-text-subtle)}:root[theme] .markdown-body .anchor{left:0;margin-left:0;position:absolute}:root[theme] .markdown-body .gist table{border-color:inherit}:root[theme] .markdown-body .gist table thead tr{background-color:inherit;border-bottom-color:inherit}:root[theme] .markdown-body .gist table td,:root[theme] .markdown-body .gist table th{border-left-color:inherit;border-top-color:inherit}:root[theme] .markdown-body .gist table tbody tr,:root[theme] .markdown-body .gist table tr:nth-child(2n){background-color:inherit}@media (max-width:767px){.markdown-body h1{font-size:1.6em}.markdown-body h2{font-size:1.4em}.markdown-body h3{font-size:1.125em}}.vimeo,.youtube{background-color:#000;background-position:50%;background-repeat:no-repeat;background-size:contain;cursor:pointer;display:table;overflow:hidden;text-align:center}.vimeo,.youtube{position:relative;width:100%}.youtube{padding-bottom:56.25%}.vimeo img{object-fit:contain;width:100%;z-index:0}.youtube img{object-fit:cover;z-index:0}.vimeo iframe,.youtube iframe,.youtube img{height:100%;left:0;position:absolute;top:0;width:100%}.vimeo iframe,.youtube iframe{vertical-align:middle;z-index:1}.vimeo .icon,.youtube .icon{color:#fff;height:auto;left:50%;opacity:.3;position:absolute;top:50%;transform:translate(-50%,-50%);transition:opacity .2s;width:auto;z-index:0}.vimeo:hover .icon,.youtube:hover .icon{opacity:.6;transition:opacity .2s}.slideshare .inner,.speakerdeck .inner{position:relative;width:100%}.slideshare .inner iframe,.speakerdeck .inner iframe{bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%}.figma{display:table;padding-bottom:56.25%;position:relative;width:100%}.figma iframe{border:1px solid #eee;bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%}.markmap-container{height:300px}.markmap-container>svg{height:100%;width:100%}.MJX_Assistive_MathML{display:none}#MathJax_Message{z-index:1000!important}.ui-infobar{color:var(--hmd-tw-text-default);font-size:14px;margin:25px auto -25px;max-width:760px;position:relative;z-index:2}.ui-infobar .ui-user-icon.small{height:18px;margin:2px;vertical-align:top;width:18px}.toc .invisable-node{list-style-type:none}.ui-toc{bottom:20px;position:fixed;z-index:998}.ui-toc.both-mode{margin-left:2px}.ui-toc.both-mode .ui-toc-label{border-bottom-left-radius:0;border-top-left-radius:0;height:40px;padding:10px 4px}:root[theme=light] :not([theme])>*>.ui-toc .ui-toc-label,:root[theme] [theme=light] .ui-toc-label{background-color:#fdfdfd;border-color:#d4d4d8;color:#a1a1aa}:root[theme=light] :not([theme])>*>.ui-toc .ui-toc-label:active,:root[theme=light] :not([theme])>*>.ui-toc .ui-toc-label:hover,:root[theme] [theme=light] .ui-toc-label:active,:root[theme] [theme=light] .ui-toc-label:hover{background-color:#f4f4f5;border-color:#d4d4d8;color:#a1a1aa}:root[theme=dark] :not([theme])>*>.ui-toc .ui-toc-label,:root[theme=dark] :not([theme])>*>.ui-toc .ui-toc-label:active,:root[theme=dark] :not([theme])>*>.ui-toc .ui-toc-label:hover,:root[theme] [theme=dark] .ui-toc-label,:root[theme] [theme=dark] .ui-toc-label:active,:root[theme] [theme=dark] .ui-toc-label:hover{background-color:#303036;border-color:#52525b;color:#a1a1aa}:root[theme=dark] :not([theme])>*>.ui-toc.both-mode .ui-toc-label,:root[theme] [theme=dark] .ui-toc.both-mode .ui-toc-label{background-color:#303036;border-color:#3f3f46;color:#d4d4d8}:root[theme=dark] :not([theme])>*>.ui-toc.both-mode .ui-toc-label:hover,:root[theme] [theme=dark] .ui-toc.both-mode .ui-toc-label:hover{background-color:#52525b}.ui-toc-label{border:1px solid;transition:opacity .2s}.ui-toc .open .ui-toc-label,.ui-toc-label:hover{opacity:1;transition:opacity .2s}.ui-toc-dropdown{letter-spacing:normal;margin-bottom:20px;margin-top:20px;max-height:70vh;max-width:45vw;overflow:auto;padding-left:10px;padding-right:10px;text-align:inherit;width:25vw}.ui-toc-dropdown.dropdown-menu{box-shadow:0 3px 15px 0 #00000026}.ui-toc-dropdown>.toc{max-height:calc(70vh - 100px);overflow:auto}.ui-toc-dropdown[dir=rtl] .nav{letter-spacing:.0029em;padding-right:0}.ui-toc-dropdown a{overflow:hidden;text-overflow:ellipsis;white-space:pre}.ui-toc-dropdown .nav>li>a{color:var(--hmd-tw-text-subtle);display:block;font-size:12px;font-weight:500;line-height:16px;padding:4px 20px}.ui-toc-dropdown .nav>li:first-child:last-child>ul,.ui-toc-dropdown .toc.expand ul{display:block}.ui-toc-dropdown .nav>li>a:focus,.ui-toc-dropdown .nav>li>a:hover{background-color:initial;border-color:var(--hmd-tw-border-bold);border-style:solid;border-width:0 0 0 1px;color:#000;color:var(--hmd-tw-text-emphasize);padding-left:19px;text-decoration:none}.ui-toc-dropdown[dir=rtl] .nav>li>a:focus,.ui-toc-dropdown[dir=rtl] .nav>li>a:hover{border-left:none;border-right:1px solid #000;padding-right:19px}.ui-toc-dropdown .nav>.active:focus>a,.ui-toc-dropdown .nav>.active:hover>a,.ui-toc-dropdown .nav>.active>a{background-color:initial;border-color:var(--hmd-tw-border-bold);border-style:solid;border-width:0 0 0 2px;color:var(--hmd-tw-text-emphasize);font-weight:600;padding-left:18px}.ui-toc-dropdown[dir=rtl] .nav>.active:focus>a,.ui-toc-dropdown[dir=rtl] .nav>.active:hover>a,.ui-toc-dropdown[dir=rtl] .nav>.active>a{border-width:0 2px 0 medium;border-left:0;border-color:var(--hmd-tw-border-bold);border-style:solid;padding-right:18px}.ui-toc-dropdown .nav .nav{display:none;padding-bottom:10px}.ui-toc-dropdown .nav>.active>ul{display:block}.ui-toc-dropdown .nav .nav>li>a{font-size:12px;font-weight:400;padding-bottom:1px;padding-left:30px;padding-top:1px}.ui-toc-dropdown[dir=rtl] .nav .nav>li>a{padding-right:30px}.ui-toc-dropdown .nav .nav>li>ul>li>a{font-size:12px;font-weight:400;padding-bottom:1px;padding-left:40px;padding-top:1px}.ui-toc-dropdown[dir=rtl] .nav .nav>li>ul>li>a{padding-right:40px}.ui-toc-dropdown .nav .nav>li>a:focus,.ui-toc-dropdown .nav .nav>li>a:hover{padding-left:29px}.ui-toc-dropdown[dir=rtl] .nav .nav>li>a:focus,.ui-toc-dropdown[dir=rtl] .nav .nav>li>a:hover{padding-right:29px}.ui-toc-dropdown .nav .nav>li>ul>li>a:focus,.ui-toc-dropdown .nav .nav>li>ul>li>a:hover{padding-left:39px}.ui-toc-dropdown[dir=rtl] .nav .nav>li>ul>li>a:focus,.ui-toc-dropdown[dir=rtl] .nav .nav>li>ul>li>a:hover{padding-right:39px}.ui-toc-dropdown .nav .nav>.active:focus>a,.ui-toc-dropdown .nav .nav>.active:hover>a,.ui-toc-dropdown .nav .nav>.active>a{font-weight:500;padding-left:28px}.ui-toc-dropdown[dir=rtl] .nav .nav>.active:focus>a,.ui-toc-dropdown[dir=rtl] .nav .nav>.active:hover>a,.ui-toc-dropdown[dir=rtl] .nav .nav>.active>a{padding-right:28px}.ui-toc-dropdown .nav .nav>.active>.nav>.active:focus>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active:hover>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active>a{font-weight:500;padding-left:38px}.ui-toc-dropdown[dir=rtl] .nav .nav>.active>.nav>.active:focus>a,.ui-toc-dropdown[dir=rtl] .nav .nav>.active>.nav>.active:hover>a,.ui-toc-dropdown[dir=rtl] .nav .nav>.active>.nav>.active>a{padding-right:38px}.ui-affix-toc{max-height:70vh;max-width:15vw;overflow:auto;position:fixed;top:0}.back-to-top,.expand-toggle,.go-to-bottom{color:var(--hmd-tw-text-subtle);display:block;font-size:12px;font-weight:500;line-height:16px;margin-left:10px;margin-top:10px;padding:2px 10px}.back-to-top:focus,.back-to-top:hover,.expand-toggle:focus,.expand-toggle:hover,.go-to-bottom:focus,.go-to-bottom:hover{color:var(--hmd-tw-text-primary);text-decoration:none}.back-to-top,.go-to-bottom{margin-top:0}.ui-user-icon{background-position:50%;background-repeat:no-repeat;background-size:cover;border-radius:50%;display:block;height:20px;margin-bottom:2px;margin-right:5px;margin-top:2px;width:20px}.ui-user-icon.small{display:inline-block;height:18px;margin:0 0 .2em;vertical-align:middle;width:18px}.ui-infobar>small>span{line-height:22px}.ui-infobar>small .dropdown{display:inline-block}.ui-infobar>small .dropdown a:focus,.ui-infobar>small .dropdown a:hover{text-decoration:none}.ui-more-info{cursor:pointer;vertical-align:middle}.ui-connectedGithub{line-height:23px;white-space:nowrap}.ui-connectedGithub a.file-path{text-decoration:none}.ui-connectedGithub a.file-path:active,.ui-connectedGithub a.file-path:hover{text-decoration:underline}.unselectable{-webkit-user-select:none;-o-user-select:none;user-select:none}.selectable{-webkit-user-select:text;-o-user-select:text;user-select:text}.inline-spoiler-section{cursor:pointer}.inline-spoiler-section .spoiler-text{background-color:#333;border-radius:2px}.inline-spoiler-section .spoiler-text>*{opacity:0}.inline-spoiler-section .spoiler-img{filter:blur(10px)}.inline-spoiler-section.raw{background-color:#333;border-radius:2px}.inline-spoiler-section.raw>*{opacity:0}.inline-spoiler-section.unveil{cursor:auto}.inline-spoiler-section.unveil .spoiler-text{background-color:#3333331a}.inline-spoiler-section.unveil .spoiler-text>*{opacity:1}.inline-spoiler-section.unveil .spoiler-img{filter:none}@media print{blockquote,div,img,pre,table{page-break-inside:avoid!important}a[href]:after{font-size:12px!important}}.markdown-body.slides{color:#222;position:relative;z-index:1}.markdown-body.slides:before{background-color:currentColor;bottom:0;box-shadow:0 0 0 50vw;content:"";display:block;left:0;position:absolute;right:0;top:0;z-index:-1}.markdown-body.slides section[data-markdown]{background-color:#fff;margin-bottom:1.5em;position:relative;text-align:center}.markdown-body.slides section[data-markdown] code{text-align:left}.markdown-body.slides section[data-markdown]:before{content:"";display:block;padding-bottom:56.23%}.markdown-body.slides section[data-markdown]>div:first-child{left:1em;max-height:100%;overflow:hidden;position:absolute;right:1em;top:50%;transform:translateY(-50%)}.markdown-body.slides section[data-markdown]>ul{display:inline-block}.markdown-body.slides>section>section+section:after{border:3px solid #777;content:"";height:1.5em;position:absolute;right:1em;top:-1.5em}.site-ui-font{font-family:Source Sans Pro,Helvetica,Arial,sans-serif}html[lang^=ja] .site-ui-font{font-family:Source Sans Pro,Helvetica,Arial,Hiragino Kaku Gothic Pro,ヒラギノ角ゴ Pro W3,Osaka,Meiryo,メイリオ,MS Gothic,ＭＳ ゴシック,sans-serif}html[lang=zh-tw] .site-ui-font{font-family:Source Sans Pro,Helvetica,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif}html[lang=zh-cn] .site-ui-font{font-family:Source Sans Pro,Helvetica,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif}body{font-smoothing:subpixel-antialiased!important;-webkit-font-smoothing:subpixel-antialiased!important;-moz-osx-font-smoothing:auto!important;-webkit-overflow-scrolling:touch;font-family:Source Sans Pro,Helvetica,Arial,sans-serif;letter-spacing:.025em}html[lang^=ja] body{font-family:Source Sans Pro,Helvetica,Arial,Hiragino Kaku Gothic Pro,ヒラギノ角ゴ Pro W3,Osaka,Meiryo,メイリオ,MS Gothic,ＭＳ ゴシック,sans-serif}html[lang=zh-tw] body{font-family:Source Sans Pro,Helvetica,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif}html[lang=zh-cn] body{font-family:Source Sans Pro,Helvetica,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}abbr[data-original-title],abbr[title]{cursor:help}body.modal-open{overflow-y:auto;padding-right:0!important}svg{text-shadow:none}
    </style>
    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    	<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js" integrity="sha256-3Jy/GbSLrg0o9y5Z5n1uw0qxZECH7C6OQpVBgNFYa0g=" crossorigin="anonymous"></script>
    	<script src="https://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js" integrity="sha256-g6iAfvZp+nDQ2TdTR/VVKJf3bGro4ub5fvWSWVRi2NE=" crossorigin="anonymous"></script>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.min.js" integrity="sha256-8E4Is26QH0bD52WoQpcB+R/tcWQtpzlCojrybUd7Mxo=" crossorigin="anonymous"></script>
    <![endif]-->
</head>

<body>
    <div id="doc" class="markdown-body container-fluid comment-enabled comment-inner" data-hard-breaks="true"><style data-custom-style="">
ins { background-color: #CCFFCC }
s { background-color: #FFCACA }
blockquote { color: inherit !important }
table.no-alt tr:nth-child(2n) { background-color: inherit }
.godbolt {
    background-size: contain;
    background-repeat: no-repeat;
    background-position-y: center;
    background-image: url("https://godbolt.org/favicon.ico?v=1")
}
</style><table><tbody>
<tr><th>Doc. no.:</th>    <td>P0963R3</td></tr>
<tr><th>Date:</th>        <td>2024-06-28</td></tr>
<tr><th>Audience:</th>    <td>CWG</td></tr>
<tr><th>Reply-to:</th>    <td>Zhihao Yuan &lt;zy@miator.net&gt;</td></tr>
</tbody></table><h1 id="Structured-binding-declaration-as-a-condition" data-id="Structured-binding-declaration-as-a-condition" data-original-title="" title=""><a class="anchor hidden-xs" href="#Structured-binding-declaration-as-a-condition" title="Structured-binding-declaration-as-a-condition"><span class="octicon octicon-link ph ph-link-simple-horizontal"></span></a><span>Structured binding declaration as a </span><em><span>condition</span></em></h1><p data-original-title="" title=""><span class="toc"><ul>
<li><a href="#Structured-binding-declaration-as-a-condition" title="Structured binding declaration as a condition">Structured binding declaration as a condition</a><ul>
<li><a href="#Changes" title="Changes">Changes</a></li>
<li><a href="#Introduction" title="Introduction">Introduction</a></li>
<li><a href="#Motivation" title="Motivation">Motivation</a></li>
<li><a href="#Design-Decisions" title="Design Decisions">Design Decisions</a><ul>
<li><a href="#Unconditionally-decompose" title="Unconditionally decompose">Unconditionally decompose</a></li>
<li><a href="#Testing-is-sequenced-before-decomposing" title="Testing is sequenced before decomposing">Testing is sequenced before decomposing</a></li>
<li><a href="#No-underlying-array-object" title="No underlying array object">No underlying array object</a></li>
</ul>
</li>
<li><a href="#Wording" title="Wording">Wording</a></li>
<li><a href="#Implementation" title="Implementation">Implementation</a></li>
<li><a href="#Acknowledgements" title="Acknowledgements">Acknowledgements</a></li>
<li><a href="#References" title="References">References</a></li>
</ul>
</li>
</ul>
</span></p><h2 id="Changes" data-id="Changes"><a class="anchor hidden-xs" href="#Changes" title="Changes"><span class="octicon octicon-link ph ph-link-simple-horizontal"></span></a><span>Changes</span></h2><dl>
<dt><span>Since R2</span></dt>
<dd>
<ul>
<li><span>Wording fixes</span></li>
<li><span>Align corner cases with </span><em><span>structured-binding-decl</span></em><span> outside a </span><em><span>condition</span></em></li>
</ul>
</dd>
<dt><span>Since R1</span></dt>
<dd>
<ul>
<li><span>Sequence the test prior to decomposition; add discussion and adjust wording</span></li>
<li><span>Refine wording</span></li>
</ul>
</dd>
<dt><span>Since R0</span></dt>
<dd>
<ul>
<li><span>Rework the motivation</span></li>
<li><span>Clarify that decomposition is sequenced before testing</span></li>
</ul>
</dd>
</dl><h2 id="Introduction" data-id="Introduction"><a class="anchor hidden-xs" href="#Introduction" title="Introduction"><span class="octicon octicon-link ph ph-link-simple-horizontal"></span></a><span>Introduction</span></h2><p><span>C++17 structured binding declaration is designed as a variant of variable declarations. As of today, it may appear as a statement on its own or as the declaration part of a range-based </span><code>for</code><span> loop. Meanwhile, the </span><em><span>condition</span></em><span> of an </span><code>if</code><span> statement may also be a variable declaration and can benefit from being a structured binding declaration. This paper proposes to allow structured binding declarations with initializers appearing in place of the </span><em><span>conditions</span></em><span> in </span><code>if</code><span>, </span><code>while</code><span>, </span><code>for</code><span>, and </span><code>switch</code><span> statements.</span></p><table class="no-alt"><tbody>
<tr><th>
<p><em><span>simple-declaration</span></em></p>
</th><td>
<pre><code class="cpp hljs"><span class="token keyword">auto</span> <span class="token punctuation">[</span>b<span class="token punctuation">,</span> p<span class="token punctuation">]</span> <span class="token operator">=</span> ranges<span class="token double-colon punctuation">::</span><span class="token function">mismatch</span><span class="token punctuation">(</span>current<span class="token punctuation">,</span> end<span class="token punctuation">,</span> pbegin<span class="token punctuation">,</span> pend<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
</td></tr><tr><th>
<p><em><span>for-range-declaration</span></em></p>
</th><td>
<pre><code class="cpp hljs"><span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">auto</span> <span class="token punctuation">[</span>index<span class="token punctuation">,</span> value<span class="token punctuation">]</span> <span class="token operator">:</span> views<span class="token double-colon punctuation">::</span><span class="token function">enumerate</span><span class="token punctuation">(</span>vec<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"{}: {}"</span><span class="token punctuation">,</span> index<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
</code></pre>
</td></tr>
<tr><th>
<p><mark><em><span>condition</span></em></mark></p>
</th>
<td>
<pre><code class="cpp hljs"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">auto</span> <span class="token punctuation">[</span>to<span class="token punctuation">,</span> ec<span class="token punctuation">]</span> <span class="token operator">=</span> std<span class="token double-colon punctuation">::</span><span class="token function">to_chars</span><span class="token punctuation">(</span>p<span class="token punctuation">,</span> last<span class="token punctuation">,</span> <span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">auto</span> s <span class="token operator">=</span> std<span class="token double-colon punctuation">::</span><span class="token function">string</span><span class="token punctuation">(</span>p<span class="token punctuation">,</span> to<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
</code></pre>
</td></tr>
</tbody></table><h2 id="Motivation" data-id="Motivation"><a class="anchor hidden-xs" href="#Motivation" title="Motivation"><span class="octicon octicon-link ph ph-link-simple-horizontal"></span></a><span>Motivation</span></h2><p><span>By design, structured binding is only about decomposition. The information of an object to be decomposed equals the information of all the components combined. However, after deploying structured bindings for a few years, it has been found that, in some scenarios, certain side information contributes to complexity if left out.</span></p><dl>
<dt><span>Scenario 1</span></dt>
<dd>
<p><span>The author sees a pattern that can be demonstrated using the following code snippet:</span></p>
<pre><code class="cpp hljs">​​​​<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">auto</span> <span class="token punctuation">[</span>first<span class="token punctuation">,</span> last<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">parse</span><span class="token punctuation">(</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> first <span class="token operator">!=</span> last<span class="token punctuation">)</span> <span class="token punctuation">{</span>
​​​​    <span class="token comment">// interpret [first, last) into a value</span>
​​​​<span class="token punctuation">}</span>
</code></pre>
<p><span>The idea is to split parsing and the action. Returning a pair of pointers makes it flexible to form different, windowed inputs.</span></p>
<p><span>However, if you wear glasses of "I did not write the code," the condition </span><code>first != last</code><span> doesn't say much. It's repetitive, opens the opportunity of being combined with other conditions, and can cause mistakes if comparing different pairs.</span></p>
<p><span>It would be nice if, when defining the intermediate type that carries the pairs to be decomposed, the condition can be baked into the type,</span></p>
<pre><code class="cpp hljs">​​​​<span class="token keyword">struct</span> <span class="token class-name">parse_window</span>
​​​​<span class="token punctuation">{</span>
​​​​    <span class="token keyword">char</span> <span class="token keyword">const</span> <span class="token operator">*</span>first<span class="token punctuation">,</span> <span class="token operator">*</span>last<span class="token punctuation">;</span>
​​​​    <span class="token keyword">explicit</span> <span class="token keyword">operator</span> <span class="token keyword">bool</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">const</span> <span class="token keyword">noexcept</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> first <span class="token operator">!=</span> last<span class="token punctuation">;</span> <span class="token punctuation">}</span>
​​​​<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre>
<p><span>and eliminates the need to maintain a convention:</span></p>
<pre><code class="cpp hljs">​​​​<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">auto</span> <span class="token punctuation">[</span>first<span class="token punctuation">,</span> last<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">parse</span><span class="token punctuation">(</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
​​​​    <span class="token comment">// interpret [first, last) into a value</span>
​​​​<span class="token punctuation">}</span>
</code></pre>
<p><span>In this example, </span><strong><span>information about the condition is spread across the components</span></strong><span>, and "how to form the condition" is not self-explanatory. If structured binding can channel this knowledge contextually, the library authors and the users may settle with a more solid pattern.</span></p>
</dd>
<dt><span>Scenario 2</span></dt>
<dd>
<p><span>Here is an updated example of using </span><code>&lt;charconv&gt;</code><span> in C++26 after adopting P2497</span><sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup><span>:</span></p>
<pre><code class="cpp hljs">​​​​<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">auto</span> result <span class="token operator">=</span> std<span class="token double-colon punctuation">::</span><span class="token function">to_chars</span><span class="token punctuation">(</span>p<span class="token punctuation">,</span> last<span class="token punctuation">,</span> <span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
​​​​    <span class="token keyword">auto</span> <span class="token punctuation">[</span>ptr<span class="token punctuation">,</span> _<span class="token punctuation">]</span> <span class="token operator">=</span> result<span class="token punctuation">;</span>
​​​​    <span class="token comment">// okay to proceed</span>
​​​​<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
​​​​    <span class="token keyword">auto</span> <span class="token punctuation">[</span>ptr<span class="token punctuation">,</span> ec<span class="token punctuation">]</span> <span class="token operator">=</span> result<span class="token punctuation">;</span>
​​​​    <span class="token comment">// handle errors</span>
​​​​<span class="token punctuation">}</span>
</code></pre>
<p><span>We succeeded at restricting the variable to the minimal lexical scope where needed, but the code still struggled to implement what the users wanted to express.</span></p>
<p><span>The example can be a lot simpler if, when testing the </span><code>result</code><span> variable which has no role other than being decomposed later, the test is done as a part of decomposition without naming the intermediate </span><code>result</code><span>:</span></p>
<pre><code class="cpp hljs">​​​​<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">auto</span> <span class="token punctuation">[</span>ptr<span class="token punctuation">,</span> ec<span class="token punctuation">]</span> <span class="token operator">=</span> std<span class="token double-colon punctuation">::</span><span class="token function">to_chars</span><span class="token punctuation">(</span>p<span class="token punctuation">,</span> last<span class="token punctuation">,</span> <span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
​​​​    <span class="token comment">// okay to proceed</span>
​​​​<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
​​​​    <span class="token comment">// handle errors</span>
​​​​<span class="token punctuation">}</span>
</code></pre>
</dd>
</dl><p><span>So, even when </span><strong><span>a single component contains information about the condition</span></strong><span> (</span><code>result.ec</code><span> in this example), people continue to be motivated to consolidate the knowledge of "how to test" into the complete object. But how to test when the complete object happens to be the underlying object of structured binding? The proposed feature answers the need.</span></p><dl>
<dt><span>Scenario 3</span></dt>
<dd>
<p><span>In an iterative solver, the code runs a primary solving step, like the following, in a loop. The call returns the state of the problem, decomposed into matrices and vectors:</span></p>
<pre><code class="cpp hljs">​​​​<span class="token keyword">auto</span> <span class="token punctuation">[</span>Ap<span class="token punctuation">,</span> bp<span class="token punctuation">,</span> x<span class="token punctuation">,</span> y<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">solve</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p><span>The solver must determine, right after the step, whether it gets an optimal solution. Mathematically, this can be done by evaluating one or more components like this:</span></p>
<pre><code class="cpp hljs">​​​​<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">is_optimal</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment">// scan the x vector</span>
​​​​    <span class="token keyword">break</span><span class="token punctuation">;</span>
</code></pre>
<p><span>But doing so may involve a linear algorithm or worse. Meanwhile, the </span><code>solve()</code><span> procedure may know whether the answer is optimal and save this information in the result as if it is cached. If the language allows retrieving this information, the following code can be terser and more efficient at the same time:</span></p>
<pre><code class="cpp hljs">​​​​<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">auto</span> <span class="token punctuation">[</span>Ap<span class="token punctuation">,</span> bp<span class="token punctuation">,</span> x<span class="token punctuation">,</span> y<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">solve</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment">// no need to scan x again</span>
​​​​    <span class="token keyword">break</span><span class="token punctuation">;</span>
</code></pre>
<p><span>In this example, </span><strong><span>the information about the condition needs to be reconstructed from the components at a cost</span></strong><span>. The complete object is an excellent place to cache this information but is not in a position to bring this redundant information into a separate component.</span></p>
</dd>
<dt><span>Scenario 4</span></dt>
<dd>
<p><span>Consider this example that uses the CTRE</span><sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup><span> library:</span></p>
<pre><code class="cpp hljs">​​​​<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">auto</span> <span class="token punctuation">[</span>all<span class="token punctuation">,</span> city<span class="token punctuation">,</span> state<span class="token punctuation">,</span> zip<span class="token punctuation">]</span> <span class="token operator">=</span> ctre<span class="token double-colon punctuation">::</span>match<span class="token operator">&lt;</span><span class="token string">"(\\w+), (\\w+) (\\d+)"</span><span class="token operator">&gt;</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">;</span> all<span class="token punctuation">)</span> <span class="token punctuation">{</span>
​​​​    <span class="token keyword">return</span> location<span class="token punctuation">{</span>city<span class="token punctuation">,</span> state<span class="token punctuation">,</span> zip<span class="token punctuation">}</span><span class="token punctuation">;</span>
​​​​<span class="token punctuation">}</span>
</code></pre>
<p><span>It is surprising to see a regular expression that introduces three capture groups generating a result of four components unless the readers are already familiar with other Perl-like regex engines, which offer a "default" capture group to represent the entire match. Such a match group can be referred to as </span><code>\0</code><span> when performing regex-based substitution, which isn't what we're doing here (nor supported by CTRE as the time of writing, either).</span></p>
<p><span>It might be more WYSIWYG if, in the next generation of the API, three capture groups mean three components to extract:</span></p>
<pre><code class="cpp hljs">​​​​<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">auto</span> <span class="token punctuation">[</span>city<span class="token punctuation">,</span> state<span class="token punctuation">,</span> zip<span class="token punctuation">]</span> <span class="token operator">=</span> ctre2<span class="token double-colon punctuation">::</span>match<span class="token operator">&lt;</span><span class="token string">"(\\w+), (\\w+) (\\d+)"</span><span class="token operator">&gt;</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
​​​​    <span class="token keyword">return</span> location<span class="token punctuation">{</span>city<span class="token punctuation">,</span> state<span class="token punctuation">,</span> zip<span class="token punctuation">}</span><span class="token punctuation">;</span>
​​​​<span class="token punctuation">}</span>
</code></pre>
<p><span>In this example, if solely looking at the outcome, the information to be tested in the condition is not in the components. But still, when </span><strong><span>all components but one have similar roles</span></strong><span>, folding such a particular component into an implicit test well-suited for its role makes the code easier to understand.</span></p>
</dd>
</dl><h2 id="Design-Decisions" data-id="Design-Decisions"><a class="anchor hidden-xs" href="#Design-Decisions" title="Design-Decisions"><span class="octicon octicon-link ph ph-link-simple-horizontal"></span></a><span>Design Decisions</span></h2><h3 id="Unconditionally-decompose" data-id="Unconditionally-decompose"><a class="anchor hidden-xs" href="#Unconditionally-decompose" title="Unconditionally-decompose"><span class="octicon octicon-link ph ph-link-simple-horizontal"></span></a><span>Unconditionally decompose</span></h3><p><span>It is tempting to add extra semantics given the proposed syntax, such as conditionally evaluating the binding protocol after testing the underlying object:</span></p><pre><code class="cpp hljs"><span class="token keyword">auto</span> <span class="token function">consume_int</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-&gt;</span> std<span class="token double-colon punctuation">::</span>optional<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span><span class="token punctuation">;</span>

<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">auto</span> <span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">consume_int</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>  <span class="token comment">// let e be the underlying object</span>
    <span class="token comment">// i = *e</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
    <span class="token comment">// *e is not evaluated</span>
<span class="token punctuation">}</span>
</code></pre><p><span>This idea turns </span><code>std::optional&lt;T&gt;</code><span> into a new kind of type that is "conditionally destructurable." Imagine this: if </span><code>[x]</code><span> can destructure </span><code>optional&lt;T&gt;</code><span>, then </span><code>[x, y]</code><span> won't destructure </span><code>optional&lt;tuple&lt;T, U&gt;&gt;</code><span>. The pattern matching proposal</span><sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup><span> has better answers to these: </span><code>let ?x</code><span> and </span><code>let ?[x, y]</code><span>. With pattern matching, one can rewrite the hypothetical code snippet above as:</span></p><pre><code class="csharp hljs"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">consume_int</span><span class="token punctuation">(</span><span class="token punctuation">)</span> match <span class="token keyword">let</span> <span class="token punctuation">?</span>i<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// use(i)</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
    <span class="token comment">// has no value</span>
<span class="token punctuation">}</span>
</code></pre><p><span>The idea of conditionally decomposing confuses sum types with product types; therefore, it is not included in this paper.</span></p><h3 id="Testing-is-sequenced-before-decomposing" data-id="Testing-is-sequenced-before-decomposing"><a class="anchor hidden-xs" href="#Testing-is-sequenced-before-decomposing" title="Testing-is-sequenced-before-decomposing"><span class="octicon octicon-link ph ph-link-simple-horizontal"></span></a><span>Testing is sequenced before decomposing</span></h3><p><span>If decomposition is taken place unconditionally, when that happens becomes a question. Does it happen before evaluating the </span><em><span>condition</span></em><span> or after? The author's mental model for structured binding in </span><em><span>condition</span></em><span> is the following:</span></p><pre>if (auto [a, b, c] = fn()) {
    statements;
}
</pre><p><span>is equivalent to</span></p><pre>if (auto [a, b, c] = fn(); <i>e</i>) {
    statements;
}
</pre><p><span>where </span><em><code>e</code></em><span> is the underlying object of the structured binding declaration. If we go further and infer the semantics of the proposed control structure from the desugared form, the </span><em><span>condition</span></em><span> would be evaluated after decomposing the underlying object.</span></p><p><span>However, "design by desugaring" can generate suboptimal outcomes. A great example is the lifetime issue of range-based </span><code>for</code><span> loops. The latest refinement deviates their semantics from the desugared equivalent, but this change is what everybody wants.</span><sup class="footnote-ref"><a href="#fn4" id="fnref4">[4]</a></sup></p><p><span>In the context of this paper, as Tim Song pointed out, users expect to test and decompose a subrange into iterators without naming the range,</span></p><pre><code class="cpp hljs"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">auto</span> <span class="token punctuation">[</span>b<span class="token punctuation">,</span> e<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">compute_some_subrange</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token comment">// ...</span>
<span class="token punctuation">}</span>
</code></pre><p><span>but this will not work under the aforementioned "desugaring" model if the bindings refer to move-only iterators, as in effect, we will be testing moved-from objects.</span></p><pre><code class="cpp hljs"><span class="token keyword">auto</span> r <span class="token operator">=</span> <span class="token function">compute_some_subrange</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">auto</span> <span class="token punctuation">[</span>b<span class="token punctuation">,</span> e<span class="token punctuation">]</span> <span class="token operator">=</span> std<span class="token double-colon punctuation">::</span><span class="token function">move</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span><span class="token punctuation">;</span> r<span class="token punctuation">)</span>  <span class="token comment">// approximately</span>
<span class="token punctuation">{</span>
    <span class="token comment">// ...</span>
<span class="token punctuation">}</span>
</code></pre><p><span>The following code (</span><ruby><a href="https://gcc.godbolt.org/z/3h74oq8zW" target="_blank" rel="noopener"><span class="godbolt"><span> </span></span><span>3h74oq8zW</span></a><rt><span>Compiler Explorer</span></rt></ruby><span>) incurs undefined behavior in the compiler that implements the R1 semantics of this paper:</span></p><pre><code class="cpp hljs">std<span class="token double-colon punctuation">::</span>generator<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">co_yield</span> <span class="token number">1</span><span class="token punctuation">;</span>
    <span class="token keyword">co_yield</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">int</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">auto</span> g <span class="token operator">=</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">auto</span> <span class="token punctuation">[</span>b<span class="token punctuation">,</span> e<span class="token punctuation">]</span> <span class="token operator">=</span> std<span class="token double-colon punctuation">::</span>ranges<span class="token double-colon punctuation">::</span>subrange<span class="token punctuation">{</span>g<span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p><span>We could imagine that what the users are looking for is a hypothetical </span><code>if</code><span> statement in which the first declaration in parenthesis is interpreted as the </span><em><span>condition</span></em><span> and the second as the </span><em><span>init-statement</span></em><span>, where the structured binding declaration in the </span><em><span>init-statement</span></em><span> is destructuring a preexisting underlying object:</span></p><pre>if (auto <i>e</i> = fn(); auto [a, b, c] = <i>e</i>) {
    statements;
}
</pre><p><span>This makes sense because contextually converting the underlying object of structured binding to </span><code>bool</code><span> is a side channel to pass information. We could mandate extracting this information first when doing so is motivated, as well as the order of extracting the other pieces of information</span><sup class="footnote-ref"><a href="#fn5" id="fnref5">[5]</a></sup><span>. This paper proposes evaluating the </span><em><span>condition</span></em><span> before initializing the bindings.</span></p><h3 id="No-underlying-array-object" data-id="No-underlying-array-object"><a class="anchor hidden-xs" href="#No-underlying-array-object" title="No-underlying-array-object"><span class="octicon octicon-link ph ph-link-simple-horizontal"></span></a><span>No underlying array object</span></h3><p><span>It is worthwhile to figure out what array decomposition does in a </span><em><span>condition</span></em><span>. The </span><em><span>condition</span></em><span> forbids declaring arrays, so this paper neither allows decomposing arrays. However, the </span><em><span>condition</span></em><span> accepts array references, which always evaluate to </span><code>true</code><span>, which is also unchanged in this paper. The following works with the proposed change:</span></p><pre><code class="c++ hljs"><span class="hljs-keyword">if</span> (<span class="hljs-keyword">auto</span>&amp; [a, b, c] = <span class="hljs-string">"ht"</span>)
    <span class="hljs-comment">// true branch is always taken</span>
</code></pre><p><span>Decomposing arrays in </span><em><span>conditions</span></em><span> is very unmotivated.</span></p><h2 id="Wording" data-id="Wording"><a class="anchor hidden-xs" href="#Wording" title="Wording"><span class="octicon octicon-link ph ph-link-simple-horizontal"></span></a><span>Wording</span></h2><p><span>The wording is relative to N4981.</span></p><p><span>Extend the grammar in </span><a href="https://eel.is/c++draft/stmt.stmt#stmt.pre-1" target="_blank" rel="noopener"><span>[stmt.pre]/1</span></a><span> as follows:</span></p><blockquote>
<p><em><span>condition:</span></em><span> </span><br>
<span>&nbsp;&nbsp;&nbsp;</span><em><span>expression</span></em><span> </span><br>
<span>&nbsp;&nbsp;&nbsp;</span><em><span>attribute-specifier-seq</span><sub><span>opt</span></sub><span> decl-specifier-seq declarator brace-or-equal-initializer</span></em><span> </span><br>
<span>&nbsp;&nbsp;&nbsp;</span><ins><em><span>structured-binding-declaration</span></em><span> </span><em><span>initializer</span></em></ins></p>
</blockquote><p><span>Modify </span><a href="https://eel.is/c++draft/stmt.stmt#stmt.pre-4" target="_blank" rel="noopener"><span>[stmt.pre]/4</span></a><span> as follows:</span></p><blockquote>
<p><span>The rules for </span><em><span>conditions</span></em><span> apply both to </span><em><span>selection-statements</span></em><span> (</span><a href="https://eel.is/c++draft/stmt.stmt#stmt.select" target="_blank" rel="noopener"><span>[stmt.select]</span></a><span>) and to the </span><code>for</code><span> and </span><code>while</code><span> statements (</span><a href="https://eel.is/c++draft/stmt.stmt#stmt.iter" target="_blank" rel="noopener"><span>[stmt.iter]</span></a><span>). </span><ins><span>If a </span><em><span>structured-binding-declaration</span></em><span> appears in a </span><em><span>condition</span></em><span>, the </span><em><span>condition</span></em><span> is a structured binding declaration (</span><a href="https://eel.is/c++draft/dcl.pre" target="_blank" rel="noopener"><span>[dcl.pre]</span></a><span>)</span></ins><span> A </span><em><span>condition</span></em><span> that is </span><s><span>not</span></s><ins><span>neither</span></ins><span> an </span><em><span>expression</span></em><span> </span><ins><span>nor a structured binding declaration</span></ins><span> is a declaration (</span><a href="https://eel.is/c++draft/dcl.dcl" target="_blank" rel="noopener"><span>[dcl.dcl]</span></a><span>). The </span><em><span>declarator</span></em><span> shall not specify a function or an array. The </span><em><span>decl-specifier-seq</span></em><span> shall not define a class or enumeration. If the </span><code>auto</code><span> </span><em><span>type-specifier</span></em><span> appears in the </span><em><span>decl-specifier-seq</span></em><span>, the type of the identifier being declared is deduced from the initializer as described in </span><a href="https://eel.is/c++draft/dcl.spec.auto" target="_blank" rel="noopener"><span>[dcl.spec.auto]</span></a><span>.</span></p>
</blockquote><p><span>Insert a paragraph between </span><a href="https://eel.is/c++draft/stmt.stmt#stmt.pre-4" target="_blank" rel="noopener"><span>[stmt.pre]/4</span></a><span> and </span><a href="https://eel.is/c++draft/stmt.stmt#stmt.pre-5" target="_blank" rel="noopener"><span>[stmt.pre]/5</span></a><span>:</span></p><blockquote>
<p><ins><span>The </span><em><span>decision variable</span></em><span> of a </span><em><span>condition</span></em><span> that is neither an </span><em><span>expression</span></em><span> nor a structured binding declaration is the declared variable. The decision variable of a </span><em><span>condition</span></em><span> that is a structured binding declaration is specified in </span><a href="https://eel.is/c++draft/dcl.struct.bind" target="_blank" rel="noopener"><span>[dcl.struct.bind]</span></a><span>.</span></ins></p>
</blockquote><p><span>Edit the original </span><a href="https://eel.is/c++draft/stmt.stmt#stmt.pre-5" target="_blank" rel="noopener"><span>[stmt.pre]/5</span></a><span> as follows:</span></p><blockquote>
<p><span>The value of a </span><em><span>condition</span></em><span> that is </span><s><span>an initialized declaration</span></s><ins><span>not an </span><em><span>expression</span></em></ins><span> in a statement other than a </span><code>switch</code><span> statement is the value of the </span><s><span>declared</span></s><ins><span>decision</span></ins><span> variable contextually converted to </span><code>bool</code><span> (</span><a href="https://eel.is/c++draft/conv#def:conversion,contextual_to_bool" target="_blank" rel="noopener"><span>[conv]</span></a><span>). If that conversion is ill-formed, the program is ill-formed. The value of a </span><em><span>condition</span></em><span> that is an expression is the value of the expression, contextually converted to </span><code>bool</code><span> for statements other than </span><code>switch</code><span>; if that conversion is ill-formed, the program is ill-formed.  The value of the condition will be referred to as simply "the condition" where the usage is unambiguous.</span></p>
</blockquote><p><span>Modify the original </span><a href="https://eel.is/c++draft/stmt.stmt#stmt.pre-7" target="_blank" rel="noopener"><span>[stmt.pre]/7</span></a><span> as follows:</span></p><blockquote>
<p><span>In the </span><em><span>decl-specifier-seq</span></em><span> of a </span><em><span>condition</span></em><ins><span>, including that of any </span><em><span>structured-binding-declaration</span></em><span> of the </span><em><span>condition</span></em></ins><span>, each </span><em><span>decl-specifier</span></em><span> shall be either a </span><em><span>type-specifier</span></em><span> or </span><code>constexpr</code><span>.</span></p>
</blockquote><p><span>Edit </span><a href="https://eel.is/c++draft/stmt.switch" target="_blank" rel="noopener"><span>[stmt.switch]/2</span></a><span> as follows:</span></p><blockquote>
<p><s><span>The value of a </span><em><span>condition</span></em><span> that is an initialized declaration is the value of the declared variable, or the value of the </span><em><span>expression</span></em><span> otherwise.</span></s><ins><span>If the </span><em><span>condition</span></em><span> is an </span><em><span>expression</span></em><span>, the value of the condition is the value of the </span><em><span>expression</span></em><span>; otherwise, it is the value of the decision variable.</span></ins><span> The value of the condition shall be of integral type, enumeration type, or class type. If of class type, the condition is contextually implicitly converted (</span><a href="https://eel.is/c++draft/conv#def:contextually_implicitly_converted" target="_blank" rel="noopener"><span>[conv]</span></a><span>) to an integral or enumeration type. If the (possibly converted) type is subject to integral promotions (</span><a href="https://eel.is/c++draft/conv.prom" target="_blank" rel="noopener"><span>[conv.prom]</span></a><span>), the condition is converted to the promoted type. [</span><span class="smartypants">…</span><span>]</span></p>
</blockquote><p><span>Modify </span><a href="https://eel.is/c++draft/dcl.pre#7" target="_blank" rel="noopener"><span>[dcl.pre]/7</span></a><span> as follows:</span></p><blockquote>
<p><span>A </span><em><span>simple-declaration</span></em><span> </span><ins><span>or a </span><em><span>condition</span></em></ins><span> with a </span><em><span>structured-binding-declaration</span></em><span> is called a </span><em><span>structured binding declaration</span></em><span> (</span><a href="https://eel.is/c++draft/dcl.struct.bind" target="_blank" rel="noopener"><span>[dcl.struct.bind]</span></a><span>). [</span><span class="smartypants">…</span><span>]</span></p>
<p><em><span>[Example 3:</span></em></p>
<pre><code>template&lt;class T&gt; concept C = true;
C auto [x, y] = std::pair{1, 2};  // error: constrained placeholder-type-specifier
                                  // not permitted for structured bindings
</code></pre>
<p><em><span class="smartypants">–</span><span>end example]</span></em></p>
<p><span>The </span><em><span>initializer</span></em><span> shall be of the form "</span><code>=</code><span> </span><em><span>assignment-expression</span></em><span>", of the form "</span><code>{</code><span> </span><em><span>assignment-expression</span></em><span> </span><code>}</code><span>", or of the form "</span><code>(</code><span> </span><em><span>assignment-expression</span></em><span> </span><code>)</code><span>"</span><ins><span>. If the </span><em><span>structured-binding-declaration</span></em><span> appears as a </span><em><span>condition</span></em><span>, the </span><em><span>assignment-expression</span></em><span> shall be of non-union class type. Otherwise,</span></ins><span> </span><s><span>where</span></s><span> the </span><em><span>assignment-expression</span></em><span> </span><s><span>is</span></s><ins><span>shall be of</span></ins><span> array or non-union class type.</span></p>
</blockquote><p><span>Insert a paragraph between </span><a href="https://eel.is/c++draft/dcl.struct.bind#1" target="_blank" rel="noopener"><span>[dcl.struct.bind]/1</span></a><span> and </span><a href="https://eel.is/c++draft/dcl.struct.bind#2" target="_blank" rel="noopener"><span>[dcl.struct.bind]/2</span></a><span>:</span></p><blockquote>
<p><ins><span>If a structured binding declaration appears as a </span><em><span>condition</span></em><span>, the decision variable (</span><a href="https://eel.is/c++draft/stmt.pre" target="_blank" rel="noopener"><span>[stmt.pre]</span></a><span>) of the condition is </span><em><code>e</code></em><span>.</span></ins></p>
</blockquote><div class="alert alert-warning">
<p><em><span>[Drafting note:</span></em><span> The wording to be added by CWG2867 is </span><mark><span>highlighted</span></mark><span>. </span><em><span class="smartypants">–</span><span>end note]</span></em></p>
</div><p><span>Modify the original </span><a href="https://eel.is/c++draft/dcl.struct.bind#4" target="_blank" rel="noopener"><span>[dcl.struct.bind]/4</span></a><span> as follows:</span></p><blockquote>
<p><span>[</span><span class="smartypants">…</span><span>], otherwise, variables are introduced with unique names </span><code>r</code><sub><em><span>i</span></em></sub><span> as follows:</span></p>
<p><span>&nbsp;&nbsp;</span><code style="white-space: pre-wrap"><i><span>S</span></i><span> U</span><sub><i><span>i</span></i></sub><span> r</span><sub><i><span>i</span></i></sub><span> = </span><i><span>initializer</span></i><span>;</span></code></p>
<p><span>Each </span><code>v</code><sub><em><span>i</span></em></sub><span> is the name of an lvalue of type </span><code>T</code><sub><em><span>i</span></em></sub><span> that refers to the object bound to </span><code>r</code><sub><em><span>i</span></em></sub><span>; the referenced type is </span><code>T</code><sub><em><span>i</span></em></sub><span>. </span><mark><span>The initialization of </span><em><code>e</code></em><ins><span>and any conversion of </span><em><code>e</code></em><span> considered as a decision variable (</span><a href="https://eel.is/c++draft/stmt.stmt" target="_blank" rel="noopener"><span>[stmt.pre]</span></a><span>)</span></ins><span> is sequenced before the initialization of any </span><code>r</code><sub><em><span>i</span></em></sub><span>. The initialization of </span><code>r</code><sub><em><span>i</span></em></sub><span> is sequenced before the initialization of </span><code>r</code><sub><em><span>j</span></em></sub><span> if </span><span class="mathjax"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="182" style="font-size: 123.5%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D456 TEX-I"></mjx-c></mjx-mi><mjx-mo class="mjx-n" space="4"><mjx-c class="mjx-c3C"></mjx-c></mjx-mo><mjx-mi class="mjx-i" space="4"><mjx-c class="mjx-c1D457 TEX-I"></mjx-c></mjx-mi></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>i</mi><mo>&lt;</mo><mi>j</mi></math></mjx-assistive-mml></mjx-container></span><span>.</span></mark></p>
</blockquote><h2 id="Implementation" data-id="Implementation"><a class="anchor hidden-xs" href="#Implementation" title="Implementation"><span class="octicon octicon-link ph ph-link-simple-horizontal"></span></a><span>Implementation</span></h2><p><span>R1 semantics has been shipped in Clang since 6.0.0, guarded by </span><code>-Wbinding-in-condition</code><span>: </span><ruby><a href="https://godbolt.org/z/b64x65716" target="_blank" rel="noopener"><span class="godbolt"><span> </span></span><span>b64x65716</span></a><rt><span>Compiler Explorer</span></rt></ruby><span>; R2 has not been implemented.</span></p><h2 id="Acknowledgements" data-id="Acknowledgements"><a class="anchor hidden-xs" href="#Acknowledgements" title="Acknowledgements"><span class="octicon octicon-link ph ph-link-simple-horizontal"></span></a><span>Acknowledgements</span></h2><p><span>Thank Richard Smith for encouraging the work and Hana Dusíková for providing motivating examples. Thank Tim Song for additional examples that suggest the revised semantics. Thank Jens Maurer for the wording review.</span></p><h2 id="References" data-id="References"><a class="anchor hidden-xs" href="#References" title="References"><span class="octicon octicon-link ph ph-link-simple-horizontal"></span></a><span>References</span></h2><hr class="footnotes-sep"><section class="footnotes">
<ol class="footnotes-list" style="padding-left: 2em;">
<li id="fn1" class="footnote-item"><p><span>Wakely, Jonathan. P2497R0 </span><em><span>Testing for success or failure of </span><code>&lt;charconv&gt;</code><span> functions</span></em><span>.</span><br>
<a href="https://wg21.link/p2497r0" target="_blank" rel="noopener"><span>https://wg21.link/p2497r0</span></a> <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn2" class="footnote-item"><p><span>Dusíková, Hana. P1433R0 </span><em><span>Compile Time Regular Expressions</span></em><span>.</span><br>
<a href="https://wg21.link/p1433r0" target="_blank" rel="noopener"><span>https://wg21.link/p1433r0</span></a> <a href="#fnref2" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn3" class="footnote-item"><p><span>Park, Michael. P2688R1 </span><em><span>Pattern Matching: </span><code>match</code><span> Expression</span></em><span>.</span><br>
<a href="https://wg21.link/p2688r1" target="_blank" rel="noopener"><span>https://wg21.link/p2688r1</span></a> <a href="#fnref3" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn4" class="footnote-item"><p><span>Josuttis, Nicolai, et al. P2644R1 </span><em><span>Final Fix of Broken Range‐based </span><code>for</code><span> Loop, Rev 1</span></em><span>.</span><br>
<a href="https://wg21.link/p2644r1" target="_blank" rel="noopener"><span>https://wg21.link/p2644r1</span></a> <a href="#fnref4" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn5" class="footnote-item"><p><span>Smith, Richard. CWG2867 </span><em><span>Order of initialization for structured bindings</span></em><span>.</span><br>
<a href="https://cplusplus.github.io/CWG/issues/2867.html" target="_blank" rel="noopener"><span>https://cplusplus.github.io/CWG/issues/2867.html</span></a> <a href="#fnref5" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section></div>
    <div class="ui-toc dropup unselectable hidden-print" style="display:none;">
        <div class="pull-right dropdown">
            <a id="tocLabel" class="ui-toc-label btn btn-default" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false" title="Table of content">
                <i class="fa fa-bars"></i>
            </a>
            <ul id="ui-toc" class="ui-toc-dropdown dropdown-menu" aria-labelledby="tocLabel">
                <div class="toc"><ul class="nav">
<li><a href="#Structured-binding-declaration-as-a-condition" title="Structured binding declaration as a condition">Structured binding declaration as a condition</a><ul class="nav">
<li><a href="#Changes" title="Changes">Changes</a></li>
<li><a href="#Introduction" title="Introduction">Introduction</a></li>
<li><a href="#Motivation" title="Motivation">Motivation</a></li>
<li><a href="#Design-Decisions" title="Design Decisions">Design Decisions</a><ul class="nav">
<li><a href="#Unconditionally-decompose" title="Unconditionally decompose">Unconditionally decompose</a></li>
<li><a href="#Testing-is-sequenced-before-decomposing" title="Testing is sequenced before decomposing">Testing is sequenced before decomposing</a></li>
<li><a href="#No-underlying-array-object" title="No underlying array object">No underlying array object</a></li>
</ul>
</li>
<li><a href="#Wording" title="Wording">Wording</a></li>
<li><a href="#Implementation" title="Implementation">Implementation</a></li>
<li><a href="#Acknowledgements" title="Acknowledgements">Acknowledgements</a></li>
<li><a href="#References" title="References">References</a></li>
</ul>
</li>
</ul>
</div><div class="toc-menu"><a class="expand-toggle" href="#">Expand all</a><a class="back-to-top" href="#">Back to top</a><a class="go-to-bottom" href="#">Go to bottom</a></div>
            </ul>
        </div>
    </div>
    <div id="ui-toc-affix" class="ui-affix-toc ui-toc-dropdown unselectable hidden-print" data-spy="affix" style="top:17px;display:none;"  >
        <div class="toc"><ul class="nav">
<li><a href="#Structured-binding-declaration-as-a-condition" title="Structured binding declaration as a condition">Structured binding declaration as a condition</a><ul class="nav">
<li><a href="#Changes" title="Changes">Changes</a></li>
<li><a href="#Introduction" title="Introduction">Introduction</a></li>
<li><a href="#Motivation" title="Motivation">Motivation</a></li>
<li><a href="#Design-Decisions" title="Design Decisions">Design Decisions</a><ul class="nav">
<li><a href="#Unconditionally-decompose" title="Unconditionally decompose">Unconditionally decompose</a></li>
<li><a href="#Testing-is-sequenced-before-decomposing" title="Testing is sequenced before decomposing">Testing is sequenced before decomposing</a></li>
<li><a href="#No-underlying-array-object" title="No underlying array object">No underlying array object</a></li>
</ul>
</li>
<li><a href="#Wording" title="Wording">Wording</a></li>
<li><a href="#Implementation" title="Implementation">Implementation</a></li>
<li><a href="#Acknowledgements" title="Acknowledgements">Acknowledgements</a></li>
<li><a href="#References" title="References">References</a></li>
</ul>
</li>
</ul>
</div><div class="toc-menu"><a class="expand-toggle" href="#">Expand all</a><a class="back-to-top" href="#">Back to top</a><a class="go-to-bottom" href="#">Go to bottom</a></div>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha256-U5ZEeKfGNOja007MMD3YBI0A3OSZOQbeG6z2f2Y0hu8=" crossorigin="anonymous" defer></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gist-embed/2.6.0/gist-embed.min.js" integrity="sha256-KyF2D6xPIJUW5sUDSs93vWyZm+1RzIpKCexxElmxl8g=" crossorigin="anonymous" defer></script>
    <script>
        var markdown = $(".markdown-body");
        //smooth all hash trigger scrolling
        function smoothHashScroll() {
            var hashElements = $("a[href^='#']").toArray();
            for (var i = 0; i < hashElements.length; i++) {
                var element = hashElements[i];
                var $element = $(element);
                var hash = element.hash;
                if (hash) {
                    $element.on('click', function (e) {
                        // store hash
                        var hash = this.hash;
                        if ($(hash).length <= 0) return;
                        // prevent default anchor click behavior
                        e.preventDefault();
                        // animate
                        $('body, html').stop(true, true).animate({
                            scrollTop: $(hash).offset().top
                        }, 100, "linear", function () {
                            // when done, add hash to url
                            // (default click behaviour)
                            window.location.hash = hash;
                        });
                    });
                }
            }
        }

        smoothHashScroll();
        var toc = $('.ui-toc');
        var tocAffix = $('.ui-affix-toc');
        var tocDropdown = $('.ui-toc-dropdown');
        //toc
        tocDropdown.click(function (e) {
            e.stopPropagation();
        });

        var enoughForAffixToc = true;

        function generateScrollspy() {
            $(document.body).scrollspy({
                target: ''
            });
            $(document.body).scrollspy('refresh');
            if (enoughForAffixToc) {
                toc.hide();
                tocAffix.show();
            } else {
                tocAffix.hide();
                toc.show();
            }
            $(document.body).scroll();
        }

        function windowResize() {
            //toc right
            var paddingRight = parseFloat(markdown.css('padding-right'));
            var right = ($(window).width() - (markdown.offset().left + markdown.outerWidth() - paddingRight));
            toc.css('right', right + 'px');
            //affix toc left
            var newbool;
            var rightMargin = (markdown.parent().outerWidth() - markdown.outerWidth()) / 2;
            //for ipad or wider device
            if (rightMargin >= 133) {
                newbool = true;
                var affixLeftMargin = (tocAffix.outerWidth() - tocAffix.width()) / 2;
                var left = markdown.offset().left + markdown.outerWidth() - affixLeftMargin;
                tocAffix.css('left', left + 'px');
            } else {
                newbool = false;
            }
            if (newbool != enoughForAffixToc) {
                enoughForAffixToc = newbool;
                generateScrollspy();
            }
        }
        $(window).resize(function () {
            windowResize();
        });
        $(document).ready(function () {
            windowResize();
            generateScrollspy();
        });

        //remove hash
        function removeHash() {
            window.location.hash = '';
        }

        var backtotop = $('.back-to-top');
        var gotobottom = $('.go-to-bottom');

        backtotop.click(function (e) {
            e.preventDefault();
            e.stopPropagation();
            if (scrollToTop)
                scrollToTop();
            removeHash();
        });
        gotobottom.click(function (e) {
            e.preventDefault();
            e.stopPropagation();
            if (scrollToBottom)
                scrollToBottom();
            removeHash();
        });

        var toggle = $('.expand-toggle');
        var tocExpand = false;

        checkExpandToggle();
        toggle.click(function (e) {
            e.preventDefault();
            e.stopPropagation();
            tocExpand = !tocExpand;
            checkExpandToggle();
        })

        function checkExpandToggle () {
            var toc = $('.ui-toc-dropdown .toc');
            var toggle = $('.expand-toggle');
            if (!tocExpand) {
                toc.removeClass('expand');
                toggle.text('Expand all');
            } else {
                toc.addClass('expand');
                toggle.text('Collapse all');
            }
        }

        function scrollToTop() {
            $('body, html').stop(true, true).animate({
                scrollTop: 0
            }, 100, "linear");
        }

        function scrollToBottom() {
            $('body, html').stop(true, true).animate({
                scrollTop: $(document.body)[0].scrollHeight
            }, 100, "linear");
        }
    </script>
</body>

</html>
