<!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>
        auto(x): decay-copy in the language - 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>
        @charset "UTF-8";@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{display:block;background:#fff;padding:.5em;color:#333;overflow-x:auto}.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{color:#55a532;background-color:#eaffea}.hljs-deletion{color:#bd2c00;background-color:#ffecec}.hljs-link{text-decoration:underline}.markdown-body{font-size:16px;line-height:1.5;word-wrap:break-word}.markdown-body:after,.markdown-body:before{display:table;content:""}.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;padding-right:4px;margin-left:-20px;line-height:1}.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-top:0;margin-bottom:16px}.markdown-body hr{height:.25em;padding:0;margin:24px 0;background-color:#e7e7e7;border:0}.markdown-body blockquote{font-size:16px;padding:0 1em;color:#777;border-left:.25em solid #ddd}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body kbd,.popover kbd{display:inline-block;padding:3px 5px;font-size:11px;line-height:10px;color:#555;vertical-align:middle;background-color:#fcfcfc;border:1px solid #ccc;border-bottom-color:#bbb;border-radius:3px;box-shadow:inset 0 -1px 0 #bbb}.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{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.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{padding-bottom:.3em;border-bottom:1px solid #eee}.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{font-size:.85em;color:#777}.markdown-body ol,.markdown-body ul{padding-left:2em}.markdown-body ol.no-list,.markdown-body ul.no-list{padding:0;list-style-type:none}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-top:0;margin-bottom:0}.markdown-body li>p{margin-top:16px}.markdown-body li+li{padding-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:700}.markdown-body dl dd{padding:0 16px;margin-bottom:16px}.markdown-body table{display:block;width:100%;overflow:auto;word-break:normal;word-break:keep-all}.markdown-body table th{font-weight:700}.markdown-body table td,.markdown-body table th{padding:6px 13px;border:1px solid #ddd}.markdown-body table tr{background-color:#fff;border-top:1px solid #ccc}.markdown-body table tr:nth-child(2n){background-color:#f8f8f8}.markdown-body img{max-width:100%;box-sizing:content-box;background-color:#fff}.markdown-body img[align=right]{padding-left:20px}.markdown-body img[align=left]{padding-right:20px}.markdown-body .emoji{max-width:none;vertical-align:text-top;background-color:transparent}.markdown-body span.frame{display:block;overflow:hidden}.markdown-body span.frame>span{display:block;float:left;width:auto;padding:7px;margin:13px 0 0;overflow:hidden;border:1px solid #ddd}.markdown-body span.frame span img{display:block;float:left}.markdown-body span.frame span span{display:block;padding:5px 0 0;clear:both;color:#333}.markdown-body span.align-center{display:block;overflow:hidden;clear:both}.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{display:block;overflow:hidden;clear:both}.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{padding:0;padding-top:.2em;padding-bottom:.2em;margin:0;font-size:85%;background-color:rgba(0,0,0,.04);border-radius:3px}.markdown-body code:after,.markdown-body code:before,.markdown-body tt:after,.markdown-body tt:before{letter-spacing:-.2em;content:"\00a0"}.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{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:transparent;border:0}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f7f7f7;border-radius:3px}.markdown-body pre code,.markdown-body pre tt{display:inline;max-width:auto;padding:0;margin:0;overflow:visible;line-height:inherit;word-wrap:normal;background-color:transparent;border: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{padding:5px;overflow:hidden;font-size:12px;line-height:1;text-align:left;white-space:nowrap}.markdown-body .csv-data .blob-line-num{padding:10px 8px 9px;text-align:right;background:#fff;border:0}.markdown-body .csv-data tr{border-top:0}.markdown-body .csv-data th{font-weight:700;background:#f8f8f8;border-top:0}.news .alert .markdown-body blockquote{padding:0 0 0 40px;border:0 none}.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{float:left;margin:.31em 0 .2em -1.3em!important;vertical-align:middle;cursor:default!important}.markdown-body{padding-top:40px;padding-bottom:40px;max-width:758px;overflow:visible!important;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{text-align:right;position:relative;display:inline-block;cursor:default;z-index:4;padding:0 8px 0 0;min-width:20px;box-sizing:content-box;color:#afafaf!important;border-right:3px solid #6ce26c!important}.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-left:none;border-top:none;border-bottom:none}.markdown-body .gist .line-data{border:none}.markdown-body .gist table{border-spacing:0;border-collapse:inherit!important}.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{overflow:unset;margin-bottom: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{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{text-align:center;background-color:inherit;border-radius:0;white-space:inherit;overflow:visible}.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{max-width:100%;height:100%}.markdown-body pre>code.wrap{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}.markdown-body .alert>p,.markdown-body .alert>ul{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{cursor:pointer;display:table;text-align:center;background-position:50%;background-repeat:no-repeat;background-size:contain;background-color:#000;overflow:hidden}.vimeo,.youtube{position:relative;width:100%}.youtube{padding-bottom:56.25%}.vimeo img{width:100%;object-fit:contain;z-index:0}.youtube img{object-fit:cover;z-index:0}.vimeo iframe,.youtube iframe,.youtube img{width:100%;height:100%;position:absolute;top:0;left:0}.vimeo iframe,.youtube iframe{vertical-align:middle;z-index:1}.vimeo .icon,.youtube .icon{position:absolute;height:auto;width:auto;top:50%;left:50%;transform:translate(-50%,-50%);color:#fff;opacity:.3;transition:opacity .2s;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{position:absolute;top:0;bottom:0;left:0;right:0;width:100%;height:100%}.MJX_Assistive_MathML{display:none}#MathJax_Message{z-index:1000!important}.ui-infobar{position:relative;z-index:2;max-width:760px;margin:25px auto -25px;color:#777}.toc .invisable-node{list-style-type:none}.ui-toc{position:fixed;bottom:20px;z-index:998}.ui-toc.both-mode{margin-left:8px}.ui-toc.both-mode .ui-toc-label{height:40px;padding:10px 4px;border-top-left-radius:0;border-bottom-left-radius:0}.ui-toc-label{background-color:#e6e6e6;border:none;color:#868686;transition:opacity .2s}.ui-toc .open .ui-toc-label{opacity:1;color:#fff;transition:opacity .2s}.ui-toc-label:focus{opacity:.3;background-color:#ccc;color:#000}.ui-toc-label:hover{opacity:1;background-color:#ccc;transition:opacity .2s}.ui-toc-dropdown{margin-top:20px;margin-bottom:20px;padding-left:10px;padding-right:10px;max-width:45vw;width:25vw;max-height:70vh;overflow:auto;text-align:inherit}.ui-toc-dropdown>.toc{max-height:calc(70vh - 100px);overflow:auto}.ui-toc-dropdown[dir=rtl] .nav{padding-right:0;letter-spacing:.0029em}.ui-toc-dropdown a{overflow:hidden;text-overflow:ellipsis;white-space:pre}.ui-toc-dropdown .nav>li>a{display:block;padding:4px 20px;font-size:13px;font-weight:500;color:#767676}.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{padding-left:19px;color:#000;text-decoration:none;background-color:transparent;border-left:1px solid #000}.ui-toc-dropdown[dir=rtl] .nav>li>a:focus,.ui-toc-dropdown[dir=rtl] .nav>li>a:hover{padding-right:19px;border-left:none;border-right:1px solid #000}.ui-toc-dropdown .nav>.active:focus>a,.ui-toc-dropdown .nav>.active:hover>a,.ui-toc-dropdown .nav>.active>a{padding-left:18px;font-weight:700;color:#000;background-color:transparent;border-left:2px solid #000}.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{padding-right:18px;border-left:none;border-right:2px solid #000}.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{padding-top:1px;padding-bottom:1px;padding-left:30px;font-size:12px;font-weight:400}.ui-toc-dropdown[dir=rtl] .nav .nav>li>a{padding-right:30px}.ui-toc-dropdown .nav .nav>li>ul>li>a{padding-top:1px;padding-bottom:1px;padding-left:40px;font-size:12px;font-weight:400}.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{padding-left:28px;font-weight:500}.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{padding-left:38px;font-weight:500}.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}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}html[lang=zh-tw] .markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif}html[lang=zh-cn] .markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif}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}html .markdown-body[lang=zh-tw]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif}html .markdown-body[lang=zh-cn]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif}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{position:fixed;top:0;max-width:15vw;max-height:70vh;overflow:auto}.back-to-top,.expand-toggle,.go-to-bottom{display:block;padding:4px 10px;margin-top:10px;margin-left:10px;font-size:12px;font-weight:500;color:#999}.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{width:20px;height:20px;display:block;border-radius:50%;margin-top:2px;margin-bottom:2px;margin-right:5px;background-position:50%;background-repeat:no-repeat;background-size:cover}.ui-user-icon.small{width:18px;height:18px;display:inline-block;vertical-align:middle;margin:0 0 .2em}.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;text-decoration:none;padding-left:22px}.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}@media print{blockquote,div,img,pre,table{page-break-inside:avoid!important}a[href]:after{font-size:12px!important}}.markdown-body.slides{position:relative;z-index:1;color:#222}.markdown-body.slides:before{content:"";display:block;position:absolute;top:0;left:0;right:0;bottom:0;z-index:-1;background-color:currentColor;box-shadow:0 0 0 50vw}.markdown-body.slides section[data-markdown]{position:relative;margin-bottom:1.5em;background-color:#fff;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{position:absolute;top:50%;left:1em;right:1em;transform:translateY(-50%);max-height:100%;overflow:hidden}.markdown-body.slides section[data-markdown]>ul{display:inline-block}.markdown-body.slides>section>section+section:after{content:"";position:absolute;top:-1.5em;right:1em;height:1.5em;border:3px solid #777}.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;text-shadow:0 0 1em transparent,1px 1px 1.2px rgba(0,0,0,.004);-webkit-overflow-scrolling:touch;letter-spacing:.025em;font-family:Source Sans Pro,Helvetica,Arial,sans-serif}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}
    </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="true" style=""><style>
ins { background-color: #A0FFA0 }
s { background-color: #FFA0A0 }
blockquote { color: inherit !important }
</style><table><tbody>
<tr><th>Doc. no.:</th>    <td>P0849R7</td></tr>
<tr><th>Date:</th>        <td>2021-2-14</td></tr>
<tr><th>Audience:</th>    <td>LWG, EWG</td></tr>
<tr><th>Reply-to:</th>    <td>Zhihao Yuan &lt;zy at miator dot net&gt;</td></tr>
</tbody></table><h1 id="autox-decay-copy-in-the-language" data-id="autox-decay-copy-in-the-language" style=""><a class="anchor hidden-xs" href="#autox-decay-copy-in-the-language" title="autox-decay-copy-in-the-language"><span class="octicon octicon-link"></span></a><span>auto(x): </span><em><span>decay-copy</span></em><span> in the language</span></h1><h2 id="Changes-Since-R6" data-id="Changes-Since-R6" style=""><a class="anchor hidden-xs" href="#Changes-Since-R6" title="Changes-Since-R6"><span class="octicon octicon-link"></span></a><span>Changes Since R6</span></h2><ul>
<li><span>compare </span><code>decltype(auto(...))</code><span> with </span><code>decay_t</code></li>
<li><span>drop wording for LWG 3491; the author will propose its resolution separately</span></li>
<li><span>discuss other papers, </span><code>reference_constructs_from_temporary</code><span> and “deducing this”</span></li>
</ul><h2 id="Changes-Since-R5" data-id="Changes-Since-R5" style=""><a class="anchor hidden-xs" href="#Changes-Since-R5" title="Changes-Since-R5"><span class="octicon octicon-link"></span></a><span>Changes Since R5</span></h2><ul>
<li><span>discuss a few points that came across during EWG review</span></li>
<li><span>add a table to summarize the library wording</span></li>
</ul><h2 id="Changes-Since-R4" data-id="Changes-Since-R4" style=""><a class="anchor hidden-xs" href="#Changes-Since-R4" title="Changes-Since-R4"><span class="octicon octicon-link"></span></a><span>Changes Since R4</span></h2><ul>
<li><span>record LWG feedback</span></li>
<li><span>rebase and refine the wording</span></li>
<li><span>demo examples</span></li>
</ul><h2 id="Changes-Since-R3" data-id="Changes-Since-R3" style=""><a class="anchor hidden-xs" href="#Changes-Since-R3" title="Changes-Since-R3"><span class="octicon octicon-link"></span></a><span>Changes Since R3</span></h2><ul>
<li><span>complete library wording</span></li>
</ul><h2 id="Changes-Since-R2" data-id="Changes-Since-R2" style=""><a class="anchor hidden-xs" href="#Changes-Since-R2" title="Changes-Since-R2"><span class="octicon octicon-link"></span></a><span>Changes Since R2</span></h2><ul>
<li><span>dropped </span><code>decltype(auto)(x)</code><span> in comply with EWG’s opinion</span></li>
</ul><h2 id="Changes-Since-R1" data-id="Changes-Since-R1" style=""><a class="anchor hidden-xs" href="#Changes-Since-R1" title="Changes-Since-R1"><span class="octicon octicon-link"></span></a><span>Changes Since R1</span></h2><ul>
<li><span>propose </span><code>decltype(auto)(x)</code><span> as well</span></li>
</ul><h2 id="Changes-Since-R0" data-id="Changes-Since-R0" style=""><a class="anchor hidden-xs" href="#Changes-Since-R0" title="Changes-Since-R0"><span class="octicon octicon-link"></span></a><span>Changes Since R0</span></h2><ul>
<li><span>updated examples</span></li>
<li><span>discussed </span><code>decltype(auto)(x)</code></li>
<li><span>added library wording</span></li>
</ul><h2 id="Introduction" data-id="Introduction" style=""><a class="anchor hidden-xs" href="#Introduction" title="Introduction"><span class="octicon octicon-link"></span></a><span>Introduction</span></h2><p><span>This paper proposes </span><code>auto(x)</code><span> and </span><code>auto{x}</code><span> for casting </span><code>x</code><span> into a prvalue as if passing </span><code>x</code><span> as a function argument by value.  The functionality appears as the </span><em><code>decay-copy</code></em><span> function in the standard for exposition only.</span></p><h2 id="Motivation" data-id="Motivation" style=""><a class="anchor hidden-xs" href="#Motivation" title="Motivation"><span class="octicon octicon-link"></span></a><span>Motivation</span></h2><h3 id="Obtaining-a-prvalue-copy-is-necessary" data-id="Obtaining-a-prvalue-copy-is-necessary" style=""><a class="anchor hidden-xs" href="#Obtaining-a-prvalue-copy-is-necessary" title="Obtaining-a-prvalue-copy-is-necessary"><span class="octicon octicon-link"></span></a><span>Obtaining a prvalue copy is necessary</span></h3><p><span>A generic way to obtain a copy of an object in C++ is </span><code>auto a = x;</code><span> but such a copy is an lvalue.  We could often convey the purpose in code more accurately if we can obtain the copy as a prvalue.  In the following example, let </span><code>Container</code><span> be a concept,</span></p><pre><code class="c++ hljs"><span class="hljs-selector-tag">void</span> <span class="hljs-selector-tag">pop_front_alike</span>(<span class="hljs-selector-tag">Container</span> <span class="hljs-selector-tag">auto</span>&amp; <span class="hljs-selector-tag">x</span>) {
    <span class="hljs-attribute">std</span>::<span class="hljs-built_in">erase</span>(x.begin(), x.<span class="hljs-built_in">end</span>(), <span class="hljs-built_in">auto</span>(x.front()));
}
</code></pre><p><span>If we write</span></p><pre><code class="c++ hljs">void pop_front_alike(Container auto&amp; x) {
    auto a = x.front();
    std::erase(x.<span class="hljs-keyword">begin</span>(), x.<span class="hljs-keyword">end</span>(), a);
}
</code></pre><p><span>, questions arise – why this is not equivalent to</span></p><pre><code class="c++ hljs"><span class="hljs-selector-tag">void</span> <span class="hljs-selector-tag">pop_front_alike</span>(<span class="hljs-selector-tag">Container</span> <span class="hljs-selector-tag">auto</span>&amp; <span class="hljs-selector-tag">x</span>) {
    <span class="hljs-attribute">std</span>::<span class="hljs-built_in">erase</span>(x.begin(), x.<span class="hljs-built_in">end</span>(), x.<span class="hljs-built_in">front</span>());
}
</code></pre><p><span>The problem is, the statement to obtain an lvalue copy is a declaration:</span></p><pre><code class="c++ hljs">    <span class="hljs-attribute">auto</span> a = x.front();
</code></pre><p><span>The declaration’s primary purpose is to declare a variable, while the variable being a copy is the declaration’s property.  In contrast, the expression to obtain an rvalue copy is a clear command to perform a copy:</span></p><pre><code class="c++ hljs">    <span class="hljs-selector-tag">auto</span>(<span class="hljs-selector-tag">x</span><span class="hljs-selector-class">.front</span>())
</code></pre><p><span>One might argue that the above is indifferent from</span></p><pre><code class="c++ hljs">    <span class="hljs-selector-tag">T</span>(<span class="hljs-selector-tag">x</span><span class="hljs-selector-class">.front</span>())
</code></pre><p><span>However, there are plenty of situations that the </span><code>T</code><span> is nontrivial to get.  We probably don’t want to write the original example as</span></p><pre><code class="c++ hljs">void pop_front_alike(Container auto&amp; x) {
    using T = std::decay_t&lt;decltype(x.front())&gt;;
    std::erase(x.<span class="hljs-keyword">begin</span>(), x.<span class="hljs-keyword">end</span>(), T(x.front()));
}
</code></pre><h3 id="Obtaining-a-prvalue-copy-with-autox-works-always" data-id="Obtaining-a-prvalue-copy-with-autox-works-always" style=""><a class="anchor hidden-xs" href="#Obtaining-a-prvalue-copy-with-autox-works-always" title="Obtaining-a-prvalue-copy-with-autox-works-always"><span class="octicon octicon-link"></span></a><span>Obtaining a prvalue copy with </span><code>auto(x)</code><span> works always</span></h3><p><span>In standard library specification, we use the following exposition only function to fulfill </span><code>auto(x)</code><span>'s role:</span></p><pre><code class="c++ hljs">template&lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">T</span>&gt;</span>
constexpr decay_t&lt;T&gt; decay_copy(T&amp;&amp; v) noexcept(
    is_nothrow_convertible_v&lt;T, decay_t&lt;T<span class="hljs-meta">&gt;&gt;</span>) {
    return std::forward&lt;T&gt;(v);
}
</code></pre><p><span>This definition involves templates, dependent </span><code>constexpr</code><span>, forwarding reference, </span><code>noexcept</code><span>, and two traits, and still has caveats if people want to use it in practice.  An obvious issue is that </span><code>decay_copy(x.front())</code><span> copies </span><code>x.front()</code><span> even if </span><code>x.front()</code><span> is a prvalue, in other words, a copy.</span></p><p><span>There is a less obvious issue that needs a code snippet to reproduce:</span></p><pre><code class="c++ hljs"><span class="hljs-keyword">class</span> <span class="hljs-title">A</span> {
    <span class="hljs-keyword">int</span> x;

<span class="hljs-keyword">public</span>:
    A();

    <span class="hljs-function">auto <span class="hljs-title">run</span>(<span class="hljs-params"></span>) </span>{
        f(A(*<span class="hljs-keyword">this</span>));           <span class="hljs-comment">// ok</span>
        f(auto(*<span class="hljs-keyword">this</span>));        <span class="hljs-comment">// ok as proposed</span>
        f(decay_copy(*<span class="hljs-keyword">this</span>));  <span class="hljs-comment">// ill-formed</span>
    }

<span class="hljs-keyword">protected</span>:
    A(<span class="hljs-keyword">const</span> A&amp;);
};
</code></pre><p><span>The problem is that </span><code>decay_copy</code><span> is nobody’s </span><code>friend</code><span>.  We can use </span><code>A</code><span> directly in this specific example.  However, in a more general setting, where a type has access to a set of type </span><code>T</code><span>'s private or protected copy/move constructors, </span><em><code>decay-copy</code></em><span> an object of </span><code>T</code><span> fails inside that type’s class scope, but </span><code>auto(x)</code><span> continues to work.</span></p><h2 id="Discussion" data-id="Discussion" style=""><a class="anchor hidden-xs" href="#Discussion" title="Discussion"><span class="octicon octicon-link"></span></a><span>Discussion</span></h2><h3 id="autox-is-a-missing-piece" data-id="autox-is-a-missing-piece" style=""><a class="anchor hidden-xs" href="#autox-is-a-missing-piece" title="autox-is-a-missing-piece"><span class="octicon octicon-link"></span></a><code>auto(x)</code><span> is a missing piece</span></h3><p><span>Replacing the </span><code>char</code><span> in </span><code>char('a')</code><span> with </span><code>auto</code><span>, we obtain </span><code>auto('a')</code><span>, which is a function-style cast.  Such a formula also supports </span><em><span>injected-class-names</span></em><span> and class template argument deduction in C++17.  Introducing </span><code>auto(x)</code><span> and </span><code>auto{x}</code><span> significantly improves the language consistency:</span></p><table>
<thead>
<tr>
<th><span>variable definition</span></th>
<th><span>function-style cast</span></th>
<th><span>new expression</span></th>
</tr>
</thead>
<tbody>
<tr>
<td><span>auto v(x);</span></td>
<td><mark><span>auto(x)</span></mark></td>
<td><span>new auto(x)</span></td>
</tr>
<tr>
<td><span>auto v{x};</span></td>
<td><mark><span>auto{x}</span></mark></td>
<td><span>new auto{x}</span></td>
</tr>
<tr>
<td><span>ClassTemplate v(x);</span></td>
<td><span>ClassTemplate(x)</span></td>
<td><span>new ClassTemplate(x)</span></td>
</tr>
<tr>
<td><span>ClassTemplate v{x};</span></td>
<td><span>ClassTemplate{x}</span></td>
<td><span>new ClassTemplate{x}</span></td>
</tr>
</tbody>
</table><p><span>** </span><em><span>The type of </span><code>x</code><span> is a specialization of </span><code>ClassTemplate</code><span>.</span></em></p><p><span>With this proposal, all the cells in the table copy construct form </span><code>x</code><span> (due to CTAD’s default behavior) to obtain lvalues, prvalues, and pointers to objects, categorized by their columns.  Defining </span><code>auto(x)</code><span> as a library</span><sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup><span> facility loses orthogonality.</span></p><p><span>Introducing </span><code>auto(x)</code><span> into the language even improves the library consistency:</span></p><table>
<thead>
<tr>
<th><span>type function style</span></th>
<th><span>expression style</span></th>
</tr>
</thead>
<tbody>
<tr>
<td><span>void_t&lt;decltype(</span><em><span>expr</span></em><span>)&gt;</span></td>
<td><span>decltype(void(</span><em><span>expr</span></em><span>))</span></td>
</tr>
<tr>
<td><span>decay_t&lt;decltype(</span><em><span>expr</span></em><span>)&gt;</span></td>
<td><mark><span>decltype(auto(</span><em><span>expr</span></em><span>))</span></mark></td>
</tr>
</tbody>
</table><p><span>Note that </span><code><span>auto(</span><em><span>expr</span></em><span>)</span></code><span> does not turn a move-only lvalue </span><em><code>expr</code></em><span> into a prvalue regardless whether </span><code><span>auto(</span><em><span>expr</span></em><span>)</span></code><span> appears in an immediate context, so there is some </span><a href="#What%E2%80%99s-the-difference-between-decltypeautoexpr-and-decay_t"><span>difference</span></a><span> between </span><code><span>decltype(auto(</span><em><span>expr</span></em><span>))</span></code><span> and </span><code><span>decay_t&lt;decltype(</span><em><span>expr</span></em><span>)&gt;</span></code><span>.</span></p><h3 id="Do-we-also-miss-decltypeautox" data-id="Do-we-also-miss-decltypeautox" style=""><a class="anchor hidden-xs" href="#Do-we-also-miss-decltypeautox" title="Do-we-also-miss-decltypeautox"><span class="octicon octicon-link"></span></a><span>Do we also miss </span><code>decltype(auto){x}</code><span>?</span></h3><p><code>decltype(auto){arg}</code><span> can forward </span><code>arg</code><span> without computing </span><code>arg</code><span>'s type.  It is equivalent to </span><code>static_cast&lt;decltype(arg)&gt;(arg) </code><span>.  If </span><code>arg</code><span> is a variable of type </span><code>T&amp;&amp;</code><span>, </span><code>arg</code><span> is an lvalue but </span><code>static_cast&lt;T&amp;&amp;&gt;(arg)</code><span> is an xvalue.</span></p><p><span>EWG discussed this idea, disliked its expert-friendly nature, and concluded that adding this facility would cause the teaching effort to add up.</span></p><h3 id="Does-auto-works-in-place-of-decay-copy-in-the-library-specification" data-id="Does-auto-works-in-place-of-decay-copy-in-the-library-specification" style=""><a class="anchor hidden-xs" href="#Does-auto-works-in-place-of-decay-copy-in-the-library-specification" title="Does-auto-works-in-place-of-decay-copy-in-the-library-specification"><span class="octicon octicon-link"></span></a><span>Does </span><code>auto</code><span> works in place of </span><em><code>decay-copy</code></em><span> in the library specification?</span></h3><p><span>Not as a simple find-and-replace, but can be made to improve the quality of the library specification.</span></p><p><span>The background is that, despite being exposition-only, </span><em><code>decay-copy</code></em><span> always materializes its argument and produces a copy. </span><code>auto(expr)</code><span> is a no-op if the </span><code>expr</code><span> is a prvalue.</span></p><p><span>In the library specification where uses </span><em><code>decay-copy</code></em><span>, some do not mean to materialize the expressions; some want a new copy; some do not care. However, with </span><code>auto(x)</code><span> semantics, we should distinguish the different needs and explicitly say so when a copy is needed.</span></p><h3 id="What’s-the-difference-between-decltypeautoexpr-and-decay_t" data-id="What’s-the-difference-between-decltypeautoexpr-and-decay_t" style=""><a class="anchor hidden-xs" href="#What’s-the-difference-between-decltypeautoexpr-and-decay_t" title="What’s-the-difference-between-decltypeautoexpr-and-decay_t"><span class="octicon octicon-link"></span></a><span>What’s the difference between </span><code><span>decltype(auto(</span><em><span>expr</span></em><span>))</span></code><span> and </span><code>decay_t</code><span>?</span></h3><p><code><span>decay_t&lt;decltype(</span><em><span>expr</span></em><span>)&gt;</span></code><span> does not look at </span><em><code>expr</code></em><span>'s value category, so the following can hold:</span></p><pre><code class="cpp hljs"><span class="token keyword">auto</span> p <span class="token operator">=</span> make_unique<span class="token operator">&lt;</span><span class="token keyword">char</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">static_assert</span><span class="token punctuation">(</span>is_same_v<span class="token operator">&lt;</span>decay_t<span class="token operator">&lt;</span><span class="token keyword">decltype</span><span class="token punctuation">(</span>p<span class="token punctuation">)</span><span class="token operator">&gt;</span><span class="token punctuation">,</span> unique_ptr<span class="token operator">&lt;</span><span class="token keyword">char</span><span class="token operator">&gt;&gt;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p><code>decay_t&lt;U&amp;&gt;</code><span> will also simply strips </span><code>&amp;</code><span> even if </span><code>U</code><span> is a move-only type.</span></p><p><span>As a result, the </span><em><code>decay-copy</code></em><span> exposition-only function is, strictly speaking, </span><a href="https://godbolt.miator.net/z/6xjdba" target="_blank" rel="noopener"><span>insufficiently constrained</span></a><span>:</span></p><pre><code class="cpp hljs"><span class="token keyword">auto</span> p2 <span class="token operator">=</span> <span class="token function">decay_copy</span><span class="token punctuation">(</span>p<span class="token punctuation">)</span><span class="token punctuation">;</span>  <span class="token comment">// fails inside definition</span>
</code></pre><p><span>The situation where </span><code><span>decltype(decay_copy(</span><em><span>expr</span></em><span>))</span></code><span> does not fail in an immediate context does not imply that the call </span><code><span>decay_copy(</span><em><span>expr</span></em><span>)</span></code><span> is well-formed.</span></p><p><code><span>decltype(auto(</span><em><span>expr</span></em><span>))</span></code><span> has no such problem. But this does not necessarily mean that </span><code><span>decltype(auto(</span><em><span>expr</span></em><span>))</span></code><span> is better than </span><code>decay_t</code><span> or something. Sometimes you do want to compute a “decayed-type,” and sometimes, you may find it helpful to exclude the expressions that cannot be passed as arguments to a parameter declared </span><code>auto</code><span>.</span></p><h3 id="May-a-different-spelling-work-better-such-as-prvalue_cast" data-id="May-a-different-spelling-work-better-such-as-prvalue_cast" style=""><a class="anchor hidden-xs" href="#May-a-different-spelling-work-better-such-as-prvalue_cast" title="May-a-different-spelling-work-better-such-as-prvalue_cast"><span class="octicon octicon-link"></span></a><span>May a different spelling work better, such as </span><code>prvalue_cast</code><span>?</span></h3><p><span>First, </span><code>auto(x)</code><span> casts to prvalue, but may not be how the name </span><code>prvalue_cast</code><span> suggests. If there is a </span><code>prvalue_cast</code><span> keyword, you may expect the following code to pass an array prvalue to the function </span><code>foo</code><span>:</span></p><pre><code class="cpp hljs"><span class="token keyword">double</span> v<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token number">1.2</span><span class="token punctuation">,</span> <span class="token number">3.5</span><span class="token punctuation">,</span> <span class="token number">.8</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token function">foo</span><span class="token punctuation">(</span><span class="token function">prvalue_cast</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p><span>But</span></p><pre><code class="cpp hljs"><span class="token function">foo</span><span class="token punctuation">(</span><span class="token keyword">auto</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p><span>will pass a </span><code>double*</code><span>. Therefore, we are talking about a different facility.</span></p><p><span>On the other hand, the term “prvalue” is unfamiliar to ordinary C++ users. While some people may expect a prvalue-casting without decaying, some other people may not have any expectation when seeing such a term.</span></p><p><span>In contrast, the use of the </span><code>auto</code><span> keyword implies that this expression decays. It decays in the same way</span></p><pre><code class="cpp hljs"><span class="token keyword">auto</span> p <span class="token operator">=</span> v<span class="token punctuation">;</span>
</code></pre><p><span>does and in the same way</span></p><pre><code class="cpp hljs"><span class="token keyword">void</span> <span class="token function">bar</span><span class="token punctuation">(</span><span class="token keyword">auto</span> v<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">bar</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p><span>does. This consistency makes the proposed spelling a lot more teachable comparing to the others.</span></p><h3 id="Can-we-build-a-decay_copy-with-a-metaprogram-that-forwards-prvalue" data-id="Can-we-build-a-decay_copy-with-a-metaprogram-that-forwards-prvalue" style=""><a class="anchor hidden-xs" href="#Can-we-build-a-decay_copy-with-a-metaprogram-that-forwards-prvalue" title="Can-we-build-a-decay_copy-with-a-metaprogram-that-forwards-prvalue"><span class="octicon octicon-link"></span></a><span>Can we build a </span><code>decay_copy</code><span> with a metaprogram that forwards prvalue?</span></h3><p><a href="https://wg21.link/p2237" target="_blank" rel="noopener"><span>P2237</span></a><span> Metaprogramming means to replace macros, and the answer is yes. Barry kindly provides the following snippet:</span></p><pre><code class="cpp hljs">consteval <span class="token keyword">void</span> <span class="token function">prvalue_cast</span><span class="token punctuation">(</span>meta<span class="token operator">::</span>info expr<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token operator">-</span><span class="token operator">&gt;</span> decay_t<span class="token operator">&lt;</span><span class="token operator">|</span><span class="token function">type_of</span><span class="token punctuation">(</span>expr<span class="token punctuation">)</span><span class="token operator">|</span><span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token operator">|</span>expr<span class="token operator">|</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p><span>However, we should note that we added </span><code>auto</code><span> type-specifier in declarations and </span><code>new</code><span> expressions not because we cannot meta-program in those contexts. We added them because they are useful, so does </span><code>auto</code><span> in a function-style cast, as shown in this paper.</span></p><p><span>As a side note, it may be a fun thing to see if someone comes up with the following code in the future:</span></p><pre><code class="cpp hljs"><span class="token keyword">auto</span> p <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">auto</span><span class="token punctuation">(</span><span class="token function">prvalue_cast</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><h3 id="Should-we-also-make-static_castltautogtx-work" data-id="Should-we-also-make-static_castltautogtx-work" style=""><a class="anchor hidden-xs" href="#Should-we-also-make-static_castltautogtx-work" title="Should-we-also-make-static_castltautogtx-work"><span class="octicon octicon-link"></span></a><span>Should we also make </span><code>static_cast&lt;auto&gt;(x)</code><span> work?</span></h3><p><span>The motivation is that because </span><code>T(x)</code><span> is indifferent from </span><code>(T)x</code><span> – a C-style cast that may try every possible route to </span><code>T</code><span>, some codebases may ban </span><code>auto(x)</code><span> altogether with </span><code>T(x)</code><span> even though </span><code>auto</code><span> is a type-placeholder rather than a type. </span><code>static_cast&lt;auto&gt;(x)</code><span> can be a way to evacuate from such a check.</span></p><p><span>In terms of styles, without loss of generality, </span><code>char{x}</code><span> means </span><em><span>direct-list-initialization</span></em><span> from </span><code>x</code><span>. It allows no narrowing and is not a cast. I believe that no codebase would ban </span><code>T{x}</code><span>, so </span><code>auto{x}</code><span> can be an alternative spelling if </span><code>auto(x)</code><span> is accidentally banned.</span></p><p><span>If we ignore the motivation for a moment, I think:</span></p><ol>
<li><span>Whether </span><code>static_cast&lt;auto&gt;(x)</code><span> should work should also take </span><code><span>static_cast&lt;</span><em><span>template-id</span></em><span>&gt;(x)</span></code><span> (CTAD) into account. The latter is currently forbidden.</span></li>
<li><span>If we have such a paper, we may also want to decide whether </span><code>static_cast&lt;auto&amp;&amp;&gt;(x)</code><span> should work. This expression is a </span><code>std::forward</code><span> without a need to supply the type, but EWG has already turned down a similar idea (</span><a href="#Do-we-also-miss-decltypeautox"><code>decltype(auto){x}</code></a><span>).</span></li>
</ol><h3 id="Relation-with-other-papers" data-id="Relation-with-other-papers" style=""><a class="anchor hidden-xs" href="#Relation-with-other-papers" title="Relation-with-other-papers"><span class="octicon octicon-link"></span></a><span>Relation with other papers</span></h3><p><span>P2255R0</span><sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup><span> “</span><em><span>A type trait to detect reference binding to temporary</span></em><span>” guards </span><code>std::tuple</code><span> and </span><code>std::pair</code><span> constructors from forming references that bind to temporaries. The change is a good thing because it can make the following code fail to compile:</span></p><pre><code class="cpp hljs">tuple<span class="token operator">&lt;</span><span class="token keyword">const</span> string<span class="token operator">&amp;</span><span class="token operator">&gt;</span> <span class="token function">x</span><span class="token punctuation">(</span><span class="token keyword">auto</span><span class="token punctuation">(</span>obj<span class="token punctuation">.</span><span class="token function">get_str</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p><code>auto(x)</code><span> can make copies if necessary, but this does not imply that “it is safer” without a context.</span></p><p data-original-title="" title=""><span>P0847R6</span><sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup><span> “Deducing this” introduced by-value member functions. With those, a call to a member function may always copy the object:</span></p><pre><code class="cpp hljs"><span class="token function">foo</span><span class="token punctuation">(</span>vec<span class="token punctuation">.</span><span class="token function">sorted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p><span>Combining it with </span><code>auto(obj)</code><span> has no cost:</span></p><pre><code class="cpp hljs"><span class="token function">foo</span><span class="token punctuation">(</span><span class="token keyword">auto</span><span class="token punctuation">(</span>vec<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">sorted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p><span>You can also use this style when calling some member functions that are unwillingly modifying the implicit object parameters:</span></p><pre><code class="cpp hljs"><span class="token function">foo</span><span class="token punctuation">(</span><span class="token keyword">auto</span><span class="token punctuation">(</span>vec<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">sorted_in_place</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="Demo" data-id="Demo" style=""><a class="anchor hidden-xs" href="#Demo" title="Demo"><span class="octicon octicon-link"></span></a><span>Demo</span></h2><p><span>Prevent algorithm from modifying through aliases: </span><a href="https://godbolt.miator.net/z/hhcvbc" target="_blank" rel="noopener"><span>https://godbolt.miator.net/z/hhcvbc</span></a></p><p><span>Using </span><code>auto(x)</code><span> in rvalue fluent interface: </span><a href="https://godbolt.miator.net/z/TY8sxr" target="_blank" rel="noopener"><span>https://godbolt.miator.net/z/TY8sxr</span></a></p><p><span>How </span><code>auto(x)</code><span> assists in defining concepts: </span><a href="https://godbolt.miator.net/z/GTaaeE" target="_blank" rel="noopener"><span>https://godbolt.miator.net/z/GTaaeE</span></a></p><p><span>Compare diagnosis to </span><code>new auto(x)</code><span>: </span><a href="https://godbolt.miator.net/z/Ks43an" target="_blank" rel="noopener"><span>https://godbolt.miator.net/z/Ks43an</span></a></p><h2 id="Wording" data-id="Wording" style=""><a class="anchor hidden-xs" href="#Wording" title="Wording"><span class="octicon octicon-link"></span></a><span>Wording</span></h2><p><span>The wording is relative to N4878.</span></p><h3 id="Part-1" data-id="Part-1" style=""><a class="anchor hidden-xs" href="#Part-1" title="Part-1"><span class="octicon octicon-link"></span></a><span>Part 1</span></h3><p><span>Modify 7.6.1.4 [expr.type.conv]/1 as indicated:</span></p><blockquote>
<p><span>A </span><em><span>simple-type-specifier</span></em><span> (9.2.9.3) or </span><em><span>typename-specifier</span></em><span> (13.8) followed by a parenthesized optional </span><em><span>expression-list</span></em><span> or by a </span><em><span>braced-init-list</span></em><span> (the initializer) constructs a value of the specified type given the initializer. If the type is a placeholder for a deduced class type, it is replaced by the return type of the function selected by</span>
<span>overload resolution for class template deduction (12.2.2.9) for the remainder of this section. </span><ins><span>Otherwise, if the type is </span><code>auto</code><span>, it is replaced by the type deduced for the variable </span><code>x</code><span> in the invented</span>
<span>declaration (</span><a href="http://eel.is/c++draft/dcl.spec.auto" target="_blank" rel="noopener"><span>[dcl.spec.auto]</span></a><span>):</span></ins></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><ins><code><span>auto x </span><em><span>init</span></em><span>;</span></code></ins></p>
<p><ins><span>, where  </span><em><span>init</span></em><span> is the initializer.</span></ins></p>
</blockquote><p><span>Modify 9.2.9.6 [dcl.spec.auto]/5 as indicated:</span></p><blockquote>
<p><span>A placeholder type can also be used in the </span><em><span>type-specifier-seq</span></em><span> in the </span><em><span>new-type-id</span></em><span> or </span><em><span>type-id</span></em><span> of a </span><em><span>new-expression</span></em>
<span>(7.6.2.8) and as a </span><em><span>decl-specifier</span></em><span> of the </span><em><span>parameter-declaration</span></em><span>’s </span><em><span>decl-specifier-seq</span></em><span> in a </span><em><span>template-parameter</span></em>
<span>(13.2).  </span><ins><span>The </span><code>auto</code><span> </span><em><span>type-specifier</span></em><span> can also be used as the </span><em><span>simple-type-specifier</span></em><span> in an explicit type conversion (functional notation) (</span><a href="http://eel.is/c++draft/expr.type.conv" target="_blank" rel="noopener"><span>[expr.type.conv]</span></a><span>).</span></ins></p>
</blockquote><h3 id="Part-2" data-id="Part-2" style=""><a class="anchor hidden-xs" href="#Part-2" title="Part-2"><span class="octicon octicon-link"></span></a><span>Part 2</span></h3><div class="alert alert-warning">
<p><em><span>[Drafting note:</span></em>
<span>Here is a summary of patterns in the library changes:</span>
<br>
<br></p>
<table>
<thead>
<tr>
<th><span>Description</span></th>
<th><span>Before</span></th>
<th><span>Proposed</span></th>
<th><span>Alternative</span></th>
</tr>
</thead>
<tbody>
<tr>
<td><em><code>decay-copy</code></em><span> specific expression</span></td>
<td><code><em><span>decay-copy</span></em><span>(begin(t))</span></code></td>
<td><code>auto(begin(t))</code></td>
<td><span>-</span></td>
</tr>
<tr>
<td><em><code>decay-copy</code></em><span> unspecific expression</span></td>
<td><code><em><span>decay-copy</span></em><span>(E)</span></code></td>
<td><span>unchanged</span></td>
<td><code>auto(identity()(E))</code></td>
</tr>
<tr>
<td><span>explain aftermath of evaluating </span><em><code>decay-copy</code></em></td>
<td><span>calls to </span><em><code>decay-copy</code></em><span> being evaluated in the constructing thread</span></td>
<td><span>values produced by </span><code>auto</code><span> being materialized in the constructing thread</span></td>
<td><span>-</span></td>
</tr>
</tbody>
</table>
<p><span>There are three uses of </span><em><code>decay-copy</code></em><span> that this wording does not propose to change. They are in [range.all.general], [range.take], and [range.drop].</span>
<em><span>–end note]</span></em></p>
</div><p><span>Modify 24.3.2 [range.access.begin]/2 as indicated:</span></p><blockquote>
<p><span>Given a subexpression </span><code>E</code><span> with type </span><code>T</code><span>, let </span><code>t</code><span> be an lvalue that denotes the reified object for </span><code>E</code><span>. Then:</span></p>
<ul>
<li><span>If </span><code>E</code><span> is an rvalue and </span><code>enable_borrowed_range&lt;remove_cv_t&lt;T&gt;&gt;</code><span> is </span><code>false</code><span>, </span><code>ranges::begin(E)</code><span> is ill-formed.</span></li>
<li><span>Otherwise, if </span><code>T</code><span> is an array type (6.8.3) and </span><code>remove_all_extents_t&lt;T&gt;</code><span> is an incomplete type, </span><code>ranges::begin(E)</code><span> is ill-formed with no diagnostic required.</span></li>
<li><span>Otherwise, if </span><code>T</code><span> is an array type, </span><code>ranges::begin(E)</code><span> is expression-equivalent to </span><code>t + 0</code><span>.</span></li>
<li><span>Otherwise, if </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(t.begin())</code><span> is a valid expression whose type models </span><code>input_or_output_iterator</code><span>, </span><code>ranges::begin(E)</code><span> is expression-equivalent to </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(t.begin())</code><span>.</span></li>
<li><span>Otherwise, if </span><code>T</code><span> is a class or enumeration type and </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(begin(t))</code><span> is a valid expression whose type models </span><code>input_or_output_iterator</code><span> with overload resolution performed in a context in which unqualified lookup for </span><code>begin</code><span> finds only the declarations</span><br>
<span>&nbsp;&nbsp;</span><code><span>void begin(auto&amp;) = delete;</span></code><br>
<span>&nbsp;&nbsp;</span><code><span>void begin(const auto&amp;) = delete;</span></code><br>
<span>then </span><code>ranges::begin(E)</code><span> is expression-equivalent to </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(begin(t))</code><span> with overload resolution performed in the above context.</span></li>
<li><span>Otherwise, </span><code>ranges::begin(E)</code><span> is ill-formed.</span></li>
</ul>
</blockquote><p><span>Modify 24.3.3 [range.access.end]/2 as indicated:</span></p><blockquote>
<p><span>Given a subexpression </span><code>E</code><span> with type </span><code>T</code><span>, let </span><code>t</code><span> be an lvalue that denotes the reified object for </span><code>E</code><span>. Then:</span></p>
<ul>
<li><span>If </span><code>E</code><span> is an rvalue and </span><code>enable_borrowed_range&lt;remove_cv_t&lt;T&gt;&gt;</code><span> is </span><code>false</code><span>, </span><code>ranges::end(E)</code><span> is ill-formed.</span></li>
<li><span>Otherwise, if </span><code>T</code><span> is an array type (6.8.3) and </span><code>remove_all_extents_t&lt;T&gt;</code><span> is an incomplete type, </span><code>ranges::end(E)</code><span> is ill-formed with no diagnostic required.</span></li>
<li><span>Otherwise, if </span><code>T</code><span> is an array of unknown bound, </span><code>ranges::end(E)</code><span> is ill-formed.</span></li>
<li><span>Otherwise, if </span><code>T</code><span> is an array, </span><code>ranges::end(E)</code><span> is expression-equivalent to </span><code>t + extent_v&lt;T&gt;</code><span>.</span></li>
<li><span>Otherwise, if </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(t.end())</code><span> is a valid expression whose type models </span><code>sentinel_for&lt;iterator_t&lt;T&gt;&gt;</code><span> then </span><code>ranges::end(E)</code><span> is expression-equivalent to </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(t.end())</code><span>.</span></li>
<li><span>Otherwise, if </span><code>T</code><span> is a class or enumeration type and </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(end(t))</code><span> is a valid expression whose type models </span><code>sentinel_for&lt;iterator_t&lt;T&gt;&gt;</code><span> with overload resolution performed in a context in which unqualified lookup for </span><code>end</code><span> finds only the declarations</span><br>
<span>&nbsp;&nbsp;</span><code><span>void end(auto&amp;) = delete;</span></code><br>
<span>&nbsp;&nbsp;</span><code><span>void end(const auto&amp;) = delete;</span></code><br>
<span>then </span><code>ranges::end(E)</code><span> is expression-equivalent to </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(end(t))</code><span> with overload resolution performed in the above context.</span></li>
<li><span>Otherwise, </span><code>ranges::end(E)</code><span> is ill-formed.</span></li>
</ul>
</blockquote><p><span>Modify 24.3.6 [range.access.rbegin]/2 as indicated:</span></p><blockquote>
<p><span>Given a subexpression </span><code>E</code><span> with type </span><code>T</code><span>, let </span><code>t</code><span> be an lvalue that denotes the reified object for </span><code>E</code><span>. Then:</span></p>
<ul>
<li><span>If </span><code>E</code><span> is an rvalue and </span><code>enable_borrowed_range&lt;remove_cv_t&lt;T&gt;&gt;</code><span> is </span><code>false</code><span>, </span><code>ranges::rbegin(E)</code><span> is ill-formed.</span></li>
<li><span>Otherwise, if </span><code>T</code><span> is an array type (6.8.3) and </span><code>remove_all_extents_t&lt;T&gt;</code><span> is an incomplete type, </span><code>ranges::rbegin(E)</code><span> is ill-formed with no diagnostic required.</span></li>
<li><span>Otherwise, if </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(t.rbegin())</code><span> is a valid expression whose type models </span><code>input_or_output_iterator</code><span>, </span><code>ranges::rbegin(E)</code><span> is expression-equivalent to </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(t.rbegin())</code><span>.</span></li>
<li><span>Otherwise, if </span><code>T</code><span> is a class or enumeration type and </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(rbegin(t))</code><span> is a valid expression whose type models </span><code>input_or_output_iterator</code><span> with overload resolution performed in a context in which unqualified lookup for </span><code>rbegin</code><span> finds only the declarations</span><br>
<span>&nbsp;&nbsp;</span><code><span>void rbegin(auto&amp;) = delete;</span></code><br>
<span>&nbsp;&nbsp;</span><code><span>void rbegin(const auto&amp;) = delete;</span></code><br>
<span>then </span><code>ranges::rbegin(E)</code><span> is expression-equivalent to </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(rbegin(t))</code><span> with overload resolution performed in the above context.</span></li>
<li><span>[…]</span></li>
</ul>
</blockquote><p><span>Modify 24.3.7 [range.access.rend]/2 as indicated:</span></p><blockquote>
<p><span>Given a subexpression </span><code>E</code><span> with type </span><code>T</code><span>, let </span><code>t</code><span> be an lvalue that denotes the reified object for </span><code>E</code><span>. Then:</span></p>
<ul>
<li><span>If </span><code>E</code><span> is an rvalue and </span><code>enable_borrowed_range&lt;remove_cv_t&lt;T&gt;&gt;</code><span> is </span><code>false</code><span>, </span><code>ranges::rend(E)</code><span> is ill-formed.</span></li>
<li><span>Otherwise, if </span><code>T</code><span> is an array type (6.8.3) and </span><code>remove_all_extents_t&lt;T&gt;</code><span> is an incomplete type, </span><code>ranges::rend(E)</code><span> is ill-formed with no diagnostic required.</span></li>
<li><span>Otherwise, if </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(t.rend())</code><span> is a valid expression whose type models </span><code>sentinel_for&lt;decltype(ranges::rbegin(E)&gt;</code><span> then </span><code>ranges::rend(E)</code><span> is expression-equivalent to </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(t.rend())</code><span>.</span></li>
<li><span>Otherwise, if </span><code>T</code><span> is a class or enumeration type and </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(rend(t))</code><span> is a valid expression whose type models </span><code>sentinel_for&lt;decltype(ranges::rbegin(E)&gt;</code><span> with overload resolution performed in a context in which unqualified lookup for </span><code>rend</code><span> finds only the declarations</span><br>
<span>&nbsp;&nbsp;</span><code><span>void rend(auto&amp;) = delete;</span></code><br>
<span>&nbsp;&nbsp;</span><code><span>void rend(const auto&amp;) = delete;</span></code><br>
<span>then </span><code>ranges::rend(E)</code><span> is expression-equivalent to </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(rend(t))</code><span> with overload resolution performed in the above context.</span></li>
<li><span>[…]</span></li>
</ul>
</blockquote><p><span>Modify 24.3.10 [range.prim.size]/2 as indicated:</span></p><blockquote>
<p><span>Given a subexpression </span><code>E</code><span> with type </span><code>T</code><span>, let </span><code>t</code><span> be an lvalue that denotes the reified object for </span><code>E</code><span>. Then:</span></p>
<ul>
<li><span>If </span><code>T</code><span> is an array of unknown bound (9.3.4.5), </span><code>ranges::size(E)</code><span> is ill-formed.</span></li>
<li><span>Otherwise, if </span><code>T</code><span> is an array type, </span><code>ranges::size(E)</code><span> is expression-equivalent to </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(extent_v&lt;T&gt;)</code><span>.</span></li>
<li><span>Otherwise, if </span><code>disable_sized_range&lt;remove_cv_t&lt;T&gt;&gt;</code><span> (24.4.3) is </span><code>false</code><span> and </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(t.size())</code><span> is a valid expression of integer-like type (23.3.4.4), </span><code>ranges::size(E)</code><span> is expression-equivalent to </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(t.size())</code><span>.</span></li>
<li><span>Otherwise, if </span><code>T</code><span> is a class or enumeration type, </span><code>disable_sized_range&lt;remove_cv_t&lt;T&gt;&gt;</code><span> is </span><code>false</code><span> and </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(size(t))</code><span> is a valid expression of integer-like type with overload resolution performed in a context in which unqualified lookup for </span><code>size</code><span> finds only the declarations</span><br>
<span>&nbsp;&nbsp;</span><code><span>void size(auto&amp;) = delete;</span></code><br>
<span>&nbsp;&nbsp;</span><code><span>void size(const auto&amp;) = delete;</span></code><br>
<span>then </span><code>ranges::size(E)</code><span> is expression-equivalent to </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(size(t))</code><span> with overload resolution performed in the above context.</span></li>
<li><span>[…]</span></li>
</ul>
</blockquote><p><span>Modify 24.3.13 [range.prim.data]/2 as indicated:</span></p><blockquote>
<p><span>Given a subexpression </span><code>E</code><span> with type </span><code>T</code><span>, let </span><code>t</code><span> be an lvalue that denotes the reified object for </span><code>E</code><span>. Then:</span></p>
<ul>
<li><span>If </span><code>E</code><span> is an rvalue and </span><code>enable_borrowed_range&lt;remove_cv_t&lt;T&gt;&gt;</code><span> is </span><code>false</code><span>, </span><code>ranges::data(E)</code><span> is ill-formed.</span></li>
<li><span>Otherwise, if </span><code>T</code><span> is an array type (6.8.3) and </span><code>remove_all_extents_t&lt;T&gt;</code><span> is an incomplete type, </span><code>ranges::data(E)</code><span> is ill-formed with no diagnostic required.</span></li>
<li><span>Otherwise, if </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(t.data())</code><span> is a valid expression of pointer to object type, </span><code>ranges::data(E)</code><span> is expression-equivalent to </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(t.data())</code><span>.</span></li>
<li><span>[…]</span></li>
</ul>
</blockquote><p><span>Modify 32.4.3.3 [thread.thread.constr]/5 as indicated:</span></p><blockquote>
<p><em><span>Effects:</span></em><span> The new thread of execution executes</span></p>
<p><span>&nbsp;&nbsp;</span><code style="white-space: pre-wrap"><span>invoke(</span><s><em><span>decay-copy</span></em></s><ins><span>auto</span></ins><span>(std::forward&lt;F&gt;(f)),</span></code><br>
<span>&nbsp;&nbsp;</span><code style="white-space: pre-wrap"><span>       </span><s><em><span>decay-copy</span></em></s><ins><span>auto</span></ins><span>(std::forward&lt;Args&gt;&gt;(args))…)</span></code></p>
<p><span>with the </span><s><span>calls to </span><em><code>decay-copy</code></em><span> being evaluated</span></s><ins><span>values produced by </span><code>auto</code><span> being materialized (</span><a href="http://eel.is/c++draft/conv#rval" target="_blank" rel="noopener"><span>[conv.rval]</span></a><span>)</span></ins><span> in the constructing thread. Any return value from this invocation is ignored. […]</span></p>
</blockquote><p><span>Modify 32.4.4.2 [thread.jthread.cons]/5 as indicated:</span></p><blockquote>
<p><em><span>Effects:</span></em><span> Initializes </span><code>ssource</code><span>. The new thread of execution executes</span></p>
<p><span>&nbsp;&nbsp;</span><code style="white-space: pre-wrap"><span>invoke(</span><s><em><span>decay-copy</span></em></s><ins><span>auto</span></ins><span>(std::forward&lt;F&gt;(f)), get_stop_token(),</span></code><br>
<span>&nbsp;&nbsp;</span><code style="white-space: pre-wrap"><span>       </span><s><em><span>decay-copy</span></em></s><ins><span>auto</span></ins><span>(std::forward&lt;Args&gt;&gt;(args))…)</span></code></p>
<p><span>if that expression is well-formed, otherwise</span></p>
<p><span>&nbsp;&nbsp;</span><code style="white-space: pre-wrap"><span>invoke(</span><s><em><span>decay-copy</span></em></s><ins><span>auto</span></ins><span>(std::forward&lt;F&gt;(f)),</span></code><br>
<span>&nbsp;&nbsp;</span><code style="white-space: pre-wrap"><span>       </span><s><em><span>decay-copy</span></em></s><ins><span>auto</span></ins><span>(std::forward&lt;Args&gt;&gt;(args))…)</span></code></p>
<p><span>with the </span><s><span>calls to </span><em><code>decay-copy</code></em><span> being evaluated</span></s><ins><span>values produced by </span><code>auto</code><span> being materialized (</span><a href="http://eel.is/c++draft/conv#rval" target="_blank" rel="noopener"><span>[conv.rval]</span></a><span>)</span></ins><span> in the constructing thread. Any return value from this invocation is ignored. […]</span></p>
</blockquote><p><span>Modify 32.9.9 [futures.async]/3 as indicated:</span></p><blockquote>
<p><em><span>Effects:</span></em><span> The first function behaves the same as a call to the second function with a </span><code>policy</code><span> argument of </span><code>launch::async | launch::deferred</code><span> […]:</span></p>
<ul>
<li><span>If </span><code>launch::async</code><span> is set in </span><code>policy</code><span>, calls </span><code><span>invoke(</span><s><em><span>decay-copy</span></em></s><ins><span>auto</span></ins><span>(std::forward&lt;F&gt;(f)), </span><s><em><span>decay-copy</span></em></s><ins><span>auto</span></ins><span>(std::forward&lt;Args&gt;&gt;(args))…)</span></code><span> (20.14.4, 32.4.3.3) as if in a new thread of execution represented by a </span><code>thread</code><span> object with the </span><s><span>calls to </span><em><code>decay-copy</code></em><span> being evaluated</span></s><ins><span>values produced by </span><code>auto</code><span> being materialized (</span><a href="http://eel.is/c++draft/conv#rval" target="_blank" rel="noopener"><span>[conv.rval]</span></a><span>)</span></ins><span> in the thread that called </span><code>async</code><span>. Any return value is stored as the result in the shared state. Any exception propagated from the execution of </span><code><span>invoke(</span><s><em><span>decay-copy</span></em></s><ins><span>auto</span></ins><span>(std::forward&lt;F&gt;(f)), </span><s><em><span>decay-copy</span></em></s><ins><span>auto</span></ins><span>(std::forward&lt;Args&gt;&gt;(args))…)</span></code><span> is stored as the exceptional result in the shared state. The </span><code>thread</code><span> object is stored in the shared state and affects the behavior of any asynchronous return objects that</span>
<span>reference that state.</span></li>
<li><span>If </span><code>launch::deferred</code><span> is set in </span><code>policy</code><span>, stores </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(std::forward&lt;F&gt;(f))</code><span> and </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(std::forward&lt;Args&gt;(args))...</code><span> in the shared state. These copies of </span><code>f</code><span> and </span><code>args</code><span> constitute a </span><em><span>deferred function</span></em><span>. Invocation of the deferred function evaluates </span><code>invoke(std::move(g), std::move(xyz))</code><span> where </span><code>g</code><span> is the stored value of </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(std::forward&lt;F&gt;(f))</code><span> and </span><code>xyz</code><span> is the stored copy of </span><s><em><code>decay-copy</code></em></s><ins><code>auto</code></ins><code>(std::forward&lt;Args&gt;(args))...</code><span>. Any return value is stored as</span>
<span>the result in the shared state. Any exception propagated from the execution of the deferred</span>
<span>function is stored as the exceptional result in the shared state. […]</span></li>
</ul>
</blockquote><h2 id="Acknowledgments" data-id="Acknowledgments" style=""><a class="anchor hidden-xs" href="#Acknowledgments" title="Acknowledgments"><span class="octicon octicon-link"></span></a><span>Acknowledgments</span></h2><p><span>Thank Alisdair Meredith, Arthur O’Dwyer, and Billy O’Neal for providing examples and feedback for this paper.  Thank James Touton for presenting the paper and bringing it forward.  Thank Jens Maurer and Casey Carter for reviewing the wording.</span></p><h2 id="References" data-id="References" style=""><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><span>Krügler, Daniel. P0758R0 </span><em><span>Implicit conversion traits and utility functions</span></em><span>.</span>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0758r0.html" target="_blank" rel="noopener"><span>http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0758r0.html</span></a> <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn2" class="footnote-item"><p><span>Song, Tim. P2255R0 </span><em><span>A type trait to detect reference binding to temporary.</span></em>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2255r0.html" target="_blank" rel="noopener"><span>http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2255r0.html</span></a> <a href="#fnref2" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn3" class="footnote-item"><p><span>Ažman et al. P0847R6 </span><em><span>Deducing this</span></em><span>.</span>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r6.html" target="_blank" rel="noopener"><span>http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r6.html</span></a> <a href="#fnref3" 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 class=""><a href="#autox-decay-copy-in-the-language" title="auto(x): decay-copy in the language">auto(x): decay-copy in the language</a><ul class="nav">
<li><a href="#Changes-Since-R6" title="Changes Since R6">Changes Since R6</a></li>
<li><a href="#Changes-Since-R5" title="Changes Since R5">Changes Since R5</a></li>
<li><a href="#Changes-Since-R4" title="Changes Since R4">Changes Since R4</a></li>
<li><a href="#Changes-Since-R3" title="Changes Since R3">Changes Since R3</a></li>
<li><a href="#Changes-Since-R2" title="Changes Since R2">Changes Since R2</a></li>
<li><a href="#Changes-Since-R1" title="Changes Since R1">Changes Since R1</a></li>
<li><a href="#Changes-Since-R0" title="Changes Since R0">Changes Since R0</a></li>
<li><a href="#Introduction" title="Introduction">Introduction</a></li>
<li><a href="#Motivation" title="Motivation">Motivation</a><ul class="nav">
<li><a href="#Obtaining-a-prvalue-copy-is-necessary" title="Obtaining a prvalue copy is necessary">Obtaining a prvalue copy is necessary</a></li>
<li><a href="#Obtaining-a-prvalue-copy-with-autox-works-always" title="Obtaining a prvalue copy with auto(x) works always">Obtaining a prvalue copy with auto(x) works always</a></li>
</ul>
</li>
<li><a href="#Discussion" title="Discussion">Discussion</a><ul class="nav">
<li><a href="#autox-is-a-missing-piece" title="auto(x) is a missing piece">auto(x) is a missing piece</a></li>
<li><a href="#Do-we-also-miss-decltypeautox" title="Do we also miss decltype(auto){x}?">Do we also miss decltype(auto){x}?</a></li>
<li><a href="#Does-auto-works-in-place-of-decay-copy-in-the-library-specification" title="Does auto works in place of decay-copy in the library specification?">Does auto works in place of decay-copy in the library specification?</a></li>
<li><a href="#What’s-the-difference-between-decltypeautoexpr-and-decay_t" title="What’s the difference between decltype(auto(expr)) and decay_t?">What’s the difference between decltype(auto(expr)) and decay_t?</a></li>
<li><a href="#May-a-different-spelling-work-better-such-as-prvalue_cast" title="May a different spelling work better, such as prvalue_cast?">May a different spelling work better, such as prvalue_cast?</a></li>
<li><a href="#Can-we-build-a-decay_copy-with-a-metaprogram-that-forwards-prvalue" title="Can we build a decay_copy with a metaprogram that forwards prvalue?">Can we build a decay_copy with a metaprogram that forwards prvalue?</a></li>
<li><a href="#Should-we-also-make-static_castltautogtx-work" title="Should we also make static_cast<auto>(x) work?">Should we also make static_cast&lt;auto&gt;(x) work?</a></li>
<li><a href="#Relation-with-other-papers" title="Relation with other papers">Relation with other papers</a></li>
</ul>
</li>
<li><a href="#Demo" title="Demo">Demo</a></li>
<li><a href="#Wording" title="Wording">Wording</a><ul class="nav">
<li><a href="#Part-1" title="Part 1">Part 1</a></li>
<li><a href="#Part-2" title="Part 2">Part 2</a></li>
</ul>
</li>
<li><a href="#Acknowledgments" title="Acknowledgments">Acknowledgments</a></li>
<li><a href="#References" title="References">References</a></li>
</ul>
</li>
</ul>
</div><div class="toc-menu"><a class="expand-toggle" href="#">Expand all</a><a class="back-to-top" href="#">Back to top</a><a class="go-to-bottom" href="#">Go to bottom</a></div>
            </ul>
        </div>
    </div>
    <div id="ui-toc-affix" class="ui-affix-toc ui-toc-dropdown unselectable hidden-print" data-spy="affix" style="top:17px;display:none;" null null>
        <div class="toc"><ul class="nav">
<li class=""><a href="#autox-decay-copy-in-the-language" title="auto(x): decay-copy in the language">auto(x): decay-copy in the language</a><ul class="nav">
<li class=""><a href="#Changes-Since-R6" title="Changes Since R6">Changes Since R6</a></li>
<li class=""><a href="#Changes-Since-R5" title="Changes Since R5">Changes Since R5</a></li>
<li class=""><a href="#Changes-Since-R4" title="Changes Since R4">Changes Since R4</a></li>
<li class=""><a href="#Changes-Since-R3" title="Changes Since R3">Changes Since R3</a></li>
<li><a href="#Changes-Since-R2" title="Changes Since R2">Changes Since R2</a></li>
<li class=""><a href="#Changes-Since-R1" title="Changes Since R1">Changes Since R1</a></li>
<li><a href="#Changes-Since-R0" title="Changes Since R0">Changes Since R0</a></li>
<li><a href="#Introduction" title="Introduction">Introduction</a></li>
<li class=""><a href="#Motivation" title="Motivation">Motivation</a><ul class="nav">
<li class=""><a href="#Obtaining-a-prvalue-copy-is-necessary" title="Obtaining a prvalue copy is necessary">Obtaining a prvalue copy is necessary</a></li>
<li class=""><a href="#Obtaining-a-prvalue-copy-with-autox-works-always" title="Obtaining a prvalue copy with auto(x) works always">Obtaining a prvalue copy with auto(x) works always</a></li>
</ul>
</li>
<li class=""><a href="#Discussion" title="Discussion">Discussion</a><ul class="nav">
<li><a href="#autox-is-a-missing-piece" title="auto(x) is a missing piece">auto(x) is a missing piece</a></li>
<li><a href="#Do-we-also-miss-decltypeautox" title="Do we also miss decltype(auto){x}?">Do we also miss decltype(auto){x}?</a></li>
<li><a href="#Does-auto-works-in-place-of-decay-copy-in-the-library-specification" title="Does auto works in place of decay-copy in the library specification?">Does auto works in place of decay-copy in the library specification?</a></li>
<li class=""><a href="#What’s-the-difference-between-decltypeautoexpr-and-decay_t" title="What’s the difference between decltype(auto(expr)) and decay_t?">What’s the difference between decltype(auto(expr)) and decay_t?</a></li>
<li><a href="#May-a-different-spelling-work-better-such-as-prvalue_cast" title="May a different spelling work better, such as prvalue_cast?">May a different spelling work better, such as prvalue_cast?</a></li>
<li><a href="#Can-we-build-a-decay_copy-with-a-metaprogram-that-forwards-prvalue" title="Can we build a decay_copy with a metaprogram that forwards prvalue?">Can we build a decay_copy with a metaprogram that forwards prvalue?</a></li>
<li><a href="#Should-we-also-make-static_castltautogtx-work" title="Should we also make static_cast<auto>(x) work?">Should we also make static_cast&lt;auto&gt;(x) work?</a></li>
<li class=""><a href="#Relation-with-other-papers" title="Relation with other papers">Relation with other papers</a></li>
</ul>
</li>
<li class=""><a href="#Demo" title="Demo">Demo</a></li>
<li class=""><a href="#Wording" title="Wording">Wording</a><ul class="nav">
<li class=""><a href="#Part-1" title="Part 1">Part 1</a></li>
<li class=""><a href="#Part-2" title="Part 2">Part 2</a></li>
</ul>
</li>
<li><a href="#Acknowledgments" title="Acknowledgments">Acknowledgments</a></li>
<li><a href="#References" title="References">References</a></li>
</ul>
</li>
</ul>
</div><div class="toc-menu"><a class="expand-toggle" href="#">Expand all</a><a class="back-to-top" href="#">Back to top</a><a class="go-to-bottom" href="#">Go to bottom</a></div>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha256-U5ZEeKfGNOja007MMD3YBI0A3OSZOQbeG6z2f2Y0hu8=" crossorigin="anonymous" defer></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gist-embed/2.6.0/gist-embed.min.js" integrity="sha256-KyF2D6xPIJUW5sUDSs93vWyZm+1RzIpKCexxElmxl8g=" crossorigin="anonymous" defer></script>
    <script>
        var markdown = $(".markdown-body");
        //smooth all hash trigger scrolling
        function smoothHashScroll() {
            var hashElements = $("a[href^='#']").toArray();
            for (var i = 0; i < hashElements.length; i++) {
                var element = hashElements[i];
                var $element = $(element);
                var hash = element.hash;
                if (hash) {
                    $element.on('click', function (e) {
                        // store hash
                        var hash = this.hash;
                        if ($(hash).length <= 0) return;
                        // prevent default anchor click behavior
                        e.preventDefault();
                        // animate
                        $('body, html').stop(true, true).animate({
                            scrollTop: $(hash).offset().top
                        }, 100, "linear", function () {
                            // when done, add hash to url
                            // (default click behaviour)
                            window.location.hash = hash;
                        });
                    });
                }
            }
        }

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

        var enoughForAffixToc = true;

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

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

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

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

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

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

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

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

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

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

</html>
