<!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>
        cv-qualified types in atomic and atomic_ref
    </title>

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

<body>
    <div id="doc" class="markdown-body container-fluid comment-enabled" data-hard-breaks="true" style=""><p><span>Document Number: P3323R0.</span><br>
<span>Date: 2024-06-10.</span><br>
<span>Reply to: Gonzalo Brito Gadeschi &lt;gonzalob _at_ </span><a href="http://nvidia.com" target="_blank" rel="noopener"><span>nvidia.com</span></a><span>&gt;.</span><br>
<span>Authors: Gonzalo Brito Gadeschi, Lewis Baker.</span><br>
<span>Audience: SG1.</span></p><style>
ins {
    color:green;
    text-decoration:underline;
}
del { 
    color:red;
    background-color:yellow;
    text-decoration:line-through;
}
bdi {
    color:blue;
    text-decoration:underline;
}
    .markdown-body { 
    max-width: 800px; 
}
</style><h1 id="cv-qualified-types-in-atomic-and-atomic_ref" data-id="cv-qualified-types-in-atomic-and-atomic_ref" style=""><a class="anchor hidden-xs" href="#cv-qualified-types-in-atomic-and-atomic_ref" title="cv-qualified-types-in-atomic-and-atomic_ref"><span class="octicon octicon-link"></span></a><span>cv-qualified types in atomic and atomic_ref</span></h1><p><span class="toc"><ul>
<li><a href="#cv-qualified-types-in-atomic-and-atomic_ref" title="cv-qualified types in atomic and atomic_ref">cv-qualified types in atomic and atomic_ref</a><ul>
<li><a href="#Summary" title="Summary">Summary</a></li>
<li><a href="#Motivation" title="Motivation">Motivation</a></li>
<li><a href="#Resolution-for-stdatomic" title="Resolution for std::atomic">Resolution for std::atomic</a></li>
<li><a href="#Resolution-for-stdatomic_ref" title="Resolution for std::atomic_ref">Resolution for std::atomic_ref</a></li>
</ul>
</li>
</ul>
</span></p><h2 id="Summary" data-id="Summary" style=""><a class="anchor hidden-xs" href="#Summary" title="Summary"><span class="octicon octicon-link"></span></a><span>Summary</span></h2><p><span>Addresses </span><a href="https://cplusplus.github.io/LWG/issue4069" target="_blank" rel="noopener"><span>LWG#4069</span></a><span> and </span><a href="https://cplusplus.github.io/LWG/issue3508" target="_blank" rel="noopener"><span>LWG#3508</span></a><span> by clarifying that cv-qualified types are not supported by </span><code>std::atomic&lt;T&gt;</code><span> and specifying how these are supported by </span><code>std::atomic_ref&lt;T&gt;</code><span>.</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><p><a href="https://cplusplus.github.io/CWG/issues/2094.html" target="_blank" rel="noopener"><span>CWG#2094</span></a><span> made </span><code>is_trivially_copyable_v&lt;volatile ...-type&gt;</code><span> (integer, pointer, floating-point) true, leading to </span><a href="https://cplusplus.github.io/LWG/issue3508" target="_blank" rel="noopener"><span>LWG#3508</span></a><span> and </span><a href="https://cplusplus.github.io/LWG/issue4069" target="_blank" rel="noopener"><span>LWG#4069</span></a><span>.</span></p><p><span>Supporting </span><code>atomic_ref&lt;volatile T&gt;</code><span> can be useful for atomically  accessing objects of type </span><code>T</code><span> stored in shared-memory where the object was not created as an </span><code>atomic&lt;T&gt;</code><span>.</span></p><h2 id="Resolution-for-stdatomic" data-id="Resolution-for-stdatomic" style=""><a class="anchor hidden-xs" href="#Resolution-for-stdatomic" title="Resolution-for-stdatomic"><span class="octicon octicon-link"></span></a><span>Resolution for </span><code>std::atomic</code></h2><p><code>std::atomic&lt;...-type&gt;</code><span> specializations only apply for cv-unqualified types.</span></p><ul>
<li><em><span>Proposed resolution</span></em><span>: restrict </span><code>std::atomic&lt;T&gt;</code><span> to types </span><code>T</code><span> for which</span><br>
<code>same_as&lt;T, remove_cv_t&lt;T&gt;&gt;</code><span> is true.</span></li>
<li><em><span>Rationale</span></em><span>: </span><code>atomic&lt;volatile int&gt;</code><span> use case is served by </span><code>volatile atomic&lt;int&gt;</code><span>, i.e., there is no need to support </span><code>atomic&lt;volatile T&gt;</code><span>.</span></li>
<li><em><span>Impact</span></em><span>: libstdc++ and libc++ can't compile </span><code>atomic&lt;volatile T&gt;</code><span> already. MSVC can, but usage is limited, e.g., because </span><code>fetch_add</code><span> only exists on specialization, not primary template.</span></li>
<li><em><span>Proposed wording</span></em><span>:</span></li>
</ul><p><span>Modify </span><a href="https://eel.is/c++draft/atomics.types.generic.general" target="_blank" rel="noopener"><span>[atomics.types.generic.general]</span></a><span>:</span></p><p><span>The template argument for </span><code>T</code><span> shall meet the </span><em><span>Cpp17CopyConstructible</span></em><span> and </span><em><span>Cpp17CopyAssignable</span></em><span> requirements. The program is ill-formed if any of</span></p><ol>
<li><code>is_trivially_copyable_v&lt;T&gt;</code><span>,</span></li>
<li><code>is_copy_constructible_v&lt;T&gt;</code><span>,</span></li>
<li><code>is_move_constructible_v&lt;T&gt;</code><span>,</span></li>
<li><code>is_copy_assignable_v&lt;T&gt;</code><span>,</span><del><span>or</span></del></li>
<li><code>is_move_assignable_v&lt;T&gt;</code><ins><span>, or</span></ins></li>
<li><ins><code>same_as&lt;T, remove_cv_t&lt;T&gt;&gt;</code></ins><br>
<span>is false.</span></li>
</ol><h2 id="Resolution-for-stdatomic_ref" data-id="Resolution-for-stdatomic_ref" style=""><a class="anchor hidden-xs" href="#Resolution-for-stdatomic_ref" title="Resolution-for-stdatomic_ref"><span class="octicon octicon-link"></span></a><span>Resolution for </span><code>std::atomic_ref</code></h2><p><a href="https://cplusplus.github.io/LWG/issue3508" target="_blank" rel="noopener"><span>LWG#3508</span></a><span> also points out this problem, and indicates that for const-qualified types, it is not possible to implement atomic load or atomic read-modify-write operations.</span></p><p><code>std::atomic_ref&lt;...-type&gt;</code><span> specializations only apply for cv-unqualified types.</span></p><ul>
<li><em><span>Proposed resolution</span></em><span>: specify </span><code>std::atomic_ref&lt;T&gt;</code><span> for cv-qualified T by restricting support of </span><code>volatile</code><span>-qualified types to lock-free atomics and restricting support of </span><code>const</code><span>-qualified types to atomic read operations.</span></li>
<li><em><span>Rationale</span></em><span>: </span><code>atomic_ref</code><span> goal of improving concurrency support when interfacing with third-party types, which may be using </span><code>volatile int</code><span> for historical purposes, needs </span><code>std::atomic_ref&lt;volatile int&gt;</code><span>: the </span><code>atomic_ref</code><span> itself is not </span><code>volatile</code><span>, the data it references is.</span></li>
<li><em><span>Impact</span></em><span>: libstdc++ and libc++ (among others) would need to implement it.</span></li>
<li><em><span>Wording</span></em><span>:</span></li>
</ul><p><span>Modify </span><a href="https://eel.is/c++draft/atomics.ref.generic.general" target="_blank" rel="noopener"><span>[atomics.ref.generic.general]</span></a><span>:</span></p><pre><code>namespace std {
  template&lt;class T&gt; struct atomic_ref {
  private:
    T* ptr;             // exposition only

  public:
    using value_type = <del>T</del><ins>remove_cv_t&lt;T&gt;</ins>;
    static constexpr size_t required_alignment = implementation-defined;

    static constexpr bool is_always_lock_free = implementation-defined;
    bool is_lock_free() const noexcept;

    explicit atomic_ref(T&amp;);
    atomic_ref(const atomic_ref&amp;) noexcept;
    atomic_ref&amp; operator=(const atomic_ref&amp;) = delete;

    void store(<del>T</del><ins>value_type</ins>, memory_order = memory_order::seq_cst) const noexcept;
    <del>T</del><ins>value_type</ins> operator=(<del>T</del><ins>value_type</ins>) const noexcept;
    <del>T</del><ins>value_type</ins> load(memory_order = memory_order::seq_cst) const noexcept;
    operator <del>T</del><ins>value_type</ins>() const noexcept;

    <del>T</del><ins>value_type</ins> exchange(<del>T</del><ins>value_type</ins>, memory_order = memory_order::seq_cst) 
      const noexcept;
    bool compare_exchange_weak(<del>T</del><ins>value_type</ins>&amp;, <del>T</del><ins>value_type</ins>,
                               memory_order, memory_order) 
        const noexcept;
    bool compare_exchange_strong(<del>T</del><ins>value_type</ins>&amp;, <del>T</del><ins>value_type</ins>,
                                 memory_order, memory_order)
        const noexcept;
    bool compare_exchange_weak(<del>T</del><ins>value_type</ins>&amp;, <del>T</del><ins>value_type</ins>,
                               memory_order = memory_order::seq_cst) 
        const noexcept;
    bool compare_exchange_strong(<del>T</del><ins>value_type</ins>&amp;, <del>T</del><ins>value_type</ins>,
                                 memory_order = memory_order::seq_cst)
        const noexcept;

    void wait(<del>T</del><ins>value_type</ins>, memory_order = memory_order::seq_cst) const noexcept;
    void notify_one() const noexcept;
    void notify_all() const noexcept;
  };
}
</code></pre><ol>
<li><span>An </span><code>atomic_ref</code><span> object applies atomic operations ([atomics.general]) to the object referenced by </span><code>*ptr</code><span> such that, for the lifetime ([basic.life]) of the </span><code>atomic_ref</code><span> object, the object referenced by </span><code>*ptr</code><span> is an atomic object ([intro.races]).</span></li>
<li><span>The program is ill-formed if </span><code>is_trivially_copyable_v&lt;T&gt;</code><span> is false.</span></li>
<li><span>The lifetime ([basic.life]) of an object referenced by </span><code>*ptr</code><span> shall exceed the lifetime of all </span><code>atomic_ref</code><span>s that reference the object. While any </span><code>atomic_ref</code><span> instances exist that reference the </span><code>*ptr</code><span> object, all accesses to that object shall exclusively occur through those </span><code>atomic_ref</code><span> instances. No subobject of the object referenced by </span><code>atomic_ref</code><span> shall be concurrently referenced by any other </span><code>atomic_ref</code><span> object.</span></li>
<li><span>Atomic operations applied to an object through a referencing </span><code>atomic_ref</code><span> are atomic with respect to atomic operations applied through any other </span><code>atomic_ref</code><span> referencing the same object.</span><br>
<span>[Note 1: Atomic operations or the </span><code>atomic_ref</code><span> constructor can acquire a shared resource, such as a lock associated with the referenced object, to enable atomic operations to be applied to the referenced object. — end note]</span></li>
<li><ins><span>The program is ill-formed if </span><code>is_always_lock_free</code><span> is </span><code>false</code><span> and </span><code>is_volatile_v&lt;T&gt;</code><span> is </span><code>true</code><span>.</span></ins></li>
</ol><p><span>Modify </span><a href="https://eel.is/c++draft/atomics.ref.ops" target="_blank" rel="noopener"><span>[atomics.ref.ops]</span></a><span> as follows:</span></p><p><span>33.5.7.2 Operations [atomics.ref.ops]</span></p><pre><code class="cpp hljs"><span class="token keyword">static</span> <span class="token keyword">constexpr</span> size_t required_alignment<span class="token punctuation">;</span>
</code></pre><ol>
<li><span>The alignment required for an object to be referenced by an atomic reference, which is at least </span><code>alignof(T)</code><span>.</span></li>
<li><span>[Note 1: Hardware could require an object referenced by an </span><code>atomic_ref</code><span> to have stricter alignment ([basic.align]) than other objects of type </span><code>T</code><span>. Further, whether operations on an </span><code>atomic_ref</code><span> are lock-free could depend on the alignment of the referenced object. For example, lock-free operations on </span><code>std​::​complex&lt;double&gt;</code><span> could be supported only if aligned to </span><code>2*alignof(double)</code><span>. — end note]</span></li>
</ol><pre><code class="cpp hljs"><span class="token keyword">static</span> <span class="token keyword">constexpr</span> <span class="token keyword">bool</span> is_always_lock_free<span class="token punctuation">;</span>
</code></pre><ol start="3">
<li><span>The static data member </span><code>is_always_lock_free</code><span> is </span><code>true</code><span> if the </span><code>atomic_ref</code><span> type's operations are always lock-free, and </span><code>false</code><span> otherwise.</span></li>
</ol><pre><code class="cpp hljs"><span class="token keyword">bool</span> <span class="token function">is_lock_free</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">const</span> <span class="token keyword">noexcept</span><span class="token punctuation">;</span>
</code></pre><ol start="4">
<li><span>Returns: </span><code>true</code><span> if operations on all objects of the type </span><code>atomic_ref&lt;T&gt;</code><span> are lock-free, </span><code>false</code><span> otherwise.</span></li>
</ol><pre><code class="cpp hljs"><span class="token function">atomic_ref</span><span class="token punctuation">(</span>T<span class="token operator">&amp;</span> obj<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><ol start="5">
<li><span>Preconditions: The referenced object is aligned to </span><code>required_alignment</code><span>.</span></li>
<li><span>Postconditions: </span><code>*this</code><span> references </span><code>obj</code><span>.</span></li>
<li><span>Throws: Nothing.</span></li>
</ol><pre><code class="cpp hljs"><span class="token function">atomic_ref</span><span class="token punctuation">(</span><span class="token keyword">const</span> atomic_ref<span class="token operator">&amp;</span> ref<span class="token punctuation">)</span> <span class="token keyword">noexcept</span><span class="token punctuation">;</span>
</code></pre><ol start="8">
<li><span>Postconditions: </span><code>*this</code><span> references the object referenced by </span><code>ref</code><span>.</span></li>
</ol><pre><code>void store(<del>T</del><ins>value_type</ins> desired, memory_order order = memory_order::seq_cst) const noexcept
</code></pre><ol start="9">
<li><ins><span>Constraints: </span><code>is_const_v&lt;T&gt;</code><span> is </span><code>false</code><span>.</span></ins></li>
<li><span>Preconditions: </span><code>order</code><span> is </span><code>memory_order​::​relaxed</code><span>, </span><code>memory_order​::​release</code><span>, or </span><code>memory_order​::​seq_cst</code><span>.</span></li>
<li><span>Effects: Atomically replaces the value referenced by </span><code>*ptr</code><span> with the value of </span><code>desired</code><span>. Memory is affected according to the value of </span><code>order</code><span>.</span></li>
</ol><pre><code><del>T</del><ins>value_type</ins> operator=(<del>T</del><ins>value_type</ins> desired) const noexcept;
</code></pre><ol start="12">
<li><ins><span>Constraints: </span><code>is_const_v&lt;T&gt;</code><span> is </span><code>false</code><span>.</span></ins></li>
<li><span>Effects: Equivalent to:</span></li>
</ol><pre><code class="c++ hljs">  <span class="hljs-built_in">store</span>(desired);
  <span class="hljs-keyword">return</span> desired;
</code></pre><pre><code><del>T</del><ins>value_type</ins> load(memory_order order = memory_order::seq_cst) const noexcept;
</code></pre><ol start="14">
<li><span>Preconditions: </span><code>order</code><span> is </span><code>memory_order​::​relaxed</code><span>, </span><code>memory_order​::​consume</code><span>, </span><code>memory_order​::​acquire</code><span>, or </span><code>memory_order​::​seq_cst</code><span>.</span></li>
<li><span>Effects: Memory is affected according to the value of </span><code>order</code><span>.</span></li>
<li><span>Returns: Atomically returns the value referenced by </span><code>*ptr</code><span>.</span></li>
</ol><pre><code>operator <del>T</del><ins>value_type</ins>() const noexcept;
</code></pre><ol start="15">
<li><span>Effects: Equivalent to: </span><code>return load();</code></li>
</ol><pre><code><del>T</del><ins>value_type</ins> exchange(<del>T</del><ins>value_type</ins> desired, memory_order order = memory_order::seq_cst) const noexcept;
</code></pre><ol start="16">
<li><ins><span>Constraints: </span><code>is_const_v&lt;T&gt;</code><span> is </span><code>false</code><span>.</span></ins></li>
<li><span>Effects: Atomically replaces the value referenced by </span><code>*ptr</code><span> with </span><code>desired</code><span>. Memory is affected according to the value of </span><code>order</code><span>. This operation is an atomic read-modify-write operation ([intro.multithread]).</span></li>
<li><span>Returns: Atomically returns the value referenced by </span><code>*ptr</code><span> immediately before the effects.</span></li>
</ol><pre><code>bool compare_exchange_weak(<del>T</del><ins>value_type</ins>&amp; expected, <del>T</del><ins>value_type</ins> desired,
                           memory_order success, memory_order failure) const noexcept;

bool compare_exchange_strong(<del>T</del><ins>value_type</ins>&amp; expected, <del>T</del><ins>value_type</ins> desired,
                             memory_order success, memory_order failure) const noexcept;

bool compare_exchange_weak(<del>T</del><ins>value_type</ins>&amp; expected, <del>T</del><ins>value_type</ins> desired,
                           memory_order order = memory_order::seq_cst) const noexcept;

bool compare_exchange_strong(<del>T</del><ins>value_type</ins>&amp; expected, <del>T</del><ins>value_type</ins> desired,
                             memory_order order = memory_order::seq_cst) const noexcept;
</code></pre><ol start="19">
<li><ins><span>Constraints: </span><code>is_const_v&lt;T&gt;</code><span> is </span><code>false</code><span>.</span></ins></li>
<li><span>Preconditions: </span><code>failure</code><span> is </span><code>memory_order​::​relaxed</code><span>, </span><code>memory_order​::​consume</code><span>, </span><code>memory_order​::​acquire</code><span>, or </span><code>memory_order​::​seq_cst</code><span>.</span></li>
<li><span>Effects: Retrieves the value in </span><code>expected</code><span>. It then atomically compares the value representation of the value referenced by </span><code>*ptr</code><span> for equality with that previously retrieved from </span><code>expected</code><span>, and if </span><code>true</code><span>, replaces the value referenced by </span><code>*ptr</code><span> with that in </span><code>desired</code><span>. If and only if the comparison is </span><code>true</code><span>, memory is affected according to the value of </span><code>success</code><span>, and if the comparison is </span><code>false</code><span>, memory is affected according to the value of </span><code>failure</code><span>. When only one </span><code>memory_order</code><span> argument is supplied, the value of </span><code>success</code><span> is </span><code>order</code><span>, and the value of </span><code>failure</code><span> is </span><code>order</code><span> except that a value of </span><code>memory_order​::​acq_rel</code><span> shall be replaced by the value </span><code>memory_order​::​acquire</code><span> and a value of </span><code>memory_order​::​release</code><span> shall be replaced by the value </span><code>memory_order​::​relaxed</code><span>. If and only if the comparison is </span><code>false</code><span> then, after the atomic operation, the value in </span><code>expected</code><span> is replaced by the value read from the value referenced by </span><code>*ptr</code><span> during the atomic comparison. If the operation returns </span><code>true</code><span>, these operations are atomic read-modify-write operations ([intro.races]) on the value referenced by </span><code>*ptr</code><span>. Otherwise, these operations are atomic load operations on that memory.</span></li>
<li><span>Returns: The result of the comparison.</span></li>
<li><span>Remarks: A weak compare-and-exchange operation may fail spuriously. That is, even when the contents of memory referred to by </span><code>expected</code><span> and </span><code>ptr</code><span> are equal, it may return </span><code>false</code><span> and store back to expected the same memory contents that were originally there.</span><br>
<span>[Note 2: This spurious failure enables implementation of compare-and-exchange on a broader class of machines, e.g., load-locked store-conditional machines. A consequence of spurious failure is that nearly all uses of weak compare-and-exchange will be in a loop. When a compare-and-exchange is in a loop, the weak version will yield better performance on some platforms. When a weak compare-and-exchange would require a loop and a strong one would not, the strong one is preferable. — end note]</span></li>
</ol><pre><code>void wait(<del>T</del><ins>value_type</ins> old, memory_order order = memory_order::seq_cst) const noexcept;
</code></pre><ol start="22">
<li><span>Preconditions: </span><code>order</code><span> is </span><code>memory_order​::​relaxed</code><span>, </span><code>memory_order​::​consume</code><span>, </span><code>memory_order​::​acquire</code><span>, or </span><code>memory_order​::​seq_cst</code><span>.</span></li>
<li><span>Effects: Repeatedly performs the following steps, in order:</span><br>
<span>(23.1) Evaluates </span><code>load(order)</code><span> and compares its value representation for equality against that of </span><code>old</code><span>.</span><br>
<span>(23.2) If they compare unequal, returns.</span><br>
<span>(23.3) Blocks until it is unblocked by an atomic notifying operation or is unblocked spuriously.</span></li>
<li><span>Remarks: This function is an atomic waiting operation ([atomics.wait]) on atomic object </span><code>*ptr</code><span>.</span></li>
</ol><pre><code>void notify_one() const noexcept;</code></pre><ol start="25">
<li><span>Effects: Unblocks the execution of at least one atomic waiting operation on </span><code>*ptr</code><span> that is eligible to be unblocked ([atomics.wait]) by this call, if any such atomic waiting operations exist.</span></li>
<li><span>Remarks: This function is an atomic notifying operation ([atomics.wait]) on atomic object </span><code>*ptr</code><span>.</span></li>
</ol><pre><code>void notify_all() const noexcept;</code></pre><ol start="27">
<li><span>Effects: Unblocks the execution of all atomic waiting operations on </span><code>*ptr</code><span> that are eligible to be unblocked ([atomics.wait]) by this call.</span></li>
<li><span>Remarks: This function is an atomic notifying operation ([atomics.wait]) on atomic object </span><code>*ptr</code><span>.</span></li>
</ol><p><span>Modify </span><a href="https://eel.is/c++draft/atomics.ref.int" target="_blank" rel="noopener"><span>[atomics.ref.int]</span></a><span>:</span></p><p><span>33.5.7.3 Specializations for integral types[atomics.ref.int]</span></p><ol>
<li><span>There are specializations of the </span><code>atomic_ref</code><span> class template for </span><ins><span>all integral types except cv</span><code>bool</code></ins><del><span>the integral types </span><code>char</code><span>, </span><code>signed char</code><span>, </span><code>unsigned char</code><span>, </span><code>short</code><span>, </span><code>unsigned short</code><span>, </span><code>int</code><span>, </span><code>unsigned int</code><span>, </span><code>long</code><span>, </span><code>unsigned long</code><span>, </span><code>long long</code><span>, </span><code>unsigned long long</code><span>, </span><code>char8_t</code><span>, </span><code>char16_t</code><span>, </span><code>char32_t</code><span>, </span><code>wchar_t</code><span>, and any other types needed by the typedefs in the header </span>&lt;cstdint&gt;</del><span>. For each such </span><ins><span>possibly cv-qualified</span></ins><span> type </span><em><span>integral-type</span></em><span>, the specialization </span><code><span>atomic_ref&lt;</span><i><span>integral-type</span></i><span>&gt;</span></code><span> provides additional atomic operations appropriate to integral types.</span><br>
<span>[Note 1: The specialization </span><code>atomic_ref&lt;bool&gt;</code><span> uses the primary template ([atomics.ref.generic]). — end note]</span></li>
<li><ins><span>The program is ill-formed if </span><code>is_always_lock_free</code><span> is </span><code>false</code><span> and </span><code>is_volatile_v&lt;T&gt;</code><span> is </span><code>true</code><span>.</span></ins></li>
</ol><pre><code>namespace std {
  template&lt;&gt; struct atomic_ref&lt;<i>integral-type</i>&gt; {
  private:
    <i>integral-type</i>* ptr;         // <i>exposition only</i>

  public:
    using value_type = <ins>remove_cv_t&lt;</ins><i>integral-type</i><ins>&gt;</ins>;
    using difference_type = value_type;
    static constexpr size_t required_alignment = <i>implementation-defined</i>;

    static constexpr bool is_always_lock_free = <i>implementation-defined</i>;
    bool is_lock_free() const noexcept;

    explicit atomic_ref(<i>integral-type</i>&amp;);
    atomic_ref(const atomic_ref&amp;) noexcept;
    atomic_ref&amp; operator=(const atomic_ref&amp;) = delete;

    void store(<del><i>integral-type</i></del><ins>value_type</ins>, memory_order = memory_order::seq_cst) const noexcept;
    <del><i>integral-type</i></del><ins>value_type</ins> operator=(<del><i>integral-type</i></del><ins>value_type</ins>) const noexcept;
    <del><i>integral-type</i></del><ins>value_type</ins> load(memory_order = memory_order::seq_cst) const noexcept;
    operator <del><i>integral-type</i></del><ins>value_type</ins>() const noexcept;

    <del><i>integral-type</i></del><ins>value_type</ins> exchange(<del><i>integral-type</i></del><ins>value_type</ins>,
                           memory_order = memory_order::seq_cst) const noexcept;
    bool compare_exchange_weak(<del><i>integral-type</i></del><ins>value_type</ins>&amp;, <del><i>integral-type</i></del><ins>value_type</ins>,
                               memory_order, memory_order) const noexcept;
    bool compare_exchange_strong(<del><i>integral-type</i></del><ins>value_type</ins>&amp;, <del><i>integral-type</i></del><ins>value_type</ins>,
                                 memory_order, memory_order) const noexcept;
    bool compare_exchange_weak(<del><i>integral-type</i></del><ins>value_type</ins>&amp;, <del><i>integral-type</i></del><ins>value_type</ins>,
                               memory_order = memory_order::seq_cst) const noexcept;
    bool compare_exchange_strong(<del><i>integral-type</i></del><ins>value_type</ins>&amp;, <del><i>integral-type</i></del><ins>value_type</ins>,
                                 memory_order = memory_order::seq_cst) const noexcept;

    <del><i>integral-type</i></del><ins>value_type</ins> fetch_add(<del><i>integral-type</i></del><ins>value_type</ins>,
                            memory_order = memory_order::seq_cst) const noexcept;
    <del><i>integral-type</i></del><ins>value_type</ins> fetch_sub(<del><i>integral-type</i></del><ins>value_type</ins>,
                            memory_order = memory_order::seq_cst) const noexcept;
    <del><i>integral-type</i></del><ins>value_type</ins> fetch_and(<del><i>integral-type</i></del><ins>value_type</ins>,
                            memory_order = memory_order::seq_cst) const noexcept;
    <del><i>integral-type</i></del><ins>value_type</ins> fetch_or(<del><i>integral-type</i></del><ins>value_type</ins>,
                            memory_order = memory_order::seq_cst) const noexcept;
    <del><i>integral-type</i></del><ins>value_type</ins> fetch_xor(<del><i>integral-type</i></del><ins>value_type</ins>,
                            memory_order = memory_order::seq_cst) const noexcept;
    <del><i>integral-type</i></del><ins>value_type</ins> fetch_max(<del><i>integral-type</i></del><ins>value_type</ins>,
                            memory_order = memory_order::seq_cst) const noexcept;
    <del><i>integral-type</i></del><ins>value_type</ins> fetch_min(<del><i>integral-type</i></del><ins>value_type</ins>,
                            memory_order = memory_order::seq_cst) const noexcept;

    <del><i>integral-type</i></del><ins>value_type</ins> operator++(int) const noexcept;
    <del><i>integral-type</i></del><ins>value_type</ins> operator--(int) const noexcept;
    <del><i>integral-type</i></del><ins>value_type</ins> operator++() const noexcept;
    <del><i>integral-type</i></del><ins>value_type</ins> operator--() const noexcept;
    <del><i>integral-type</i></del><ins>value_type</ins> operator+=(<del><i>integral-type</i></del><ins>value_type</ins>) const noexcept;
    <del><i>integral-type</i></del><ins>value_type</ins> operator-=(<del><i>integral-type</i></del><ins>value_type</ins>) const noexcept;
    <del><i>integral-type</i></del><ins>value_type</ins> operator&amp;=(<del><i>integral-type</i></del><ins>value_type</ins>) const noexcept;
    <del><i>integral-type</i></del><ins>value_type</ins> operator|=(<del><i>integral-type</i></del><ins>value_type</ins>) const noexcept;
    <del><i>integral-type</i></del><ins>value_type</ins> operator^=(<del><i>integral-type</i></del><ins>value_type</ins>) const noexcept;

    void wait(<del><i>integral-type</i></del><ins>value_type</ins>, memory_order = memory_order::seq_cst) const noexcept;
    void notify_one() const noexcept;
    void notify_all() const noexcept;
  };
}
</code></pre><ol start="3">
<li><span>Descriptions are provided below only for members that differ from the primary template.</span></li>
<li><span>The following operations perform arithmetic computations. The correspondence among key, operator, and computation is specified in Table 148.</span></li>
</ol><pre><code><del><i>integral-type</i></del><ins>value_type</ins> fetch_key(<del><i>integral-type</i></del><ins>value_type</ins> operand,
  memory_order order = memory_order::seq_cst) const noexcept;
</code></pre><ol start="5">
<li><ins><span>Constraints: </span><code><span>is_const_v&lt;</span><i><span>integral-type</span></i><span>&gt;</span></code><span> is </span><code>false</code><span>.</span></ins></li>
<li><span>Effects: Atomically replaces the value referenced by </span><code>*ptr</code><span> with the result of the computation applied to the value referenced by </span><code>*ptr</code><span> and the given </span><code>operand</code><span>. Memory is affected according to the value of </span><code>order</code><span>. These operations are atomic read-modify-write operations ([intro.races]).</span></li>
<li><span>Returns: Atomically, the value referenced by </span><code>*ptr</code><span> immediately before the effects.</span></li>
<li><span>Remarks: Except for </span><code>fetch_max</code><span> and </span><code>fetch_min</code><span>, for signed integer types the result is as if the object value and parameters were converted to their corresponding unsigned types, the computation performed on those types, and the result converted back to the signed type.</span><br>
<span>[Note 2: There are no undefined results arising from the computation. — end note]</span></li>
<li><span>For </span><code>fetch_max</code><span> and </span><code>fetch_min</code><span>, the maximum and minimum computation is performed as if by </span><code>max</code><span> and </span><code>min</code><span> algorithms ([alg.min.max]), respectively, with the object value and the first parameter as the arguments.</span></li>
</ol><pre><code><del><i>integral-type</i></del><ins>value_type</ins>  operator <i>op</i>=(<del><i>integral-type</i></del><ins>value_type</ins>  operand) const noexcept;
</code></pre><ol start="10">
<li><ins><span>Constraints: </span><code><span>is_const_v&lt;</span><i><span>integral-type</span></i><span>&gt;</span></code><span> is </span><code>false</code><span>.</span></ins></li>
<li><span>Effects: Equivalent to: </span><code><span>return fetch_</span><i><span>key</span></i><span>(operand) </span><i><span>op</span></i><span> operand;</span></code></li>
</ol><p><span>Modify </span><a href="https://eel.is/c++draft/atomics.ref.float" target="_blank" rel="noopener"><span>[atomics.ref.float]</span></a><span>:</span></p><p><span>33.5.7.4 Specializations for floating-point types[atomics.ref.float]</span></p><ol>
<li><span>There are specializations of the </span><code>atomic_ref</code><span> class template for all </span><del><span>cv-unqualified</span></del><span> floating-point types. For each such </span><ins><span>possibly cv-qualified</span></ins><span> type </span><i><span>floating-point-type</span></i><span>, the specialization </span><code><span>atomic_ref&lt;</span><i><span>floating-point</span></i><span>&gt;</span></code><span> provides additional atomic operations appropriate to floating-point types.</span></li>
<li><ins><span>The program is ill-formed if </span><code>is_always_lock_free</code><span> is </span><code>false</code><span> and </span><code>is_volatile_v&lt;T&gt;</code><span> is </span><code>true</code><span>.</span></ins></li>
</ol><pre><code>namespace std {
  template&lt;&gt; struct atomic_ref&lt;<i>floating-point-type</i>&gt; {
  private:
    <i>floating-point-type</i>* ptr;   // exposition only

  public:
    using value_type = <ins>remove_cv_t&lt;</ins><i>floating-point-type</i><ins>&gt;</ins>;
    using difference_type = value_type;
    static constexpr size_t required_alignment = <i>implementation-defined</i>;

    static constexpr bool is_always_lock_free = <i>implementation-defined</i>;
    bool is_lock_free() const noexcept;

    explicit atomic_ref(<i>floating-point-type</i>&amp;);
    atomic_ref(const atomic_ref&amp;) noexcept;
    atomic_ref&amp; operator=(const atomic_ref&amp;) = delete;

    void store(<del><i>floating-point-type</i></del><ins>value_type</ins>, memory_order = memory_order::seq_cst) const noexcept;
    <del><i>floating-point-type</i></del><ins>value_type</ins> operator=(<del><i>floating-point-type</i></del><ins>value_type</ins>) const noexcept;
    <del><i>floating-point-type</i></del><ins>value_type</ins> load(memory_order = memory_order::seq_cst) const noexcept;
    operator <del><i>floating-point-type</i></del><ins>value_type</ins>() const noexcept;

    <del><i>floating-point-type</i></del><ins>value_type</ins> exchange(<del><i>floating-point-type</i></del><ins>value_type</ins>,
                                 memory_order = memory_order::seq_cst) const noexcept;
    bool compare_exchange_weak(<del><i>floating-point-type</i></del><ins>value_type</ins>&amp;, <del><i>floating-point-type</i></del><ins>value_type</ins>,
                               memory_order, memory_order) const noexcept;
    bool compare_exchange_strong(<del><i>floating-point-type</i></del><ins>value_type</ins>&amp;, <del><i>floating-point-type</i></del><ins>value_type</ins>,
                                 memory_order, memory_order) const noexcept;
    bool compare_exchange_weak(<del><i>floating-point-type</i></del><ins>value_type</ins>&amp;, <del><i>floating-point-type</i></del><ins>value_type</ins>,
                               memory_order = memory_order::seq_cst) const noexcept;
    bool compare_exchange_strong(<del><i>floating-point-type</i></del><ins>value_type</ins>&amp;, <del><i>floating-point-type</i></del><ins>value_type</ins>,
                                 memory_order = memory_order::seq_cst) const noexcept;

    <del><i>floating-point-type</i></del><ins>value_type</ins> fetch_add(<del><i>floating-point-type</i></del><ins>value_type</ins>,
                                  memory_order = memory_order::seq_cst) const noexcept;
    <del><i>floating-point-type</i></del><ins>value_type</ins> fetch_sub(<del><i>floating-point-type</i></del><ins>value_type</ins>,
                                  memory_order = memory_order::seq_cst) const noexcept;

    <del><i>floating-point-type</i></del><ins>value_type</ins> operator+=(<del><i>floating-point-type</i></del><ins>value_type</ins>) const noexcept;
    <del><i>floating-point-type</i></del><ins>value_type</ins> operator-=(<del><i>floating-point-type</i></del><ins>value_type</ins>) const noexcept;

    void wait(<del><i>floating-point-type</i></del><ins>value_type</ins>, memory_order = memory_order::seq_cst) const noexcept;
    void notify_one() const noexcept;
    void notify_all() const noexcept;
  };
}
</code></pre><ol start="3">
<li><span>Descriptions are provided below only for members that differ from the primary template.</span></li>
<li><span>The following operations perform arithmetic computations. The correspondence among key, operator, and computation is specified in Table 148.</span></li>
</ol><pre><code><del><i>floating-point-type</i></del><ins>value_type</ins> fetch_key(<del><i>floating-point-type</i></del><ins>value_type</ins> operand,
                          memory_order order = memory_order::seq_cst) const noexcept;
</code></pre><ol start="5">
<li><ins><span>Constraints: </span><code><span>is_const_v&lt;</span><i><span>floating-point-type</span></i><span>&gt;</span></code><span> is </span><code>false</code><span>.</span></ins></li>
<li><span>Effects: Atomically replaces the value referenced by </span><code>*ptr</code><span> with the result of the computation applied to the value referenced by </span><code>*ptr</code><span> and the given </span><code>operand</code><span>. Memory is affected according to the value of </span><code>order</code><span>. These operations are atomic read-modify-write operations ([intro.races]).</span></li>
<li><span>Returns: Atomically, the value referenced by </span><code>*ptr</code><span> immediately before the effects.</span></li>
<li><span>Remarks: If the result is not a representable value for its type ([expr.pre]), the result is unspecified, but the operations otherwise have no undefined behavior. Atomic arithmetic operations on </span><em><span>floating-point-type</span></em><span> should conform to the </span><code><span>std​::​numeric_limits&lt;</span><del><i><span>floating-point-type</span></i></del><ins><span>value_type</span></ins><span>&gt;</span></code><span> traits associated with the floating-point type ([limits.syn]). The floating-point environment ([cfenv]) for atomic arithmetic operations on </span><em><span>floating-point-type</span></em><span> may be different than the calling thread's floating-point environment.</span></li>
</ol><pre><code><del><i>floating-point-type</i></del><ins>value_type</ins> operator op=(<del><i>floating-point-type</i></del><ins>value_type</ins> operand) const noexcept;
</code></pre><ol start="9">
<li><ins><span>Constraints: </span><code><span>is_const_v&lt;</span><i><span>floating-point-type</span></i><span>&gt;</span></code><span> is </span><code>false</code><span>.</span></ins></li>
<li><span>Effects: Equivalent to: </span><code><span>return fetch_</span><i><span>key</span></i><span>(operand) </span><i><span>op</span></i><span> operand;</span></code></li>
</ol><p><span>Modify </span><a href="https://eel.is/c++draft/atomics.ref.pointer" target="_blank" rel="noopener"><span>[atomics.ref.pointer]</span></a><span>:</span></p><p><span>33.5.7.5 Partial specialization for pointers[atomics.ref.pointer]</span></p><ol>
<li><ins><span>There are specializations of the </span><code>atomic_ref</code><span> class template for all pointer-to-object types. For each such possibly cv-qualified type </span><em><span>pointer-type</span></em><span>, the specialization </span><code><span>atomic_ref&lt;</span><i><span>pointer-type</span></i><span>&gt;</span></code><span> provides additional atomic operations appropriate to pointer types.</span></ins></li>
<li><ins><span>The program is ill-formed if </span><code>is_always_lock_free</code><span> is </span><code>false</code><span> and </span><code>is_volatile_v&lt;T&gt;</code><span> is </span><code>true</code><span>.</span></ins></li>
</ol><pre><code>namespace std {
  template&lt;<del>class T</del>&gt; struct atomic_ref&lt;<del>T*</del><ins><i>pointer-type</i></ins>&gt; {
  private:
    <del>T*</del><ins><i>pointer-type</i></ins>* ptr;        // exposition only

  public:
    using value_type = <del>T*</del><ins>remove_cv_t&lt;<i>pointer-type</i>&gt;</ins>;
    using difference_type = ptrdiff_t;
    static constexpr size_t required_alignment = implementation-defined;

    static constexpr bool is_always_lock_free = implementation-defined;
    bool is_lock_free() const noexcept;

    explicit atomic_ref(<del>T*</del><ins><i>pointer-type</i></ins>&amp;);
    atomic_ref(const atomic_ref&amp;) noexcept;
    atomic_ref&amp; operator=(const atomic_ref&amp;) = delete;

    void store(<del>T*</del><ins>value_type</ins>, memory_order = memory_order::seq_cst) const noexcept;
    <del>T*</del><ins>value_type</ins> operator=(<del>T*</del><ins>value_type</ins>) const noexcept;
    <del>T*</del><ins>value_type</ins> load(memory_order = memory_order::seq_cst) const noexcept;
    operator <del>T*</del><ins>value_type</ins>() const noexcept;

    <del>T*</del><ins>value_type</ins> exchange(<del>T*</del><ins>value_type</ins>, memory_order = memory_order::seq_cst) const noexcept;
    bool compare_exchange_weak(<del>T*</del><ins>value_type</ins>&amp;, <del>T*</del><ins>value_type</ins>,
                               memory_order, memory_order) const noexcept;
    bool compare_exchange_strong(<del>T*</del><ins>value_type</ins>&amp;, <del>T*</del><ins>value_type</ins>,
                                 memory_order, memory_order) const noexcept;
    bool compare_exchange_weak(<del>T*</del><ins>value_type</ins>&amp;, <del>T*</del><ins>value_type</ins>,
                               memory_order = memory_order::seq_cst) const noexcept;
    bool compare_exchange_strong(<del>T*</del><ins>value_type</ins>&amp;, <del>T*</del><ins>value_type</ins>,
                                 memory_order = memory_order::seq_cst) const noexcept;

    <del>T*</del><ins>value_type</ins> fetch_add(difference_type, memory_order = memory_order::seq_cst) const noexcept;
    <del>T*</del><ins>value_type</ins> fetch_sub(difference_type, memory_order = memory_order::seq_cst) const noexcept;
    <del>T*</del><ins>value_type</ins> fetch_max(<del>T*</del><ins>value_type</ins>, memory_order = memory_order::seq_cst) const noexcept;
    <del>T*</del><ins>value_type</ins> fetch_min(<del>T*</del><ins>value_type</ins>, memory_order = memory_order::seq_cst) const noexcept;

    <del>T*</del><ins>value_type</ins> operator++(int) const noexcept;
    <del>T*</del><ins>value_type</ins> operator--(int) const noexcept;
    <del>T*</del><ins>value_type</ins> operator++() const noexcept;
    <del>T*</del><ins>value_type</ins> operator--() const noexcept;
    <del>T*</del><ins>value_type</ins> operator+=(difference_type) const noexcept;
    <del>T*</del><ins>value_type</ins> operator-=(difference_type) const noexcept;

    void wait(<del>T*</del><ins>value_type</ins>, memory_order = memory_order::seq_cst) const noexcept;
    void notify_one() const noexcept;
    void notify_all() const noexcept;
  };
}
</code></pre><ol start="3">
<li><span>Descriptions are provided below only for members that differ from the primary template.</span></li>
<li><span>The following operations perform arithmetic computations. The correspondence among key, operator, and computation is specified in Table 149.</span></li>
</ol><pre><code>
<del>T*</del><ins>value_type</ins> fetch_<i>key</i>(difference_type operand, memory_order order = memory_order::seq_cst) const noexcept;
</code></pre><ol start="5">
<li><ins><span>Constraints: </span><code><span>is_const_v&lt;</span><i><span>pointer-type</span></i><span>&gt;</span></code><span> is </span><code>false</code><span>.</span></ins></li>
<li><span>Mandates: </span><del><code><span>T</span></code></del><ins><code><span>remove_pointer_t&lt;</span><i><span>pointer-type</span></i><span>&gt;</span></code></ins><span> is a complete object type.</span></li>
<li><span>Effects: Atomically replaces the value referenced by </span><code>*ptr</code><span> with the result of the computation applied to the value referenced by </span><code>*ptr</code><span> and the given </span><code>operand</code><span>. Memory is affected according to the value of </span><code>order</code><span>. These operations are atomic read-modify-write operations ([intro.races]).</span></li>
<li><span>Returns: Atomically, the value referenced by </span><code>*ptr</code><span> immediately before the effects.</span></li>
<li><span>Remarks: The result may be an undefined address, but the operations otherwise have no undefined behavior.</span></li>
<li><span>For </span><code>fetch_max</code><span> and </span><code>fetch_min</code><span>, the maximum and minimum computation is performed as if by </span><code>max</code><span> and </span><code>min</code><span> algorithms ([alg.min.max]), respectively, with the object value and the first parameter as the arguments.</span><br>
<span>[Note 1: If the pointers point to different complete objects (or subobjects thereof), the </span><code>&lt;</code><span> operator does not establish a strict weak ordering (Table 29, [expr.rel]). — end note]</span></li>
</ol><pre><code>
<del>T*</del><ins>value_type</ins> operator <i>op</i>=(difference_type operand) const noexcept;
</code></pre><ol start="11">
<li><ins><span>Constraints: </span><code><span>is_const_v&lt;</span><i><span>pointer-type</span></i><span>&gt;</span></code><span> is </span><code>false</code><span>.</span></ins></li>
<li><span>Effects: Equivalent to: </span><code><span>return fetch_</span><i><span>key</span></i><span>(operand) </span><i><span>op</span></i><span> operand;</span></code></li>
</ol><p><span>Modify </span><a href="https://eel.is/c++draft/atomics.ref.memop" target="_blank" rel="noopener"><span>[atomics.ref.memop]</span></a><span>:</span></p><p><span>33.5.7.6 Member operators common to integers and pointers to objects[atomics.ref.memop]</span></p><ol>
<li><ins><span>Let </span><i><span>referred-type</span></i><span> be </span><i><span>pointer-type</span></i><span> for the specializations in [atomics.ref.pointer] and be </span><i><span>integral-type</span></i><span> for the specializations in [atomics.ref.int].</span></ins></li>
</ol><pre><code>value_type operator++(int) const noexcept;</code></pre><ol start="2">
<li><ins><span>Constraints: </span><code><span>is_const_v&lt;</span><i><span>referred-type</span></i><span>&gt;</span></code><span> is </span><code>false</code><span>.</span></ins></li>
<li><span>Effects: Equivalent to: </span><code>return fetch_add(1);</code></li>
</ol><pre><code>value_type operator--(int) const noexcept;</code></pre><ol start="4">
<li><ins><span>Constraints: </span><code><span>is_const_v&lt;</span><i><span>referred-type</span></i><span>&gt;</span></code><span> is </span><code>false</code><span>.</span></ins></li>
<li><span>Effects: Equivalent to: </span><code>return fetch_sub(1);</code></li>
</ol><pre><code>value_type operator++() const noexcept;</code></pre><ol start="6">
<li><ins><span>Constraints: </span><code><span>is_const_v&lt;</span><i><span>referred-type</span></i><span>&gt;</span></code><span> is </span><code>false</code><span>.</span></ins></li>
<li><span>Effects: Equivalent to: </span><code>return fetch_add(1) + 1;</code></li>
</ol><pre><code>value_type operator--() const noexcept;</code></pre><ol start="8">
<li><ins><span>Constraints: </span><code><span>is_const_v&lt;</span><i><span>referred-type</span></i><span>&gt;</span></code><span> is </span><code>false</code><span>.</span></ins></li>
<li><span>Effects: Equivalent to: </span><code>return fetch_sub(1) - 1;</code></li>
</ol></div>
    <div class="ui-toc dropup unselectable hidden-print" style="display:none;">
        <div class="pull-right dropdown">
            <a id="tocLabel" class="ui-toc-label btn btn-default" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false" title="Table of content">
                <i class="fa fa-bars"></i>
            </a>
            <ul id="ui-toc" class="ui-toc-dropdown dropdown-menu" aria-labelledby="tocLabel">
                <div class="toc"><ul class="nav">
<li><a href="#cv-qualified-types-in-atomic-and-atomic_ref" title="cv-qualified types in atomic and atomic_ref">cv-qualified types in atomic and atomic_ref</a><ul class="nav">
<li><a href="#Summary" title="Summary">Summary</a></li>
<li><a href="#Motivation" title="Motivation">Motivation</a></li>
<li><a href="#Resolution-for-stdatomic" title="Resolution for std::atomic">Resolution for std::atomic</a></li>
<li><a href="#Resolution-for-stdatomic_ref" title="Resolution for std::atomic_ref">Resolution for std::atomic_ref</a></li>
</ul>
</li>
</ul>
</div><div class="toc-menu"><a class="expand-toggle" href="#">Expand all</a><a class="back-to-top" href="#">Back to top</a><a class="go-to-bottom" href="#">Go to bottom</a></div>
            </ul>
        </div>
    </div>
    <div id="ui-toc-affix" class="ui-affix-toc ui-toc-dropdown unselectable hidden-print" data-spy="affix" style="top:17px;display:none;"  >
        <div class="toc"><ul class="nav">
<li><a href="#cv-qualified-types-in-atomic-and-atomic_ref" title="cv-qualified types in atomic and atomic_ref">cv-qualified types in atomic and atomic_ref</a><ul class="nav">
<li><a href="#Summary" title="Summary">Summary</a></li>
<li><a href="#Motivation" title="Motivation">Motivation</a></li>
<li><a href="#Resolution-for-stdatomic" title="Resolution for std::atomic">Resolution for std::atomic</a></li>
<li><a href="#Resolution-for-stdatomic_ref" title="Resolution for std::atomic_ref">Resolution for std::atomic_ref</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>
