<!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>
        constant dangling - 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-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;padding:6px 13px}.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{background-color:#f7f7f7;border-radius:3px;font-size:85%;line-height:1.45;overflow:auto;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-body{max-width:758px;overflow:visible!important;padding-bottom:40px;padding-top:40px;position:relative}.markdown-body .emoji{vertical-align:top}.markdown-body pre{border:inherit!important}.markdown-body code{color:inherit!important}.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:3px solid #6ce26c!important;box-sizing:initial;color:#afafaf!important;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>p:last-child{margin-bottom: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 .alert>p:last-child,.markdown-body .alert>ul:last-child{margin-bottom:0}.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}.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:#777;margin:25px auto -25px;max-width:760px;position:relative;z-index:2}.toc .invisable-node{list-style-type:none}.ui-toc{bottom:20px;position:fixed;z-index:998}.ui-toc.both-mode{margin-left:8px}.ui-toc.both-mode .ui-toc-label{border-bottom-left-radius:0;border-top-left-radius:0;height:40px;padding:10px 4px}.ui-toc-label{background-color:#e6e6e6;border:none;color:#868686;transition:opacity .2s}.ui-toc .open .ui-toc-label{color:#fff;opacity:1;transition:opacity .2s}.ui-toc-label:focus{background-color:#ccc;color:#000;opacity:.3}.ui-toc-label:hover{background-color:#ccc;opacity:1;transition:opacity .2s}.ui-toc-dropdown{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>.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:#767676;display:block;font-size:13px;font-weight:500;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-left:1px solid #000;color:#000;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-left:2px solid #000;color:#000;font-weight:700;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-left:none;border-right:2px solid #000;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}.markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html[lang^=ja] .markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,Hiragino Kaku Gothic Pro,ヒラギノ角ゴ Pro W3,Osaka,Meiryo,メイリオ,MS Gothic,ＭＳ ゴシック,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html[lang=zh-tw] .markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html[lang=zh-cn] .markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html .markdown-body[lang^=ja]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,Hiragino Kaku Gothic Pro,ヒラギノ角ゴ Pro W3,Osaka,Meiryo,メイリオ,MS Gothic,ＭＳ ゴシック,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html .markdown-body[lang=zh-tw]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html .markdown-body[lang=zh-cn]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html[lang^=ja] .ui-toc-dropdown{font-family:Source Sans Pro,Helvetica,Arial,Meiryo UI,MS PGothic,ＭＳ Ｐゴシック,sans-serif}html[lang=zh-tw] .ui-toc-dropdown{font-family:Source Sans Pro,Helvetica,Arial,Microsoft JhengHei UI,微軟正黑UI,sans-serif}html[lang=zh-cn] .ui-toc-dropdown{font-family:Source Sans Pro,Helvetica,Arial,Microsoft YaHei UI,微软雅黑UI,sans-serif}html .ui-toc-dropdown[lang^=ja]{font-family:Source Sans Pro,Helvetica,Arial,Meiryo UI,MS PGothic,ＭＳ Ｐゴシック,sans-serif}html .ui-toc-dropdown[lang=zh-tw]{font-family:Source Sans Pro,Helvetica,Arial,Microsoft JhengHei UI,微軟正黑UI,sans-serif}html .ui-toc-dropdown[lang=zh-cn]{font-family:Source Sans Pro,Helvetica,Arial,Microsoft YaHei UI,微软雅黑UI,sans-serif}.ui-affix-toc{max-height:70vh;max-width:15vw;overflow:auto;position:fixed;top:0}.back-to-top,.expand-toggle,.go-to-bottom{color:#999;display:block;font-size:12px;font-weight:500;margin-left:10px;margin-top:10px;padding:4px 10px}.back-to-top:focus,.back-to-top:hover,.expand-toggle:focus,.expand-toggle:hover,.go-to-bottom:focus,.go-to-bottom:hover{color:#563d7c;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{color:#888;cursor:pointer;vertical-align:middle}.ui-more-info .fa{font-size:16px}.ui-connectedGithub,.ui-published-note{color:#888}.ui-connectedGithub{line-height:23px;white-space:nowrap}.ui-connectedGithub a.file-path{color:#888;padding-left:22px;text-decoration:none}.ui-connectedGithub a.file-path:active,.ui-connectedGithub a.file-path:hover{color:#888;text-decoration:underline}.ui-connectedGithub .fa{font-size:20px}.ui-published-note .fa{font-size:20px;vertical-align:top}.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" data-hard-breaks="false"><style>
ins { background-color: #CCFFCC }
s { background-color: #FFCACA }
blockquote { color: inherit !important }
</style><table>
<tbody><tr>
<td>Document number</td>
<td>P2724R0</td>
</tr>
<tr>
<td>Date</td>
<td>2022-12-11</td>
</tr>
<tr>
<td>Reply-to</td>
<td>
<p><span>Jarrad J. Waterloo &lt;descender76 at gmail dot com&gt;</span></p>
</td>
</tr>
<tr>
<td>Audience</td>
<td>Evolution Working Group (EWG)</td>
</tr>
</tbody></table><h1 id="constant-dangling" data-id="constant-dangling"><a class="anchor hidden-xs" href="#constant-dangling" title="constant-dangling"><span class="octicon octicon-link"></span></a><span>constant dangling</span></h1><style>
.inline-link
{
    font-size: small;
    margin-top: -2.8em;
    margin-right: 4px;
    text-align: right;
    font-weight: bold;
}

code
{
    font-family: "Fira Code", monospace !important;
    font-size: 0.87em;
}

.sourceCode
{
    font-size: 0.95em;
}

a code
{
    color: #0645ad;
}
</style><h2 id="Table-of-contents" data-id="Table-of-contents"><a class="anchor hidden-xs" href="#Table-of-contents" title="Table-of-contents"><span class="octicon octicon-link"></span></a><span>Table of contents</span></h2><ul>
<li><a href="#constant-dangling"><span>constant dangling</span></a>
<ul>
<li><a href="#Changelog"><span>Changelog</span></a></li>
<li><a href="#Abstract"><span>Abstract</span></a></li>
<li><a href="#Motivation"><span>Motivation</span></a></li>
<li><a href="#Motivating-Examples"><span>Motivating examples</span></a></li>
<li><a href="#Proposed-Wording"><span>Proposed Wording</span></a></li>
<li><a href="#In-Depth-Rationale"><span>In Depth Rationale</span></a></li>
<li><a href="#Value-Categories"><span>Value Categories</span></a></li>
<li><a href="#Performance-Considerations"><span>Performance Considerations</span></a></li>
<li><a href="#Tooling-Opportunities"><span>Tooling Opportunities</span></a></li>
<li><a href="#Summary"><span>Summary</span></a></li>
<li><a href="#Frequently-Asked-Questions"><span>Frequently Asked Questions</span></a></li>
<li><a href="#References"><span>References</span></a></li>
</ul>
</li>
</ul><h2 id="Changelog" data-id="Changelog"><a class="anchor hidden-xs" href="#Changelog" title="Changelog"><span class="octicon octicon-link"></span></a><span>Changelog</span></h2><h3 id="R0" data-id="R0"><a class="anchor hidden-xs" href="#R0" title="R0"><span class="octicon octicon-link"></span></a><span>R0</span></h3><ul>
<li><span>The constant content was extracted and merged from the </span><code>temporary storage class specifiers</code><span> </span><sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup><span> and </span><code>implicit constant initialization</code><span> </span><sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup><span> proposals.</span></li>
</ul><h2 id="Abstract" data-id="Abstract"><a class="anchor hidden-xs" href="#Abstract" title="Abstract"><span class="octicon octicon-link"></span></a><span>Abstract</span></h2><p><span>This paper proposes the standard adds anonymous global constants to the language with the intention of automatically fixing a shocking type of dangling which occurs when constants or that which should be constants dangle. This is shocking because constant like instances should really have constant-initialization meaning that they should have static storage duration and consequently should not dangle. This trips up beginner code requiring teaching dangling on day one. It is annoying to non beginners. Constants are used as defaults in production code. Constants are also frequently used in test and example code. Further, many instances of dangling used by non </span><code>C++</code><span> language comparisons frequently use constants as examples.</span></p><h2 id="Motivation" data-id="Motivation"><a class="anchor hidden-xs" href="#Motivation" title="Motivation"><span class="octicon octicon-link"></span></a><span>Motivation</span></h2><p><span>There are multiple resolutions to dangling in the </span><code>C++</code><span> language.</span></p><ol>
<li><span>Produce an error</span>
<ul>
<li><code>Simpler implicit move</code><span> </span><sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup></li>
</ul>
</li>
<li><span>Fix with block/variable scoping</span>
<ul>
<li><code>Fix the range-based for loop, Rev2</code><span> </span><sup class="footnote-ref"><a href="#fn4" id="fnref4">[4]</a></sup></li>
<li><code>Get Fix of Broken Range-based for Loop Finally Done</code><span> </span><sup class="footnote-ref"><a href="#fn5" id="fnref5">[5]</a></sup></li>
</ul>
</li>
<li><span>Fix by making the instance global</span>
<ul>
<li><strong><code>This proposal</code></strong></li>
</ul>
</li>
</ol><p><span>All are valid resolutions and individually are better than the others, given the scenario. This proposal is focused on the third option, which is to fix by making the instance global.</span></p><p><span>Dangling the stack is shocking because is violates our trust in our compilers and language, since they are primarily responsible for the stack. However, there are three types of dangling that are even more shocking than the rest.</span></p><ol>
<li><span>Returning a </span><strong><span>direct</span></strong><span> reference to a local</span>
<ul>
<li><span>partially resolved by </span><code>Simpler implicit move</code><span> </span><sup class="footnote-ref"><a href="#fn3" id="fnref3:1">[3:1]</a></sup></li>
</ul>
</li>
<li><span>Immediate dangling</span></li>
<li><strong><span>Dangling Constants</span></strong></li>
</ol><p><span>Making an instance global is a legitimate fix to dangling.</span></p><table>
<tbody><tr>
<td>
<p><strong><span>C++ Core Guidelines</span></strong><br><strong><span>F.43: Never (directly or indirectly) return a pointer or a reference to a local object</span></strong><span> </span><sup class="footnote-ref"><a href="#fn6" id="fnref6">[6]</a></sup></p>
<p><em><strong><span>Reason</span></strong><span> To avoid the crashes and data corruption that can result from the use of such a dangling pointer.</span></em><span> </span><sup class="footnote-ref"><a href="#fn6" id="fnref6:1">[6:1]</a></sup></p>
<p><span>…</span></p>
<p><em><strong><span>Note</span></strong><span> This applies only to non-static local variables. All static variables are (as their name indicates) statically allocated, so that pointers to them cannot dangle.</span></em><span> </span><sup class="footnote-ref"><a href="#fn6" id="fnref6:2">[6:2]</a></sup></p>
</td>
</tr>
</tbody></table><p><span>While making an instance global doesn’t fix all dangling in the language, it is the only resolution that can fix all three most shocking types of dangling provided the instance in question is a constant. It is also the </span><strong><span>best</span></strong><span> fix for these instances.</span></p><p><span>Since </span><code>constexpr</code><span> was added to the language in </span><code>C++11</code><span> there has been an increase in the candidates of temporary instances that could be turned into global constants. ROMability was in part the motivation for </span><code>constexpr</code><span> but the requirement was never made. Even if a </span><code>C++</code><span> architecture doesn’t support ROM, it is still required by language to support </span><code>static storage duration</code><span> and </span><code>const</code><span>. Matter of fact, due to the immutable nature of constant-initialized constant expressions, these expressions/instances are constant for the entire program even though they, at present, don’t have </span><code>static storage duration</code><span>, even if just </span><a href="#What-about-locality-of-reference" title="What-about-locality-of-reference"><span>logically</span></a><span>. There is a greater need now that more types are getting constexpr constructors. Also types that would normally only be dynamically allocated, such as string and vector, since </span><code>C++20</code><span>, can also be </span><code>constexpr</code><span>. This has opened up the door wide for many more types being constructed at compile time.</span></p><h2 id="Motivating-Examples" data-id="Motivating-Examples"><a class="anchor hidden-xs" href="#Motivating-Examples" title="Motivating-Examples"><span class="octicon octicon-link"></span></a><span>Motivating Examples</span></h2><p><span>Before diving into the examples, let’s discuss what exactly is being asked for. There are two features; one implicit and the other explicit.</span></p><p><strong><span>implicit constant initialization</span></strong></p><p><span>If a temporary argument is constant-initialized </span><sup class="footnote-ref"><a href="#fn7" id="fnref7">[7]</a></sup><span> </span><sup><em><span>(7.7 Constant expressions [expr.const])</span></em></sup>
<span>and its argument/instance type is a </span><code>LiteralType</code>
<span>and its parameter/local/member type is </span><code>const</code><span> and not </span><code>mutable</code>
<span>then the instance is implicitly created with </span><code>constant initialization</code><span>.</span></p><p><span>As such it has </span><code>static storage duration</code><span> and can’t dangle.</span></p><p><strong><span>explicit constant initialization</span></strong></p><p><span>The </span><code>constinit</code><span> specifier can be applied to temporaries. Applying it asserts that the temporary was </span><code>const-initialized</code><span>, that the argument type is a </span><code>LiteralType</code><span> and its parameter/local/member type is </span><code>const</code><span> and not </span><code>mutable</code><span>. This explicitly gives the temporary </span><code>static storage duration</code><span>.</span></p><p><span>While </span><code>implicit constant initialization</code><span> automatically fixes dangle, </span><code>constinit</code><span> allows the programmers to manually and explicitly fix some dangling. The former is better for programmers and the language, while the later favors code reviewers or programmers who copy an example and want to have the compiler, momentarily, verify whether it is correct.</span></p><p><span>So what sorts of dangling does this fix for us. Besides fixing some dangling, this also fixes some inconsistencies between string literals </span><sup class="footnote-ref"><a href="#fn7" id="fnref7:1">[7:1]</a></sup><span> </span><sup><em><span>(5.13.5 String literals [lex.string])</span></em></sup><span> and other literal types.</span></p><pre><code class="cpp hljs"><span class="token comment">// does not dangle because string literals are lvalues with static storage duration</span>
std<span class="token double-colon punctuation">::</span>string_view sv <span class="token operator">=</span> <span class="token string">"hello world"</span><span class="token punctuation">;</span>
<span class="token comment">// immediate dangling reference</span>
<span class="token comment">// even though "hello world"s is a constant-initialized,</span>
<span class="token comment">// literal type that is only being used in a const fashion</span>
std<span class="token double-colon punctuation">::</span>string_view sv <span class="token operator">=</span> <span class="token string">"hello world"</span>s<span class="token punctuation">;</span><span class="token comment">// fixed in this proposal</span>
std<span class="token double-colon punctuation">::</span>string_view sv <span class="token operator">=</span> <span class="token keyword">constinit</span> <span class="token string">"hello world"</span>s<span class="token punctuation">;</span><span class="token comment">// fixed in this proposal</span>
</code></pre><p><span>This is reasonable based on how programmers reason about constants being immutable variables and temporaries which are known at compile time and do not change for the life of the program. This also works with plain old references.</span></p><pre><code class="cpp hljs"><span class="token keyword">struct</span> <span class="token class-name">X</span>
<span class="token punctuation">{</span>
    <span class="token keyword">int</span> a<span class="token punctuation">,</span> b<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> <span class="token function">get_a</span><span class="token punctuation">(</span><span class="token keyword">const</span> X<span class="token operator">&amp;</span> x<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token comment">// sporadically dangling, returning indirect reference</span>
    <span class="token keyword">return</span> x<span class="token punctuation">.</span>a<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> a <span class="token operator">=</span> <span class="token function">get_a</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
a<span class="token punctuation">;</span> <span class="token comment">// currently dangling, will be 4 with this proposal</span>
</code></pre><p><em><span>“Such a feature would also help to … fix several bugs we see in practice:”</span></em><span> </span><sup class="footnote-ref"><a href="#fn8" id="fnref8">[8]</a></sup></p><p><em><span>“Consider we have a function returning the value of a map element or a default value if no such element exists without copying it:”</span></em><span> </span><sup class="footnote-ref"><a href="#fn8" id="fnref8:1">[8:1]</a></sup></p><pre><code class="cpp hljs"><span class="token keyword">const</span> V<span class="token operator">&amp;</span> <span class="token function">findOrDefault</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>map<span class="token operator">&lt;</span>K<span class="token punctuation">,</span>V<span class="token operator">&gt;</span><span class="token operator">&amp;</span> m<span class="token punctuation">,</span> <span class="token keyword">const</span> K<span class="token operator">&amp;</span> key<span class="token punctuation">,</span> <span class="token keyword">const</span> V<span class="token operator">&amp;</span> defvalue<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p><em><span>“then this results in a classical bug:”</span></em><span> </span><sup class="footnote-ref"><a href="#fn8" id="fnref8:2">[8:2]</a></sup></p><pre><code class="cpp hljs">std<span class="token double-colon punctuation">::</span>map<span class="token operator">&lt;</span>std<span class="token double-colon punctuation">::</span>string<span class="token punctuation">,</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&gt;</span> myMap<span class="token punctuation">;</span>
<span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&amp;</span> s <span class="token operator">=</span> <span class="token function">findOrDefault</span><span class="token punctuation">(</span>myMap<span class="token punctuation">,</span> key<span class="token punctuation">,</span> <span class="token string">"none"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// runtime bug if key not found</span>
</code></pre><p><span>Is this really a bug? With this proposal, it isn’t! Here is why. The function </span><code>findOrDefault</code><span> </span><strong><span>expects</span></strong><span> a </span><strong><code>const</code></strong><span> </span><code>string&amp;</code><span> for its third parameter. Since </span><code>C++20</code><span>, string’s constructor is </span><code>constexpr</code><span>. It </span><strong><span>CAN</span></strong><span> be constructed as a constant expression. Since all the arguments passed to this </span><code>constexpr</code><span> constructor are constant expressions, in this case </span><code>"none"</code><span>, the temporary </span><code>string</code><span> </span><code>defvalue</code><span> </span><strong><span>IS</span></strong><span> also </span><code>constant-initialized</code><span> </span><sup class="footnote-ref"><a href="#fn7" id="fnref7:2">[7:2]</a></sup><span> </span><sup><em><span>(7.7 Constant expressions [expr.const])</span></em></sup><span>. This paper advises that if you have a non </span><code>mutable</code><span> </span><code>const</code><span> that it is </span><code>constant-initialized</code><span>, that the variable or temporary undergoes </span><code>constant initialization</code><span> </span><sup class="footnote-ref"><a href="#fn7" id="fnref7:3">[7:3]</a></sup><span> </span><sup><em><span>(6.9.3.2 Static initialization [basic.start.static])</span></em></sup><span>. In other words it has implicit </span><code>static storage duration</code><span>. The temporary would actually cease to be a temporary. As such this usage of </span><code>findOrDefault</code><span> </span><strong><span>CAN’T</span></strong><span> dangle.</span></p><p><span>The pain of immediate dangling associated with temporaries are especially felt when working with other anonymous language features of </span><code>C++</code><span> such as lambda functions and coroutines.</span></p><h4 id="Lambda-functions" data-id="Lambda-functions"><a class="anchor hidden-xs" href="#Lambda-functions" title="Lambda-functions"><span class="octicon octicon-link"></span></a><span>Lambda functions</span></h4><p><span>Whenever a lambda function captures a reference to a temporary it immediately dangles before an opportunity is given to call it, unless it is a immediately invoked lambda/function expression.</span></p><pre><code class="cpp hljs"><span class="token punctuation">[</span><span class="token operator">&amp;</span>c1 <span class="token operator">=</span> <span class="token string">"hello"</span>s<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&amp;</span> s<span class="token punctuation">)</span><span class="token comment">// OK</span>
<span class="token punctuation">{</span>
    <span class="token keyword">return</span> c1 <span class="token operator">+</span> <span class="token string">" "</span>s <span class="token operator">+</span> s<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token string">"world"</span>s<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// immediately invoked lambda/function expression</span>

<span class="token keyword">auto</span> lambda <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token operator">&amp;</span>c1 <span class="token operator">=</span> <span class="token string">"hello"</span>s<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&amp;</span> s<span class="token punctuation">)</span><span class="token comment">// immediate dangling</span>
<span class="token punctuation">{</span>
    <span class="token keyword">return</span> c1 <span class="token operator">+</span> <span class="token string">" "</span>s <span class="token operator">+</span> s<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// ...</span>
<span class="token function">lambda</span><span class="token punctuation">(</span><span class="token string">"world"</span>s<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p><span>This problem is resolved when the scope of temporaries has </span><code>static storage duration</code><span> instead of the containing expression provided </span><code>c1</code><span> resolves to a </span><code>const std::string&amp;</code><span> since </span><code>c1</code><span> was constant-initialized. The </span><code>constinit</code><span> specifier could ensure this.</span></p><h4 id="Coroutines" data-id="Coroutines"><a class="anchor hidden-xs" href="#Coroutines" title="Coroutines"><span class="octicon octicon-link"></span></a><span>Coroutines</span></h4><p><span>Similarly, whenever a coroutine gets constructed with a reference to a temporary it immediately dangles before an opportunity is given for it to be </span><code>co_await</code><span>ed upon.</span></p><pre><code class="cpp hljs">generator<span class="token operator">&lt;</span><span class="token keyword">char</span><span class="token operator">&gt;</span> <span class="token function">each_char</span><span class="token punctuation">(</span><span class="token keyword">const</span> std<span class="token double-colon punctuation">::</span>string<span class="token operator">&amp;</span> s<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">char</span> ch <span class="token operator">:</span> s<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">co_yield</span> ch<span class="token punctuation">;</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">auto</span> ec <span class="token operator">=</span> <span class="token function">each_char</span><span class="token punctuation">(</span><span class="token string">"hello world"</span><span class="token punctuation">)</span><span class="token comment">// immediate dangling</span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">char</span> ch <span class="token operator">:</span> ec<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        std<span class="token double-colon punctuation">::</span><span class="token function">print</span><span class="token punctuation">(</span>ch<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p><span>This specific immediately dangling example is fixed by implicit constant initialization since the parameter </span><code>s</code><span> expects a </span><code>const std::string&amp;</code><span> and it was constant-initialized.</span></p><p><span>It should be noted too that the current rules of temporaries discourages the use of temporaries because of the dangling it introduces. However, if the lifetime of temporaries was increased to a reasonable degree than programmers would use temporaries more. This would reduce dangling further because there would be fewer named variables that could be propagated outside of their containing scope. This would also improve code clarity by reducing the number of lines of code allowing any remaining dangling to be more clearly seen.</span></p><h2 id="Proposed-Wording" data-id="Proposed-Wording"><a class="anchor hidden-xs" href="#Proposed-Wording" title="Proposed-Wording"><span class="octicon octicon-link"></span></a><span>Proposed Wording</span></h2><p><strong><span>6.7.5.4 Automatic storage duration [basic.stc.auto]</span></strong></p><p><sub><span>1</span></sub><span> Variables that belong to a block or parameter scope and are not explicitly declared static, thread_local, </span><s><span>or</span></s><span> extern </span><ins><span>or had not underwent implicit constant initialization (6.9.3.2)</span></ins><span> have automatic storage duration. The storage for these entities lasts until the block in which they are created exits.</span></p><p><span>…</span></p><p><strong><span>6.9.3.2 Static initialization [basic.start.static]</span></strong></p><p><span>…</span></p><p><sub><span>2</span></sub><span> Constant initialization is performed </span><ins><span>explicitly</span></ins><span> if a variable or temporary object with static or thread storage duration is constant-initialized (7.7). </span><ins><span>Constant initialization is performed implicitly if a non mutable const variable or non mutable const temporary object is constant-initialized (7.7).</span></ins><span> If constant initialization is not performed, a variable with static storage duration (6.7.5.2) or thread storage duration (6.7.5.3) is zero-initialized (9.4). Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization. All static initialization strongly happens before (6.9.2.2) any dynamic initialization.</span></p><p><span>…</span></p><p><strong><span>9.2.7 The constinit specifer [dcl.constinit]</span></strong></p><p><sub><span>1</span></sub><span> </span><ins><span>If the constinit specifer is applied to a temporary, it gives the temporary static storage duration, asserts that the argument is a </span><code>LiteralType</code><span> and asserts that the parameter type is not </span><code>mutable</code><span> and </span><code>const</code><span> otherwise</span></ins><span> the constinit specifer shall be applied only to a declaration of a variable with static or thread storage duration. If the specifer is applied to any declaration of a variable, it shall be applied to the initializing declaration. No diagnostic is required if no constinit declaration is reachable at the point of the initializing declaration.</span></p><p><span>…</span></p><p><span style="color:red"><strong><span>NOTE: Wording still need to capture that these temporaries are no longer temporaries and that their value category is </span><code>lvalue</code><span>.</span></strong></span></p><h2 id="In-Depth-Rationale" data-id="In-Depth-Rationale"><a class="anchor hidden-xs" href="#In-Depth-Rationale" title="In-Depth-Rationale"><span class="octicon octicon-link"></span></a><span>In Depth Rationale</span></h2><p><span>There is a general expectation across programming languages that constants or more specifically constant literals are “immutable values which are known at compile time and do not change for the life of the program”.  </span><sup class="footnote-ref"><a href="#fn9" id="fnref9">[9]</a></sup><span> In most programming languages or rather the most widely used programming languages, constants do not dangle. Constants are so simple, so trivial (English wise), that it is shocking to even have to be conscience of dangling. This is shocking to </span><code>C++</code><span> beginners, expert programmers from other programming languages who come over to </span><code>C++</code><span> and at times even shocking to experienced </span><code>C++</code><span> programmers.</span></p><p><span>There is already significant interest in this type of feature from programmers. Just look at </span><code>C23</code><span> as an example. For instance, the </span><code>Introduce storage-class specifiers for compound literals</code><span> </span><sup class="footnote-ref"><a href="#fn10" id="fnref10">[10]</a></sup><span> and </span><code>The 'constexpr' specifier</code><sup class="footnote-ref"><a href="#fn11" id="fnref11">[11]</a></sup><span> allows </span><code>C</code><span> programmers to specify </span><code>static</code><span>, </span><code>constexpr</code><span> and </span><code>thread_local</code><span> as storage class specifiers on their compound literals. The compound literals equivalent in </span><code>C++</code><span> is </span><code>LiteralType</code><span> and temporaries. This paper reuses our existing keyword </span><code>constinit</code><span> over </span><code>static</code><span> because of what we all know from the </span><code>C++ Core Guidelines</code><sup class="footnote-ref"><a href="#fn12" id="fnref12">[12]</a></sup><span>.</span></p><table>
<tbody><tr>
<td>
<p><strong><span>I.2: Avoid non-const global variables</span></strong><sup class="footnote-ref"><a href="#fn12" id="fnref12:1">[12:1]</a></sup></p>
<p><strong><span>Reason</span></strong><span> Non-const global variables hide dependencies and make the dependencies subject to unpredictable changes.</span><sup class="footnote-ref"><a href="#fn12" id="fnref12:2">[12:2]</a></sup></p>
</td>
</tr>
</tbody></table><p><span>I also did not choose </span><code>constexpr</code><span>, though that may be better for greater </span><code>C</code><span> compatibility, since I wrote my proposals before my seeing the </span><code>C</code><span> paper. Also </span><code>constinit</code><span> better matches that which these features are doing in the context of existing </span><code>C++</code><span> terminology of constant initialization. Further, there are differences in what </span><code>constexpr</code><span> means to </span><code>C++</code><span> and </span><code>C</code><span>, at present.</span></p><p><span>It should also be noted that these concepts are already in the standard just not fully exposed in the language. For instance, strings literals already have static storage duration and attempting to modify one is undefined.</span></p><table>
<tbody><tr>
<td>
<p><code>Working Draft, Standard for Programming Language C++</code><span> </span><sup class="footnote-ref"><a href="#fn7" id="fnref7:4">[7:4]</a></sup></p>
<p><strong><span>“</span><em><span>5.13.5 String literals [lex.string]</span></em><span>”</span></strong></p>
<p><span>“</span><em><sub><span>9</span></sub><span> </span><strong><span>Evaluating a string-literal results in a string literal object with static storage duration</span></strong><span> (6.7.5). Whether all string-literals are distinct (that is, are stored in nonoverlapping objects) and whether successive evaluations of a string-literal yield the same or a diﬀerent object is unspecifed.</span></em><span>”</span></p>
<p><span>“</span><em><span>[Note 4: The effect of attempting to modify a string literal object is undefined. — end note]</span></em><span>”</span></p>
</td>
</tr>
</tbody></table><p><span>Further, this behavior happens all the time with evaluations of constant expressions but unfortunately we can’t enjoy all the benefits thereof.</span></p><table>
<tbody><tr>
<td>
<p><code>Working Draft, Standard for Programming Language C++</code><span> </span><sup class="footnote-ref"><a href="#fn7" id="fnref7:5">[7:5]</a></sup></p>
<p><span>“</span><em><strong><span>6.9.3.2 Static initialization [basic.start.static]</span></strong></em><span>”</span></p>
<p><span>“</span><em><sub><span>1</span></sub><span> Variables with static storage duration are initialized as a consequence of program initiation. Variables with thread storage duration are initialized as a consequence of thread execution. Within each of these phases of initiation, initialization occurs as follows.</span></em><span>”</span></p>
<p><span>“</span><em><sub><span>2</span></sub><span> Constant initialization is performed if a variable or temporary object with static or thread storage duration is constant-initialized (7.7). …</span></em><span>”</span></p>
<p><span>…</span></p>
<p><span>“</span><em><sub><span>3</span></sub><span> An implementation is permitted to perform the initialization of a variable with static or thread storage duration as a static initialization even if such initialization is not required to be done statically, provided that …</span></em><span>”</span></p>
</td>
</tr>
</tbody></table><p><span>These ROM-able instances do not dangle as globals but from our code perspective they currently look like dangling locals. This causes false positive with our static analyzers and the programmer’s themselves. If we would just admit from a language standpoint that these are indeed constants than not only do we fix some dangling but also our mental model. This same reference also says “constant initialization is performed if a … temporary object with static … storage duration is constant-initialized”. Programmers can’t fully utilize this scenario because at present we can only use </span><code>static</code><span> on class members and locals but not temporary arguments. Since the code identified by this paper is already subject to constant initialization than there is no real chance of these changes causing any breakage.</span></p><h2 id="Value-Categories" data-id="Value-Categories"><a class="anchor hidden-xs" href="#Value-Categories" title="Value-Categories"><span class="octicon octicon-link"></span></a><span>Value Categories</span></h2><p><span>If some temporaries can be changed to have global scope than how does it affect their value categories? Currently, if the literal is a string than it is a </span><code>lvalue</code><span> and it has global scope. For all the other literals, they tend to be a </span><code>prvalue</code><span> and have statement scope.</span></p><table>
<tbody><tr>
<td></td>
<td>
<p><strong><span>movable</span></strong></p>
</td>
<td>
<p><strong><span>unmovable</span></strong></p>
</td>
</tr>
<tr>
<td>
<p><strong><span>named</span></strong></p>
</td>
<td>xvalue</td>
<td>lvalue</td>
</tr>
<tr>
<td>
<p><strong><span>unnamed</span></strong></p>
</td>
<td>prvalue</td>
<td>?</td>
</tr>
</tbody></table><p><span>From the programmers perspective, global temporaries are just anonymously named variables. When they are passed as arguments, they have life beyond the life of the function that it is given to. As such the expression is not movable. As such, the desired behavior described throughout the paper is that they are </span><code>lvalues</code><span> which makes sense from a anonymously named standpoint. However, it must be said that technically they are unnamed which places them into the value category that </span><code>C++</code><span> currently does not have; the unmovable unnamed. The point is, this is simple whether it is worded as a </span><code>lvalue</code><span> or an unambiguous new value category that behaves like a </span><code>lvalue</code><span>. Regardless of which, there are some advantages that must be pointed out.</span></p><h3 id="Avoids-superfluous-moves" data-id="Avoids-superfluous-moves"><a class="anchor hidden-xs" href="#Avoids-superfluous-moves" title="Avoids-superfluous-moves"><span class="octicon octicon-link"></span></a><span>Avoids superfluous moves</span></h3><p><span>The proposed avoids superfluous moves. Copying pointers and lvalue references are cheaper than performing a move which is cheaper than performing any non trivial value copy.</span></p><h3 id="Undo-forced-naming" data-id="Undo-forced-naming"><a class="anchor hidden-xs" href="#Undo-forced-naming" title="Undo-forced-naming"><span class="octicon octicon-link"></span></a><span>Undo forced naming</span></h3><p><span>The proposed makes using types that delete their </span><code>rvalue</code><span> reference constructor easier to use. For instance, </span><code>std::reference_wrapper</code><span> can’t be created/reassigned with a </span><code>rvalue</code><span> reference, i.e. temporaries. Rather, it must be created/reassigned with a </span><code>lvalue</code><span> reference created on a seperate line. This requires superfluous naming which increases the chances of dangling. Further, according to the </span><code>C++ Core Guidelines</code><span>, it is developers practice to do the following:</span></p><ul>
<li><em><span>ES.5: Keep scopes small</span></em><span> [^cppcges5]</span></li>
<li><em><span>ES.6: Declare names in for-statement initializers and conditions to limit scope</span></em><span> [^cppcges6]</span></li>
</ul><pre><code class="cpp hljs"><span class="token comment">// currently not permitted; works as proposed</span>
std<span class="token double-colon punctuation">::</span>reference_wrapper<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> <span class="token function">rwi1</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// current forced usage</span>
<span class="token keyword">int</span> value1 <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">;</span>
std<span class="token double-colon punctuation">::</span>reference_wrapper<span class="token operator">&lt;</span><span class="token keyword">int</span><span class="token operator">&gt;</span> <span class="token function">rwi2</span><span class="token punctuation">(</span>value1<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">randomBool</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">int</span> value2 <span class="token operator">=</span> <span class="token number">7</span><span class="token punctuation">;</span><span class="token comment">// ES.5, ES.6</span>
    rwi2 <span class="token operator">=</span> <span class="token function">ref</span><span class="token punctuation">(</span>value2<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// dangles with block scope</span>
    rwi2 <span class="token operator">=</span> <span class="token function">ref</span><span class="token punctuation">(</span><span class="token number">7</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// ok, safe and easy with global scope proposal</span>
    rwi2 <span class="token operator">=</span> <span class="token number">7</span><span class="token punctuation">;</span><span class="token comment">// might make sense to add back direct assignment operator</span>
<span class="token punctuation">}</span>
<span class="token keyword">else</span>
<span class="token punctuation">{</span>
    <span class="token keyword">int</span> value3 <span class="token operator">=</span> <span class="token number">9</span><span class="token punctuation">;</span><span class="token comment">// ES.5, ES.6</span>
    rwi2 <span class="token operator">=</span> <span class="token function">ref</span><span class="token punctuation">(</span>value3<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// dangles with block scope</span>
    rwi2 <span class="token operator">=</span> <span class="token function">ref</span><span class="token punctuation">(</span><span class="token number">9</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// ok, safe and easy with global scope proposal</span>
    rwi2 <span class="token operator">=</span> <span class="token number">9</span><span class="token punctuation">;</span><span class="token comment">// might make sense to add back direct assignment operator</span>
<span class="token punctuation">}</span>
</code></pre><p><span>Since the variable </span><code>value2</code><span> and </span><code>value3</code><span> is likely to be created manually at block scope instead of variable scope, it can accidentally introduce more dangling. Constructing and reassigning with a </span><code>global scoped</code><span> </span><code>lvalue</code><span> temporary avoids these common dangling possibilities along with simplifying the code.</span></p><h2 id="Performance-Considerations" data-id="Performance-Considerations"><a class="anchor hidden-xs" href="#Performance-Considerations" title="Performance-Considerations"><span class="octicon octicon-link"></span></a><span>Performance Considerations</span></h2><p><span>There are at least three ways to provide a non dangling globalish constant.</span></p><ul>
<li><span>ROM i.e. hardware</span></li>
<li><code>const</code><span> and </span><code>static</code><span> i.e. </span><code>C++</code><span> language</span></li>
<li><span>assembly opcode with inline constant i.e. machine code level</span></li>
</ul><p><span>While the first two are addressable, the last one isn’t.</span></p><p><span>In the next three examples, the same assembly is produced regardless of whether the literal </span><code>5</code><span> was provided via a native literal, a </span><code>constexpr</code><span> or a </span><code>const</code><span> global. The following results were produced in </span><a href="https://godbolt.org/" target="_blank" rel="noopener"><span>Compiler Explorer</span></a><span> using both “</span><code>x86-64 clang (trunk) -std=c++20 -O3</code><span>” and “</span><code>x86-64 gcc (trunk) -std=c++20 -O3</code><span>”.</span></p><h3 id="values-that-are-logically-global-constants" data-id="values-that-are-logically-global-constants"><a class="anchor hidden-xs" href="#values-that-are-logically-global-constants" title="values-that-are-logically-global-constants"><span class="octicon octicon-link"></span></a><span>values that are [logically] global constants</span></h3><h4 id="local-constant-but-logically-a-global-constant" data-id="local-constant-but-logically-a-global-constant"><a class="anchor hidden-xs" href="#local-constant-but-logically-a-global-constant" title="local-constant-but-logically-a-global-constant"><span class="octicon octicon-link"></span></a><span>local constant but logically a global constant</span></h4><pre><code class="cpp hljs"><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">return</span> <span class="token number">5</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><pre><code class="assembly hljs"><span class="hljs-symbol">main:</span>                                   <span class="hljs-meta"># @main</span>
        <span class="hljs-keyword">mov</span>     eax, <span class="hljs-number">5</span>
        <span class="hljs-keyword">ret</span>
</code></pre><h4 id="constant-expression-ie-logically-a-global-constant" data-id="constant-expression-ie-logically-a-global-constant"><a class="anchor hidden-xs" href="#constant-expression-ie-logically-a-global-constant" title="constant-expression-ie-logically-a-global-constant"><span class="octicon octicon-link"></span></a><span>constant expression i.e. logically a global constant</span></h4><pre><code class="cpp hljs"><span class="token keyword">constexpr</span> <span class="token keyword">int</span> <span class="token function">return5</span><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">5</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">return</span> <span class="token function">return5</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><pre><code class="assembly hljs"><span class="hljs-symbol">main:</span>                                   <span class="hljs-meta"># @main</span>
        <span class="hljs-keyword">mov</span>     eax, <span class="hljs-number">5</span>
        <span class="hljs-keyword">ret</span>
</code></pre><h4 id="an-actual-global" data-id="an-actual-global"><a class="anchor hidden-xs" href="#an-actual-global" title="an-actual-global"><span class="octicon octicon-link"></span></a><span>an actual global</span></h4><pre><code class="cpp hljs"><span class="token keyword">const</span> <span class="token keyword">int</span> GLOBAL <span class="token operator">=</span> <span class="token number">5</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">return</span> GLOBAL<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><pre><code class="assembly hljs"><span class="hljs-symbol">main:</span>                                   <span class="hljs-meta"># @main</span>
        <span class="hljs-keyword">mov</span>     eax, <span class="hljs-number">5</span>
        <span class="hljs-keyword">ret</span>
</code></pre><p><span>The point is all three are logically non dangling, constant global. Now let’s look at reference examples.</span></p><h3 id="immediate-dangling" data-id="immediate-dangling"><a class="anchor hidden-xs" href="#immediate-dangling" title="immediate-dangling"><span class="octicon octicon-link"></span></a><span>immediate dangling</span></h3><p><span>Not only do all three following examples produce the exact same assembly, they also provide the exact same assembly as the previous three examples. They are all essentially global constants from the assembly and programmer standpoint but the current standard says two of the three dangle, unnecessarily.</span></p><h4 id="local-constant-but-logically-a-global-constant1" data-id="local-constant-but-logically-a-global-constant"><a class="anchor hidden-xs" href="#local-constant-but-logically-a-global-constant1" title="local-constant-but-logically-a-global-constant1"><span class="octicon octicon-link"></span></a><span>local constant but logically a global constant</span></h4><pre><code class="cpp hljs"><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">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> reflocal <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">;</span><span class="token comment">// immediate dangling</span>
    <span class="token keyword">return</span> reflocal<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><pre><code class="assembly hljs"><span class="hljs-symbol">main:</span>                                   <span class="hljs-meta"># @main</span>
        <span class="hljs-keyword">mov</span>     eax, <span class="hljs-number">5</span>
        <span class="hljs-keyword">ret</span>
</code></pre><pre><code class="cpp hljs"><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">const</span> <span class="token keyword">int</span> local <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> reflocal <span class="token operator">=</span> local<span class="token punctuation">;</span>
    <span class="token keyword">return</span> reflocal<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><pre><code class="assembly hljs"><span class="hljs-symbol">main:</span>                                   <span class="hljs-meta"># @main</span>
        <span class="hljs-keyword">mov</span>     eax, <span class="hljs-number">5</span>
        <span class="hljs-keyword">ret</span>
</code></pre><h4 id="constant-expression-ie-logically-a-global-constant1" data-id="constant-expression-ie-logically-a-global-constant"><a class="anchor hidden-xs" href="#constant-expression-ie-logically-a-global-constant1" title="constant-expression-ie-logically-a-global-constant1"><span class="octicon octicon-link"></span></a><span>constant expression i.e. logically a global constant</span></h4><pre><code class="cpp hljs"><span class="token keyword">constexpr</span> <span class="token keyword">int</span> <span class="token function">return5</span><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">5</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">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> reflocal <span class="token operator">=</span> <span class="token function">return5</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// immediate dangling</span>
    <span class="token keyword">return</span> reflocal<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><pre><code class="assembly hljs"><span class="hljs-symbol">main:</span>                                   <span class="hljs-meta"># @main</span>
        <span class="hljs-keyword">mov</span>     eax, <span class="hljs-number">5</span>
        <span class="hljs-keyword">ret</span>
</code></pre><h4 id="an-actual-global1" data-id="an-actual-global"><a class="anchor hidden-xs" href="#an-actual-global1" title="an-actual-global1"><span class="octicon octicon-link"></span></a><span>an actual global</span></h4><pre><code class="cpp hljs"><span class="token keyword">const</span> <span class="token keyword">int</span> GLOBAL <span class="token operator">=</span> <span class="token number">5</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">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> reflocal <span class="token operator">=</span> GLOBAL<span class="token punctuation">;</span>
    <span class="token keyword">return</span> reflocal<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><pre><code class="assembly hljs"><span class="hljs-symbol">main:</span>                                   <span class="hljs-meta"># @main</span>
        <span class="hljs-keyword">mov</span>     eax, <span class="hljs-number">5</span>
        <span class="hljs-keyword">ret</span>
</code></pre><h3 id="indirect-dangling-of-caller’s-local" data-id="indirect-dangling-of-caller’s-local"><a class="anchor hidden-xs" href="#indirect-dangling-of-caller’s-local" title="indirect-dangling-of-caller’s-local"><span class="octicon octicon-link"></span></a><span>indirect dangling of caller’s local</span></h3><p><span>Similarly to, the next three examples produce the same assembly in the 3 </span><code>clang</code><span> cases and 2 of the </span><code>gcc</code><span> cases. </span><code>GCC</code><span> would have produced the same result in its 2nd case had it had treated the </span><code>const</code><span> expected evaluation of a constant expression as a global constant as its third case did.</span></p><h4 id="local-constant-but-logically-a-global-constant2" data-id="local-constant-but-logically-a-global-constant"><a class="anchor hidden-xs" href="#local-constant-but-logically-a-global-constant2" title="local-constant-but-logically-a-global-constant2"><span class="octicon octicon-link"></span></a><span>local constant but logically a global constant</span></h4><pre><code class="cpp hljs"><span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> <span class="token function">potential_dangler</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> passthrough<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">return</span> passthrough<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">const</span> <span class="token keyword">int</span> local <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> reflocal <span class="token operator">=</span> <span class="token function">potential_dangler</span><span class="token punctuation">(</span>local<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> reflocal<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><pre><code class="assembly hljs">potential_dangler(<span class="hljs-keyword">int</span> const&amp;):               # @potential_dangler(<span class="hljs-keyword">int</span> const&amp;)
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">rax</span>, <span class="hljs-built_in">rdi</span>
        <span class="hljs-keyword">ret</span>
<span class="hljs-symbol">main:</span>                                   # @main
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">eax</span>, <span class="hljs-number">5</span>
        <span class="hljs-keyword">ret</span>
</code></pre><h4 id="constant-expression-ie-logically-a-global-constant2" data-id="constant-expression-ie-logically-a-global-constant"><a class="anchor hidden-xs" href="#constant-expression-ie-logically-a-global-constant2" title="constant-expression-ie-logically-a-global-constant2"><span class="octicon octicon-link"></span></a><span>constant expression i.e. logically a global constant</span></h4><pre><code class="cpp hljs"><span class="token keyword">constexpr</span> <span class="token keyword">int</span> <span class="token function">return5</span><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">5</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> <span class="token function">potential_dangler</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> passthrough<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">return</span> passthrough<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">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> reflocal <span class="token operator">=</span> <span class="token function">potential_dangler</span><span class="token punctuation">(</span><span class="token function">return5</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> reflocal<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><h5 id="x86-64-clang-trunk--stdc20--O3" data-id="x86-64-clang-trunk--stdc20--O3"><a class="anchor hidden-xs" href="#x86-64-clang-trunk--stdc20--O3" title="x86-64-clang-trunk--stdc20--O3"><span class="octicon octicon-link"></span></a><span>x86-64 clang (trunk) -std=c++20 -O3</span></h5><pre><code class="assembly hljs">potential_dangler(<span class="hljs-keyword">int</span> const&amp;):               # @potential_dangler(<span class="hljs-keyword">int</span> const&amp;)
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">rax</span>, <span class="hljs-built_in">rdi</span>
        <span class="hljs-keyword">ret</span>
<span class="hljs-symbol">main:</span>                                   # @main
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">eax</span>, <span class="hljs-number">5</span>
        <span class="hljs-keyword">ret</span>
</code></pre><h5 id="x86-64-gcc-trunk--stdc20--O3" data-id="x86-64-gcc-trunk--stdc20--O3"><a class="anchor hidden-xs" href="#x86-64-gcc-trunk--stdc20--O3" title="x86-64-gcc-trunk--stdc20--O3"><span class="octicon octicon-link"></span></a><span>x86-64 gcc (trunk) -std=c++20 -O3</span></h5><p><span style="color:red"><strong><span>NOTE: Can’t really say what GCC is doing with the </span><code>xor</code><span>. However, if GCC had treated the resolved constant expression which is const required as a const global as in the next example than the results would have been the same.</span></strong></span></p><pre><code class="assembly hljs">potential_dangler(<span class="hljs-keyword">int</span> const&amp;):
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">rax</span>, <span class="hljs-built_in">rdi</span>
        <span class="hljs-keyword">ret</span>
<span class="hljs-symbol">main:</span>
        <span class="hljs-keyword">xor</span>     <span class="hljs-built_in">eax</span>, <span class="hljs-built_in">eax</span>
        <span class="hljs-keyword">ret</span>
</code></pre><h4 id="an-actual-global2" data-id="an-actual-global"><a class="anchor hidden-xs" href="#an-actual-global2" title="an-actual-global2"><span class="octicon octicon-link"></span></a><span>an actual global</span></h4><pre><code class="cpp hljs"><span class="token keyword">const</span> <span class="token keyword">int</span> GLOBAL <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> <span class="token function">potential_dangler</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> passthrough<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">return</span> passthrough<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">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> reflocal <span class="token operator">=</span> <span class="token function">potential_dangler</span><span class="token punctuation">(</span>GLOBAL<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> reflocal<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><pre><code class="assembly hljs">potential_dangler(<span class="hljs-keyword">int</span> const&amp;):               # @potential_dangler(<span class="hljs-keyword">int</span> const&amp;)
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">rax</span>, <span class="hljs-built_in">rdi</span>
        <span class="hljs-keyword">ret</span>
<span class="hljs-symbol">main:</span>                                   # @main
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">eax</span>, <span class="hljs-number">5</span>
        <span class="hljs-keyword">ret</span>
</code></pre><p><span>In all these logically global constant cases, no instance was actually stored global but was perfectly inlined as an assembly opcode constant. So, the worst case performance of this proposal would be a single upfront load time cost. Contrast that with the current potential local constant cost of constantly creating and destroying instances, even multiple times concurrently in different threads. Even the proposed cost can go from 1 to 0 while the current non global local could result in superfluous dynamic allocations since </span><code>std::string</code><span> and </span><code>std::vector</code><span> are now </span><code>constexpr</code><span>.</span></p><h3 id="Microsoft’s-compiler-and-existing-dangling-detection" data-id="Microsoft’s-compiler-and-existing-dangling-detection"><a class="anchor hidden-xs" href="#Microsoft’s-compiler-and-existing-dangling-detection" title="Microsoft’s-compiler-and-existing-dangling-detection"><span class="octicon octicon-link"></span></a><span>Microsoft’s compiler and existing dangling detection</span></h3><p><span>Things really get interesting when we factor Microsoft’s compiler into the equation and contrast its dangling detection between optimized configurations.</span></p><p><strong><span>x64 msvc v19.latest</span></strong></p><h4 id="indirect-dangling-of-caller’s-local1" data-id="indirect-dangling-of-caller’s-local"><a class="anchor hidden-xs" href="#indirect-dangling-of-caller’s-local1" title="indirect-dangling-of-caller’s-local1"><span class="octicon octicon-link"></span></a><span>indirect dangling of caller’s local</span></h4><table>
<tbody><tr>
<td colspan="2">
<p><strong><span>temporary constant but logically a global constant</span></strong></p>
</td>
</tr>
<tr>
<td colspan="2">
<pre><code class="cpp hljs"><span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> <span class="token function">potential_dangler</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> passthrough<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">return</span> passthrough<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">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> reftemp <span class="token operator">=</span> <span class="token function">potential_dangler</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> reftemp<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<p><strong><span>/Ox optimizations (favor speed)</span></strong></p>
</td>
</tr>
<tr>
<td>
<pre><code class="assembly hljs">passthrough$ = <span class="hljs-number">8</span>
<span class="hljs-comment">; potential_dangler</span>
<span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;) PROC
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> [<span class="hljs-built_in">rsp</span>+<span class="hljs-number">8</span>], <span class="hljs-built_in">rcx</span>
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">rax</span>, <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> passthrough$[<span class="hljs-built_in">rsp</span>]
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
<span class="hljs-comment">; potential_dangler</span>
<span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;) ENDP

$T1 = <span class="hljs-number">32</span>
reftemp$ = <span class="hljs-number">40</span>
main    PROC
$LN3:
        <span class="hljs-keyword">sub</span>     <span class="hljs-built_in">rsp</span>, <span class="hljs-number">56</span><span class="hljs-comment">; 00000038H</span>
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">DWORD</span> <span class="hljs-built_in">PTR</span> $T1[<span class="hljs-built_in">rsp</span>], <span class="hljs-number">5</span>
        <span class="hljs-keyword">lea</span>     <span class="hljs-built_in">rcx</span>, <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> $T1[<span class="hljs-built_in">rsp</span>]
        <span class="hljs-comment">; potential_dangler</span>
        <span class="hljs-keyword">call</span>    <span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;)
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> reftemp$[<span class="hljs-built_in">rsp</span>], <span class="hljs-built_in">rax</span>
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">rax</span>, <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> reftemp$[<span class="hljs-built_in">rsp</span>]
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">eax</span>, <span class="hljs-built_in">DWORD</span> <span class="hljs-built_in">PTR</span> [<span class="hljs-built_in">rax</span>]
        <span class="hljs-keyword">add</span>     <span class="hljs-built_in">rsp</span>, <span class="hljs-number">56</span><span class="hljs-comment">; 00000038H</span>
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
main    ENDP
</code></pre>
</td>
<td>
<pre><code class="assembly hljs">passthrough$ = <span class="hljs-number">8</span>
<span class="hljs-comment">; potential_dangler</span>
<span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;) PROC
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">rax</span>, <span class="hljs-built_in">rcx</span>
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
<span class="hljs-comment">; potential_dangler</span>
<span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;) ENDP

main    PROC
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">eax</span>, <span class="hljs-number">5</span>
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
main    ENDP
</code></pre>
</td>
</tr>
</tbody></table><table>
<tbody><tr>
<td colspan="2">
<p><strong><span>local constant but logically a global constant</span></strong></p>
</td>
</tr>
<tr>
<td colspan="2">
<pre><code class="cpp hljs"><span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> <span class="token function">potential_dangler</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> passthrough<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">return</span> passthrough<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">const</span> <span class="token keyword">int</span> local <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> reflocal <span class="token operator">=</span> <span class="token function">potential_dangler</span><span class="token punctuation">(</span>local<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> reflocal<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<p><strong><span>/Ox optimizations (favor speed)</span></strong></p>
</td>
</tr>
<tr>
<td>
<pre><code class="assembly hljs">passthrough$ = <span class="hljs-number">8</span>
<span class="hljs-comment">; potential_dangler</span>
<span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;) PROC
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> [<span class="hljs-built_in">rsp</span>+<span class="hljs-number">8</span>], <span class="hljs-built_in">rcx</span>
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">rax</span>, <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> passthrough$[<span class="hljs-built_in">rsp</span>]
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
<span class="hljs-comment">; potential_dangler</span>
<span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;) ENDP

local$ = <span class="hljs-number">32</span>
reflocal$ = <span class="hljs-number">40</span>
main    PROC
$LN3:
        <span class="hljs-keyword">sub</span>     <span class="hljs-built_in">rsp</span>, <span class="hljs-number">56</span><span class="hljs-comment">; 00000038H</span>
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">DWORD</span> <span class="hljs-built_in">PTR</span> local$[<span class="hljs-built_in">rsp</span>], <span class="hljs-number">5</span>
        <span class="hljs-keyword">lea</span>     <span class="hljs-built_in">rcx</span>, <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> local$[<span class="hljs-built_in">rsp</span>]
        <span class="hljs-comment">; potential_dangler</span>
        <span class="hljs-keyword">call</span>    <span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;)
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> reflocal$[<span class="hljs-built_in">rsp</span>], <span class="hljs-built_in">rax</span>
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">rax</span>, <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> reflocal$[<span class="hljs-built_in">rsp</span>]
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">eax</span>, <span class="hljs-built_in">DWORD</span> <span class="hljs-built_in">PTR</span> [<span class="hljs-built_in">rax</span>]
        <span class="hljs-keyword">add</span>     <span class="hljs-built_in">rsp</span>, <span class="hljs-number">56</span><span class="hljs-comment">; 00000038H</span>
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
main    ENDP
</code></pre>
</td>
<td>
<pre><code class="assembly hljs">passthrough$ = <span class="hljs-number">8</span>
<span class="hljs-comment">; potential_dangler</span>
<span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;) PROC
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">rax</span>, <span class="hljs-built_in">rcx</span>
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
<span class="hljs-comment">; potential_dangler</span>
<span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;) ENDP

main    PROC
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">eax</span>, <span class="hljs-number">5</span>
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
main    ENDP
</code></pre>
</td>
</tr>
</tbody></table><table>
<tbody><tr>
<td colspan="2">
<p><strong><span>constant expression i.e. logically a global constant</span></strong></p>
</td>
</tr>
<tr>
<td colspan="2">
<pre><code class="cpp hljs"><span class="token keyword">constexpr</span> <span class="token keyword">int</span> <span class="token function">return5</span><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">5</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> <span class="token function">potential_dangler</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> passthrough<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">return</span> passthrough<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">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> reflocal <span class="token operator">=</span> <span class="token function">potential_dangler</span><span class="token punctuation">(</span><span class="token function">return5</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> reflocal<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<p><strong><span>/Ox optimizations (favor speed)</span></strong></p>
</td>
</tr>
<tr>
<td>
<pre><code class="assembly hljs"><span class="hljs-keyword">int</span> return5(void) PROC<span class="hljs-comment">; return5, COMDAT</span>
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">eax</span>, <span class="hljs-number">5</span>
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
<span class="hljs-keyword">int</span> return5(void) ENDP<span class="hljs-comment">; return5</span>

passthrough$ = <span class="hljs-number">8</span>
<span class="hljs-comment">; potential_dangler</span>
<span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;) PROC
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> [<span class="hljs-built_in">rsp</span>+<span class="hljs-number">8</span>], <span class="hljs-built_in">rcx</span>
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">rax</span>, <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> passthrough$[<span class="hljs-built_in">rsp</span>]
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
<span class="hljs-comment">; potential_dangler</span>
<span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;) ENDP

$T1 = <span class="hljs-number">32</span>
reflocal$ = <span class="hljs-number">40</span>
main    PROC
$LN3:
        <span class="hljs-keyword">sub</span>     <span class="hljs-built_in">rsp</span>, <span class="hljs-number">56</span><span class="hljs-comment">; 00000038H</span>
        <span class="hljs-keyword">call</span>    <span class="hljs-keyword">int</span> return5(void)<span class="hljs-comment">; return5</span>
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">DWORD</span> <span class="hljs-built_in">PTR</span> $T1[<span class="hljs-built_in">rsp</span>], <span class="hljs-built_in">eax</span>
        <span class="hljs-keyword">lea</span>     <span class="hljs-built_in">rcx</span>, <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> $T1[<span class="hljs-built_in">rsp</span>]
        <span class="hljs-comment">; potential_dangler</span>
        <span class="hljs-keyword">call</span>    <span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;)
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> reflocal$[<span class="hljs-built_in">rsp</span>], <span class="hljs-built_in">rax</span>
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">rax</span>, <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> reflocal$[<span class="hljs-built_in">rsp</span>]
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">eax</span>, <span class="hljs-built_in">DWORD</span> <span class="hljs-built_in">PTR</span> [<span class="hljs-built_in">rax</span>]
        <span class="hljs-keyword">add</span>     <span class="hljs-built_in">rsp</span>, <span class="hljs-number">56</span><span class="hljs-comment">; 00000038H</span>
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
main    ENDP
</code></pre>
</td>
<td>
<pre><code class="assembly hljs"><span class="hljs-keyword">int</span> return5(void) PROC<span class="hljs-comment">; return5, COMDAT</span>
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">eax</span>, <span class="hljs-number">5</span>
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
<span class="hljs-keyword">int</span> return5(void) ENDP<span class="hljs-comment">; return5</span>

passthrough$ = <span class="hljs-number">8</span>
<span class="hljs-comment">; potential_dangler</span>
<span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;) PROC
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">rax</span>, <span class="hljs-built_in">rcx</span>
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
<span class="hljs-comment">; potential_dangler</span>
<span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;) ENDP

main    PROC
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">eax</span>, <span class="hljs-number">5</span>
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
main    ENDP
</code></pre>
</td>
</tr>
</tbody></table><table>
<tbody><tr>
<td colspan="2">
<p><strong><span>an actual global</span></strong></p>
</td>
</tr>
<tr>
<td colspan="2">
<pre><code class="cpp hljs"><span class="token keyword">const</span> <span class="token keyword">int</span> GLOBAL <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> <span class="token function">potential_dangler</span><span class="token punctuation">(</span><span class="token keyword">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> passthrough<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">return</span> passthrough<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">const</span> <span class="token keyword">int</span><span class="token operator">&amp;</span> reflocal <span class="token operator">=</span> <span class="token function">potential_dangler</span><span class="token punctuation">(</span>GLOBAL<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> reflocal<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<p><strong><span>/Ox optimizations (favor speed)</span></strong></p>
</td>
</tr>
<tr>
<td>
<pre><code class="assembly hljs"><span class="hljs-keyword">int</span> const <span class="hljs-meta">GLOBAL</span> <span class="hljs-built_in">DD</span> <span class="hljs-number">05H</span><span class="hljs-comment">; GLOBAL</span>

passthrough$ = <span class="hljs-number">8</span>
<span class="hljs-comment">; potential_dangler</span>
<span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;) PROC
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> [<span class="hljs-built_in">rsp</span>+<span class="hljs-number">8</span>], <span class="hljs-built_in">rcx</span>
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">rax</span>, <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> passthrough$[<span class="hljs-built_in">rsp</span>]
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
<span class="hljs-comment">; potential_dangler</span>
<span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;) ENDP

reflocal$ = <span class="hljs-number">32</span>
main    PROC
$LN3:
        <span class="hljs-keyword">sub</span>     <span class="hljs-built_in">rsp</span>, <span class="hljs-number">56</span><span class="hljs-comment">; 00000038H</span>
        <span class="hljs-keyword">lea</span>     <span class="hljs-built_in">rcx</span>, OFFSET FLAT:<span class="hljs-keyword">int</span> const <span class="hljs-meta">GLOBAL</span>
        <span class="hljs-comment">; potential_dangler</span>
        <span class="hljs-keyword">call</span>    <span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;)
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> reflocal$[<span class="hljs-built_in">rsp</span>], <span class="hljs-built_in">rax</span>
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">rax</span>, <span class="hljs-built_in">QWORD</span> <span class="hljs-built_in">PTR</span> reflocal$[<span class="hljs-built_in">rsp</span>]
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">eax</span>, <span class="hljs-built_in">DWORD</span> <span class="hljs-built_in">PTR</span> [<span class="hljs-built_in">rax</span>]
        <span class="hljs-keyword">add</span>     <span class="hljs-built_in">rsp</span>, <span class="hljs-number">56</span><span class="hljs-comment">; 00000038H</span>
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
main    ENDP
</code></pre>
</td>
<td>
<pre><code class="assembly hljs">passthrough$ = <span class="hljs-number">8</span>
<span class="hljs-comment">; potential_dangler</span>
<span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;) PROC
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">rax</span>, <span class="hljs-built_in">rcx</span>
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
<span class="hljs-comment">; potential_dangler</span>
<span class="hljs-keyword">int</span> const &amp; potential_dangler(<span class="hljs-keyword">int</span> const &amp;) ENDP

main    PROC
        <span class="hljs-keyword">mov</span>     <span class="hljs-built_in">eax</span>, <span class="hljs-number">5</span>
        <span class="hljs-keyword">ret</span>     <span class="hljs-number">0</span>
main    ENDP
</code></pre>
</td>
</tr>
</tbody></table><p><span>In all four cases, when optimizations (favor speed) is turned on, the Microsoft compiler produced the same </span><strong><span>non dangling</span></strong><span> code regardless of whether it was an actual global, a local constant, a temporary constant or a constant expression evaluation. This is also the same that </span><code>GCC</code><span> and </span><code>Clang</code><span> was generating. To the </span><code>msvc</code><span> compiler’s credit, it not only detect functions that can potentially dangle but also executions that could as well. In all cases, it was a warning instead of an error. While the temporary constant and the constant expression evaluation is truly dangling when not optimized, it was not a compiler error. Further, the global example was incorrectly flagged as potentially dangling even though it new it was a global. Regardless the optimized compilation, fixed the dangling and removed the potentially dangling flag.</span></p><p><span>This proposal advocates standardizing an optimization that compiler’s are already doing and have been doing before </span><code>C++</code><span> got </span><code>constexpr</code><span> in the language. Fixing this type of dangling in this fashion is the best possible way because potentially invalid code becomes valid with no programmer intervention, it produces no errors, it is faster, uses less memory and produces smaller executable sizes. In short, the compiler/language already has all it needs to fix dangling constants. Compilers are already doing this but there is currently no verbiage in the standard that state that anonymous constants don’t dangle because they are logically a global constant. Adopting this proposal ensures programmers do not have to fix something that was never dangling in the first place even though the current language makes it look like it is, needlessly.</span></p><h2 id="Tooling-Opportunities" data-id="Tooling-Opportunities"><a class="anchor hidden-xs" href="#Tooling-Opportunities" title="Tooling-Opportunities"><span class="octicon octicon-link"></span></a><span>Tooling Opportunities</span></h2><p><span>There area a couple tooling opportunities especially with respect to the </span><code>constinit</code><span> specifier.</span></p><ul>
<li><span>A command line and/or IDE tool could analyze the code for </span><code>const</code><span>, </span><code>constexpr</code><span>/</span><code>LiteralType</code><span> and constant-initialized and if the conditions matches automatically add the </span><code>constinit</code><span> specifier for code reviewers.</span></li>
<li><span>Another command line and/or IDE tool could strip </span><code>constinit</code><span> specifier from any temporaries for programmers.</span></li>
</ul><p><span>Combined they would form a </span><code>constinit</code><span> toggle which wouldn’t be all that much different from whitespace and special character toggles already found in many IDE(s).</span></p><h2 id="Summary" data-id="Summary"><a class="anchor hidden-xs" href="#Summary" title="Summary"><span class="octicon octicon-link"></span></a><span>Summary</span></h2><p><span>The advantages to </span><code>C++</code><span> with adopting this proposal is manifold.</span></p><ul>
<li><span>Safer</span>
<ul>
<li><span>Eliminate dangling of what should be constants</span></li>
<li><span>Reduce immediate dangling when the instance is a constant</span></li>
<li><span>Reduce returning direct reference dangling when the instance is a constant</span></li>
<li><span>Reduce returning indirect reference dangling when the instance is a constant and was provided as an argument</span></li>
<li><span>Reduce indirect dangling that can occur in the body of a function</span></li>
<li><span>Reduce unitialized and delayed initialization errors</span></li>
<li><span>Increases safety by avoiding data races.</span></li>
</ul>
</li>
<li><span>Simpler</span>
<ul>
<li><span>Encourages the use of temporaries</span>
<ul>
<li><span>Reduce lines of code</span></li>
<li><span>Reduce naming; fewer names to return dangle</span></li>
</ul>
</li>
<li><span>Increases anonymously named </span><code>lvalues</code><span> and decreases </span><code>rvalues</code><span> in the code.</span>
<ul>
<li><span>Reduce lines of code</span></li>
<li><span>Reduce naming; fewer names to return dangle</span></li>
</ul>
</li>
<li><span>Make constexpr literals less surprising for new and old developers alike</span></li>
<li><span>Reduce the gap between </span><code>C++</code><span> and </span><code>C99</code><span> compound literals</span></li>
<li><span>Improve the potential contribution of </span><code>C++</code><span>'s dangling resolutions back to </span><code>C</code></li>
<li><span>Make string literals and </span><code>C++</code><span> literals more consistent with one another</span></li>
<li><span>Taking a step closer to reducing undefined behavior in string literals</span></li>
<li><span>Simplify the language to match existing practice</span></li>
<li><span>Consequently, a “cleanup”, i.e. adoption of simpler, more general rules/guidelines</span></li>
</ul>
</li>
<li><span>Faster &amp; More Memory Efficient</span>
<ul>
<li><span>Reduce unnecessary heap allocations</span></li>
<li><span>Increase and improve upon the utilization of ROM and the benefits that entails</span></li>
</ul>
</li>
</ul><h2 id="Frequently-Asked-Questions" data-id="Frequently-Asked-Questions"><a class="anchor hidden-xs" href="#Frequently-Asked-Questions" title="Frequently-Asked-Questions"><span class="octicon octicon-link"></span></a><span>Frequently Asked Questions</span></h2><h3 id="What-about-locality-of-reference" data-id="What-about-locality-of-reference"><a class="anchor hidden-xs" href="#What-about-locality-of-reference" title="What-about-locality-of-reference"><span class="octicon octicon-link"></span></a><span>What about locality of reference?</span></h3><p><span>It is true that globals can be slower than locals because they are farther in memory from the code that uses them. So let me clarify, when I say </span><code>static storage duration</code><span>, I really mean </span><strong><span>logically</span></strong><span> </span><code>static storage duration</code><span>. If a type is a </span><code>PODType</code><span>/</span><code>TrivialType</code><span> or </span><code>LiteralType</code><span> than there is nothing preventing the compiler from copying the global to a local that is closer to the executing code. Rather, the compiler </span><strong><span>must</span></strong><span> ensure that the instance is always available; </span><strong><span>effectively</span></strong><span> </span><code>static storage duration</code><span>.</span></p><p><span>Consider this from an processor and assembly/machine language standpoint. A processor usually has instructions that works with memory. Whether that memory is ROM or is logically so because it is never written to by a program, then we have constants.</span></p><pre><code class="cpp hljs">mov <span class="token operator">&lt;</span><span class="token keyword">register</span><span class="token operator">&gt;</span><span class="token punctuation">,</span><span class="token operator">&lt;</span>memory<span class="token operator">&gt;</span>
</code></pre><p><span>A processor may also have specialized versions of common instructions where a constant value is taken as part of the instruction itself. This too is a constant. However, this constant is guaranteed closer to the code because it is physically a part of it.</span></p><pre><code class="cpp hljs">mov <span class="token operator">&lt;</span><span class="token keyword">register</span><span class="token operator">&gt;</span><span class="token punctuation">,</span><span class="token operator">&lt;</span>constant<span class="token operator">&gt;</span>
mov <span class="token operator">&lt;</span>memory<span class="token operator">&gt;</span><span class="token punctuation">,</span><span class="token operator">&lt;</span>constant<span class="token operator">&gt;</span>
</code></pre><p><span>What is more interesting is these two examples of constants have different value categories since the ROM version is addressable and the instruction only version, clearly, is not. It should also be noted that the later unnamed/unaddressable version physically can’t dangle.</span></p><h3 id="Won’t-this-break-a-lot-of-existing-code" data-id="Won’t-this-break-a-lot-of-existing-code"><a class="anchor hidden-xs" href="#Won’t-this-break-a-lot-of-existing-code" title="Won’t-this-break-a-lot-of-existing-code"><span class="octicon octicon-link"></span></a><span>Won’t this break a lot of existing code?</span></h3><p><span>NO, if any. To the contrary, code that is broken is now fixed. Code that would be invalid is now valid, makes sense and can be rationally explained. Let me summarize:</span></p><p><span>This feature not only changes the point of destruction but also the point of construction. Instances that were of automatic storage duration, are now of static storage duration. Instances that were temporaries, are no longer temporaries. Surely, something must be broken! From the earlier section “Present”, subsection “C Standard Compound Literals”. Even the </span><code>C++</code><span> standard recognized that their are other opportunities for constant initialization.</span></p><table>
<tbody><tr>
<td>
<p><code>Working Draft, Standard for Programming Language C++</code><span> </span><sup class="footnote-ref"><a href="#fn7" id="fnref7:6">[7:6]</a></sup></p>
<p><strong><span>“</span><em><span>6.9.3.2 Static initialization [basic.start.static]</span></em><span>”</span></strong></p>
<p><span>“</span><em><span>3 An implementation is permitted to perform the initialization of a variable with static or thread storage duration as a static initialization even if such initialization is not required to be done statically …</span></em><span>”</span></p>
</td>
</tr>
</tbody></table><p><span>So, what is the point? For the instances that would benefit from implicit constant initialization, their are currently NO guarantees as far as their lifetime and as such is indeterminite. With this portion of the proposal, a guarantee is given and as such that which was non determinite becomes determinite.</span></p><p><span>It should also be noted that while this enhancement is applied implicitly, programmers has opted into this up to three times.</span></p><ol>
<li><span>The programmer of the type must have provided a means for the type to be constructed at compile time likely by having a </span><code>constexpr</code><span> constructor.</span></li>
<li><span>The programmer of the variable or function parameter must have stated that they want a </span><code>const</code><span>.</span></li>
<li><span>The end programmer have </span><code>const-initialized</code><span> the variable or argument.</span></li>
</ol><p><span>Having expressed contant requirements three times, it is pretty certain that the end programmer wanted a constant, even if it is anonymous.</span></p><h3 id="Who-would-even-use-these-features-Their-isn’t-sufficient-use-to-justify-these-changes" data-id="Who-would-even-use-these-features-Their-isn’t-sufficient-use-to-justify-these-changes"><a class="anchor hidden-xs" href="#Who-would-even-use-these-features-Their-isn’t-sufficient-use-to-justify-these-changes" title="Who-would-even-use-these-features-Their-isn’t-sufficient-use-to-justify-these-changes"><span class="octicon octicon-link"></span></a><span>Who would even use these features? Their isn’t sufficient use to justify these changes.</span></h3><p><span>Everyone … Quite a bit, actually</span></p><p><span>Consider all the examples littered throughout our history, these are what gets fixed.</span></p><ul>
<li><span>dangling reported on normal use of the </span><code>STL</code></li>
<li><span>dangling examples reported in the </span><code>C++</code><span> standard</span></li>
<li><span>real world dangling reported in NAD, not a defect, reports</span></li>
</ul><p><span>This doesn’t even include the countless examples found in numerous articles comparing </span><code>C++</code><span> with other nameless programming languages which would be fixed. However, the best proof can be found in our usage and other proposals.</span></p><table>
<tbody><tr>
<td>
<p><code>C++ Core Guidelines</code><span> </span><sup class="footnote-ref"><a href="#fn13" id="fnref13">[13]</a></sup></p>
<p><em><strong><span>F.16: For “in” parameters, pass</span></strong><span> cheaply-copied types by value and others </span><strong><span>by reference to const</span></strong></em></p>
</td>
</tr>
</tbody></table><p><span>In </span><code>C++</code><span>, we use </span><code>const</code><span> parameters alot. This is the first of three requirements of </span><code>implicit constant initialization</code><span>. What about the use of types that can be constructed at compile time?</span></p><ul>
<li><strong><code>C++20</code></strong><span>: </span><code>std::pair</code><span>, </span><code>std::tuple</code><span>, </span><code>std::string</code><span>, </span><code>std::vector</code></li>
<li><strong><code>C++23</code></strong><span>: </span><code>std::optional</code><span>, </span><code>std::variant</code><span>, </span><code>std::unique_ptr</code></li>
</ul><p><span>As their was sufficient use to justify making the constructors of any one of these listed above types to be </span><code>constexpr</code><span> than their would be sufficient use of the </span><code>implicit constant initialization</code><span> feature which would use them all as this satisfies its second and third requirement that the instances be constructable at compile time and </span><code>constant-initialized</code><span>.</span></p><h3 id="Why-not-just-use-a-static-analyzer" data-id="Why-not-just-use-a-static-analyzer"><a class="anchor hidden-xs" href="#Why-not-just-use-a-static-analyzer" title="Why-not-just-use-a-static-analyzer"><span class="octicon octicon-link"></span></a><span>Why not just use a static analyzer?</span></h3><p><span>Typically a static analyzer doesn’t fix code. Instead, it just produces warnings and errors. It is the programmer’s responsibility to fix code by deciding whether the incident was a false positive or not and making the corresponding code changes. This proposal does fix some dangling but others go unresolved and unidentified. As such this proposal and static analyzers are complimentary. Combined this proposal can fix some dangling and a static analyzer could be used to identify what is remaining. As such those who still ask, “why not just use a static analyzer”, might really be saying </span><strong><span>this proposal’s language enhancements might break their static analyzer</span></strong><span>. To which I say, the standard dictates the analyzer, not the other way around. That is true for all tools. However, let’s explore the potential impact of this proposal on static analyzers.</span></p><p><span>The </span><code>C++</code><span> language is complex. It stands to reason that our tools would have some degree of complexity, since they would need to take some subset of our language’s rules into consideration. In any proposal, mine included, fixes to any dangling would result in potential dangling incidents becoming false positives between those identified by a static analyzer that overlap with said proposal. The false positives would join those that a static analyzer already has for not factoring existing language rules into consideration just as it would for any new language rules.</span></p><p><span>With </span><code>implicit constant initialization</code><span>, existing static analyzers would need to be enhanced to track the </span><code>const</code><span>ness of variables and parameters, whether or not the types of variables and parameters can be constructed at compile time and whether or not instances were constant-initialized. Until that happens, an existing dangling incident reported by static analyzer will just be a false positive. The total number of incidents remain the same and the programmer just need to recognize that it was a false positive which should be easy to do since constants are trivial and these rules are simple.</span></p><h3 id="Can-this-even-be-implemented" data-id="Can-this-even-be-implemented"><a class="anchor hidden-xs" href="#Can-this-even-be-implemented" title="Can-this-even-be-implemented"><span class="octicon octicon-link"></span></a><span>Can this even be implemented?</span></h3><p><code>C++</code><span> already provides static storage duration guarantee for instances of one type and allows it for many others.</span></p><ul>
<li><span>native string literals already have static storage duration</span></li>
<li><span>compilers have been free for a long time to promote compile time constructed instances to have static storage duration</span></li>
<li><span>any </span><code>LiteralType</code><span> instances that are constant-initialized are already prime candidates for compilers to promote to having static storage duration</span></li>
</ul><h3 id="Doesn’t-the-implicit-constant-initialization-feature-make-it-harder-for-programmers-to-identify-dangling-and-thus-harder-to-teach" data-id="Doesn’t-the-implicit-constant-initialization-feature-make-it-harder-for-programmers-to-identify-dangling-and-thus-harder-to-teach"><a class="anchor hidden-xs" href="#Doesn’t-the-implicit-constant-initialization-feature-make-it-harder-for-programmers-to-identify-dangling-and-thus-harder-to-teach" title="Doesn’t-the-implicit-constant-initialization-feature-make-it-harder-for-programmers-to-identify-dangling-and-thus-harder-to-teach"><span class="octicon octicon-link"></span></a><span>Doesn’t the </span><code>implicit constant initialization</code><span> feature make it harder for programmers to identify dangling and thus harder to teach?</span></h3><p><span>If there was no dangling than there would be nothing to teach with respect to any dangling feature. Even the whole standard is not taught. So the more dangling we fix in the language, the less dangling that has to be taught to beginners. Consider the following example, does the new features make it easier or harder to identify dangling?</span></p><pre><code class="cpp hljs"><span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// implicit constant initialization</span>
<span class="token comment">// vs.</span>
<span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">{</span>i<span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// no implicit constant initialization</span>
</code></pre><p><span>It is plain to see that </span><code>{1,2}</code><span> is constant-initialized as it is composed entirely of </span><code>LiteralType</code><span>(s). It is also plain to see that </span><code>{i,2}</code><span> is modifiable as its initialization statement is variable and dynamic due to the variable </span><code>i</code><span>. So the real questions are as follows:</span></p><ul>
<li><span>Is the first parameter to the function </span><code>f</code><span> const?</span></li>
<li><span>Is the type of the first parameter to the function </span><code>f</code><span> a </span><code>LiteralType</code><span>?</span></li>
</ul><p><span>The fact is some programmer had to have known the answer to both questions in order to have writtern  </span><code>f({1,2})</code><span> in the first place. The case could be made that it would be nice to be able to use the </span><code>constinit</code><span> keyword on temporary arguments, </span><code>f(constinit {1, 2})</code><span>, as this would allow those who don’t write the code, such as code reviewers, to quickly validate the code. Even the programmer would benefit, some, if the code was copied. However, </span><code>constinit</code><span> would mostly be superfluous, if the </span><code>temporaries are just anonymously named variables</code><span> feature is added. As such, </span><code>constinit</code><span> should be optional. Consequently, any negative impact upon identifying and teaching dangling is negligible.</span></p><p><span>Yet, both </span><code>implicit and explicit constant initialization</code><span> feature, by itself, makes it easier to identify and teach dangling.</span></p><p><strong><span>C++ Core Guidelines</span></strong><br><strong><span>F.43: Never (directly or indirectly) return a pointer or a reference to a local object</span></strong><span> </span><sup class="footnote-ref"><a href="#fn6" id="fnref6:3">[6:3]</a></sup></p><p><span>…</span></p><p><em><strong><span>Note</span></strong><span> This applies only to non-static local variables. All static variables are (as their name indicates) statically allocated, so that pointers to them cannot dangle.</span></em><span> </span><sup class="footnote-ref"><a href="#fn6" id="fnref6:4">[6:4]</a></sup></p><p><span>Instances that have static storage duration can’t dangle. Currently in </span><code>C++</code><span>, instances that don’t immediately dangle can still dangle later such as by returning. Using </span><code>static storage duration</code><span> short circuits the dangling identification process. An instance, once identified, doesn’t need to be factored into any additional dangling decision making process. Using more </span><code>static storage duration</code><span> speeds up the dangling identification process. This would also be of benefit to static analyzers that goes through a similar thought process.</span></p><h3 id="Doesn’t-this-make-C-harder-to-teach" data-id="Doesn’t-this-make-C-harder-to-teach"><a class="anchor hidden-xs" href="#Doesn’t-this-make-C-harder-to-teach" title="Doesn’t-this-make-C-harder-to-teach"><span class="octicon octicon-link"></span></a><span>Doesn’t this make C++ harder to teach?</span></h3><p><span>Until the day that all dangling gets fixed, any incremental fixes to dangling still would require programmers to be able to identify any remaining dangling and know how to fix it specific to the given scenario, as there are multiple solutions. Since dangling occurs even for things as simple as constants and immediate dangling is so naturally easy to produce, </span><!--than--><span> dangling resolution still have to be taught, even to beginners. As this proposal fixes these types of dangling, it makes teaching </span><code>C++</code><span> easier because it makes </span><code>C++</code><span> easier.</span></p><p><span>So, what do we teach now and what bearing does these teachings, the </span><code>C++</code><span> standard and this proposal have on one another.</span></p><p><strong><span>C++ Core Guidelines</span></strong><br><strong><span>F.42: Return a </span><code>T*</code><span> to indicate a position (only)</span></strong><span> </span><sup class="footnote-ref"><a href="#fn12" id="fnref12:3">[12:3]</a></sup><br><em><strong><span>Note</span></strong><span> Do not return a pointer to something that is not in the caller’s scope; see F.43.</span></em><span> </span><sup class="footnote-ref"><a href="#fn6" id="fnref6:5">[6:5]</a></sup></p><p><span>Returning references to something in the caller’s scope is only natural. It is a part of our reference delegating programming model. A function when given a reference does not know how the instance was created and it doesn’t care as long as it is good for the life of the function call (and beyond).  Unfortunately, scoping temporary arguments to the statement instead of the containing block doesn’t just create immediate dangling but it provides to functions references to instances that are near death. These instances are almost dead on arrival. Having the ability to return a reference to a caller’s instance or a sub-instance thereof assumes, correctly, that reference from the caller’s scope would still be alive after this function call. The fact that temporary rules shortened the life to the statement is at odds with what we teach. This proposal restores to some temporaries the lifetime of anonymously named constants which is not only natural but also consistent with what programmers already know. It is also in line with what we teach as was codified in the C++ Core Guidelines. One such is as follows:</span></p><p><strong><span>C++ Core Guidelines</span></strong><br><strong><span>F.43: Never (directly or indirectly) return a pointer or a reference to a local object</span></strong><span> </span><sup class="footnote-ref"><a href="#fn6" id="fnref6:6">[6:6]</a></sup></p><p><em><strong><span>Reason</span></strong><span> To avoid the crashes and data corruption that can result from the use of such a dangling pointer.</span></em><span> </span><sup class="footnote-ref"><a href="#fn6" id="fnref6:7">[6:7]</a></sup></p><p><span>Other than turning some of these locals into globals, this proposal does not solve nor contradict this teaching. If anything, by cleaning up the simple dangling it makes the remaining more visible.</span></p><p><span>Further, what is proposed is easy to teach because we already teach it and it makes </span><code>C++</code><span> even easier to teach.</span></p><ul>
<li><span>We already teach that native string literals don’t dangle because they have static storage duration. This proposal just extends the concept to constants, as expected. This increases good consistency and reduces a bifurcation that is currently taught.</span></li>
</ul><p><span>All of this can be done without adding any new keywords or any new attributes. We just use constant concepts that beginners are already familiar with. In fact, we will would be working in harmony with all that we already teach about globals in the </span><code>Core C++ Guidelines</code><span> </span><sup class="footnote-ref"><a href="#fn14" id="fnref14">[14]</a></sup><span>.</span></p><ul>
<li><code>I.2: Avoid non-const global variables</code><span> </span><sup class="footnote-ref"><a href="#fn12" id="fnref12:4">[12:4]</a></sup></li>
<li><code>I.22: Avoid complex initialization of global objects</code><span> </span><sup class="footnote-ref"><a href="#fn12" id="fnref12:5">[12:5]</a></sup></li>
<li><code>F.15: Prefer simple and conventional ways of passing information</code><span> </span><sup class="footnote-ref"><a href="#fn12" id="fnref12:6">[12:6]</a></sup></li>
<li><code>F.16: For “in” parameters, pass cheaply-copied types by value and others by reference to const</code><span> </span><sup class="footnote-ref"><a href="#fn12" id="fnref12:7">[12:7]</a></sup></li>
<li><code>F.43: Never (directly or indirectly) return a pointer or a reference to a local object</code><span> </span><sup class="footnote-ref"><a href="#fn6" id="fnref6:8">[6:8]</a></sup></li>
<li><code>R.5: Prefer scoped objects, don’t heap-allocate unnecessarily</code><span> </span><sup class="footnote-ref"><a href="#fn12" id="fnref12:8">[12:8]</a></sup></li>
<li><code>R.6: Avoid non-const global variables</code><span> </span><sup class="footnote-ref"><a href="#fn12" id="fnref12:9">[12:9]</a></sup></li>
<li><code>CP.2: Avoid data races</code><span> </span><sup class="footnote-ref"><a href="#fn12" id="fnref12:10">[12:10]</a></sup></li>
<li><code>CP.24: Think of a thread as a global container</code><span> </span><sup class="footnote-ref"><a href="#fn12" id="fnref12:11">[12:11]</a></sup></li>
<li><code>CP.32: To share ownership between unrelated threads use shared_ptr</code><span> </span><sup class="footnote-ref"><a href="#fn12" id="fnref12:12">[12:12]</a></sup></li>
</ul><h3 id="How-do-these-specifiers-propagate" data-id="How-do-these-specifiers-propagate"><a class="anchor hidden-xs" href="#How-do-these-specifiers-propagate" title="How-do-these-specifiers-propagate"><span class="octicon octicon-link"></span></a><span>How do these specifiers propagate?</span></h3><p><span>These specifiers apply to the temporary immediately to the right of said specifier and to any child temporaries. It does not impact any parent or sibling temporaries. Consider these examples:</span></p><pre><code class="cpp hljs"><span class="token comment">// all of the temporaries has the default temporary scope as</span>
<span class="token comment">// specified by the module attribute otherwise statement scope</span>
<span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token punctuation">{</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</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">// only 4 has constinit scope</span>
<span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token punctuation">{</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token keyword">constinit</span> <span class="token number">4</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</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">// only {2, 3}, 2, 3 has constinit scope</span>
<span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token keyword">constinit</span> <span class="token punctuation">{</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</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">// only { {2, 3}, 4}, {2, 3}, 2, 3, 4 has constinit scope</span>
<span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token keyword">constinit</span> <span class="token punctuation">{</span> <span class="token punctuation">{</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</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">// all of the arguments have has constinit scope</span>
<span class="token function">f</span><span class="token punctuation">(</span><span class="token keyword">constinit</span> <span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token punctuation">{</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</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">// only 5 has constinit scope</span>
<span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token punctuation">{</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token keyword">constinit</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><h2 id="References" data-id="References"><a class="anchor hidden-xs" href="#References" title="References"><span class="octicon octicon-link"></span></a><span>References</span></h2><hr class="footnotes-sep"><section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2658r0.html" target="_blank" rel="noopener"><span>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2658r0.html</span></a> <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn2" class="footnote-item"><p><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2623r2.html" target="_blank" rel="noopener"><span>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2623r2.html</span></a> <a href="#fnref2" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn3" class="footnote-item"><p><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2266r3.html" target="_blank" rel="noopener"><span>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2266r3.html</span></a> <a href="#fnref3" class="footnote-backref">↩︎</a> <a href="#fnref3:1" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn4" class="footnote-item"><p><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2012r2.pdf" target="_blank" rel="noopener"><span>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2012r2.pdf</span></a> <a href="#fnref4" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn5" class="footnote-item"><p><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2644r0.pdf" target="_blank" rel="noopener"><span>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2644r0.pdf</span></a> <a href="#fnref5" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn6" class="footnote-item"><p><a href="https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#f43-never-directly-or-indirectly-return-a-pointer-or-a-reference-to-a-local-object" target="_blank" rel="noopener"><span>https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#f43-never-directly-or-indirectly-return-a-pointer-or-a-reference-to-a-local-object</span></a> <a href="#fnref6" class="footnote-backref">↩︎</a> <a href="#fnref6:1" class="footnote-backref">↩︎</a> <a href="#fnref6:2" class="footnote-backref">↩︎</a> <a href="#fnref6:3" class="footnote-backref">↩︎</a> <a href="#fnref6:4" class="footnote-backref">↩︎</a> <a href="#fnref6:5" class="footnote-backref">↩︎</a> <a href="#fnref6:6" class="footnote-backref">↩︎</a> <a href="#fnref6:7" class="footnote-backref">↩︎</a> <a href="#fnref6:8" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn7" class="footnote-item"><p><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/n4910.pdf" target="_blank" rel="noopener"><span>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/n4910.pdf</span></a> <a href="#fnref7" class="footnote-backref">↩︎</a> <a href="#fnref7:1" class="footnote-backref">↩︎</a> <a href="#fnref7:2" class="footnote-backref">↩︎</a> <a href="#fnref7:3" class="footnote-backref">↩︎</a> <a href="#fnref7:4" class="footnote-backref">↩︎</a> <a href="#fnref7:5" class="footnote-backref">↩︎</a> <a href="#fnref7:6" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn8" class="footnote-item"><p><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0936r0.pdf" target="_blank" rel="noopener"><span>http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0936r0.pdf</span></a> <a href="#fnref8" class="footnote-backref">↩︎</a> <a href="#fnref8:1" class="footnote-backref">↩︎</a> <a href="#fnref8:2" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn9" class="footnote-item"><p><a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/constants" target="_blank" rel="noopener"><span>https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/constants</span></a> <a href="#fnref9" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn10" class="footnote-item"><p><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3038.htm" target="_blank" rel="noopener"><span>https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3038.htm</span></a> <a href="#fnref10" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn11" class="footnote-item"><p><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2917.pdf" target="_blank" rel="noopener"><span>https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2917.pdf</span></a> <a href="#fnref11" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn12" class="footnote-item"><p><a href="https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#glossary" target="_blank" rel="noopener"><span>https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#glossary</span></a> <a href="#fnref12" class="footnote-backref">↩︎</a> <a href="#fnref12:1" class="footnote-backref">↩︎</a> <a href="#fnref12:2" class="footnote-backref">↩︎</a> <a href="#fnref12:3" class="footnote-backref">↩︎</a> <a href="#fnref12:4" class="footnote-backref">↩︎</a> <a href="#fnref12:5" class="footnote-backref">↩︎</a> <a href="#fnref12:6" class="footnote-backref">↩︎</a> <a href="#fnref12:7" class="footnote-backref">↩︎</a> <a href="#fnref12:8" class="footnote-backref">↩︎</a> <a href="#fnref12:9" class="footnote-backref">↩︎</a> <a href="#fnref12:10" class="footnote-backref">↩︎</a> <a href="#fnref12:11" class="footnote-backref">↩︎</a> <a href="#fnref12:12" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn13" class="footnote-item"><p><a href="https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-in" target="_blank" rel="noopener"><span>https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-in</span></a> <a href="#fnref13" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn14" class="footnote-item"><p><a href="https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines" target="_blank" rel="noopener"><span>https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines</span></a> <a href="#fnref14" 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="#constant-dangling" title="constant dangling">constant dangling</a><ul class="nav">
<li><a href="#Table-of-contents" title="Table of contents">Table of contents</a></li>
<li><a href="#Changelog" title="Changelog">Changelog</a><ul class="nav">
<li><a href="#R0" title="R0">R0</a></li>
</ul>
</li>
<li><a href="#Abstract" title="Abstract">Abstract</a></li>
<li><a href="#Motivation" title="Motivation">Motivation</a></li>
<li><a href="#Motivating-Examples" title="Motivating Examples">Motivating Examples</a></li>
<li><a href="#Proposed-Wording" title="Proposed Wording">Proposed Wording</a></li>
<li><a href="#In-Depth-Rationale" title="In Depth Rationale">In Depth Rationale</a></li>
<li><a href="#Value-Categories" title="Value Categories">Value Categories</a><ul class="nav">
<li><a href="#Avoids-superfluous-moves" title="Avoids superfluous moves">Avoids superfluous moves</a></li>
<li><a href="#Undo-forced-naming" title="Undo forced naming">Undo forced naming</a></li>
</ul>
</li>
<li><a href="#Performance-Considerations" title="Performance Considerations">Performance Considerations</a><ul class="nav">
<li><a href="#values-that-are-logically-global-constants" title="values that are [logically] global constants">values that are [logically] global constants</a></li>
<li><a href="#immediate-dangling" title="immediate dangling">immediate dangling</a></li>
<li><a href="#indirect-dangling-of-caller’s-local" title="indirect dangling of caller’s local">indirect dangling of caller’s local</a></li>
<li><a href="#Microsoft’s-compiler-and-existing-dangling-detection" title="Microsoft’s compiler and existing dangling detection">Microsoft’s compiler and existing dangling detection</a></li>
</ul>
</li>
<li><a href="#Tooling-Opportunities" title="Tooling Opportunities">Tooling Opportunities</a></li>
<li><a href="#Summary" title="Summary">Summary</a></li>
<li><a href="#Frequently-Asked-Questions" title="Frequently Asked Questions">Frequently Asked Questions</a><ul class="nav">
<li><a href="#What-about-locality-of-reference" title="What about locality of reference?">What about locality of reference?</a></li>
<li><a href="#Won’t-this-break-a-lot-of-existing-code" title="Won’t this break a lot of existing code?">Won’t this break a lot of existing code?</a></li>
<li><a href="#Who-would-even-use-these-features-Their-isn’t-sufficient-use-to-justify-these-changes" title="Who would even use these features? Their isn’t sufficient use to justify these changes.">Who would even use these features? Their isn’t sufficient use to justify these changes.</a></li>
<li><a href="#Why-not-just-use-a-static-analyzer" title="Why not just use a static analyzer?">Why not just use a static analyzer?</a></li>
<li><a href="#Can-this-even-be-implemented" title="Can this even be implemented?">Can this even be implemented?</a></li>
<li><a href="#Doesn’t-the-implicit-constant-initialization-feature-make-it-harder-for-programmers-to-identify-dangling-and-thus-harder-to-teach" title="Doesn’t the implicit constant initialization feature make it harder for programmers to identify dangling and thus harder to teach?">Doesn’t the implicit constant initialization feature make it harder for programmers to identify dangling and thus harder to teach?</a></li>
<li><a href="#Doesn’t-this-make-C-harder-to-teach" title="Doesn’t this make C++ harder to teach?">Doesn’t this make C++ harder to teach?</a></li>
<li><a href="#How-do-these-specifiers-propagate" title="How do these specifiers propagate?">How do these specifiers propagate?</a></li>
</ul>
</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;" null null>
        <div class="toc"><ul class="nav">
<li><a href="#constant-dangling" title="constant dangling">constant dangling</a><ul class="nav">
<li><a href="#Table-of-contents" title="Table of contents">Table of contents</a></li>
<li><a href="#Changelog" title="Changelog">Changelog</a><ul class="nav">
<li><a href="#R0" title="R0">R0</a></li>
</ul>
</li>
<li><a href="#Abstract" title="Abstract">Abstract</a></li>
<li><a href="#Motivation" title="Motivation">Motivation</a></li>
<li><a href="#Motivating-Examples" title="Motivating Examples">Motivating Examples</a></li>
<li><a href="#Proposed-Wording" title="Proposed Wording">Proposed Wording</a></li>
<li><a href="#In-Depth-Rationale" title="In Depth Rationale">In Depth Rationale</a></li>
<li><a href="#Value-Categories" title="Value Categories">Value Categories</a><ul class="nav">
<li><a href="#Avoids-superfluous-moves" title="Avoids superfluous moves">Avoids superfluous moves</a></li>
<li><a href="#Undo-forced-naming" title="Undo forced naming">Undo forced naming</a></li>
</ul>
</li>
<li><a href="#Performance-Considerations" title="Performance Considerations">Performance Considerations</a><ul class="nav">
<li><a href="#values-that-are-logically-global-constants" title="values that are [logically] global constants">values that are [logically] global constants</a></li>
<li><a href="#immediate-dangling" title="immediate dangling">immediate dangling</a></li>
<li><a href="#indirect-dangling-of-caller’s-local" title="indirect dangling of caller’s local">indirect dangling of caller’s local</a></li>
<li><a href="#Microsoft’s-compiler-and-existing-dangling-detection" title="Microsoft’s compiler and existing dangling detection">Microsoft’s compiler and existing dangling detection</a></li>
</ul>
</li>
<li><a href="#Tooling-Opportunities" title="Tooling Opportunities">Tooling Opportunities</a></li>
<li><a href="#Summary" title="Summary">Summary</a></li>
<li><a href="#Frequently-Asked-Questions" title="Frequently Asked Questions">Frequently Asked Questions</a><ul class="nav">
<li><a href="#What-about-locality-of-reference" title="What about locality of reference?">What about locality of reference?</a></li>
<li><a href="#Won’t-this-break-a-lot-of-existing-code" title="Won’t this break a lot of existing code?">Won’t this break a lot of existing code?</a></li>
<li><a href="#Who-would-even-use-these-features-Their-isn’t-sufficient-use-to-justify-these-changes" title="Who would even use these features? Their isn’t sufficient use to justify these changes.">Who would even use these features? Their isn’t sufficient use to justify these changes.</a></li>
<li><a href="#Why-not-just-use-a-static-analyzer" title="Why not just use a static analyzer?">Why not just use a static analyzer?</a></li>
<li><a href="#Can-this-even-be-implemented" title="Can this even be implemented?">Can this even be implemented?</a></li>
<li><a href="#Doesn’t-the-implicit-constant-initialization-feature-make-it-harder-for-programmers-to-identify-dangling-and-thus-harder-to-teach" title="Doesn’t the implicit constant initialization feature make it harder for programmers to identify dangling and thus harder to teach?">Doesn’t the implicit constant initialization feature make it harder for programmers to identify dangling and thus harder to teach?</a></li>
<li><a href="#Doesn’t-this-make-C-harder-to-teach" title="Doesn’t this make C++ harder to teach?">Doesn’t this make C++ harder to teach?</a></li>
<li><a href="#How-do-these-specifiers-propagate" title="How do these specifiers propagate?">How do these specifiers propagate?</a></li>
</ul>
</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>
