<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2024-03-17" />
  <title>const prvalues in the conditional operator</title>
  <style>
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
      div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
      ul.task-list{list-style: none;}
      pre > code.sourceCode { white-space: pre; position: relative; }
      pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
      pre > code.sourceCode > span:empty { height: 1.2em; }
      code.sourceCode > span { color: inherit; text-decoration: inherit; }
      div.sourceCode { margin: 1em 0; }
      pre.sourceCode { margin: 0; }
      @media screen {
      div.sourceCode { overflow: auto; }
      }
      @media print {
      pre > code.sourceCode { white-space: pre-wrap; }
      pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
      }
      pre.numberSource code
        { counter-reset: source-line 0; }
      pre.numberSource code > span
        { position: relative; left: -4em; counter-increment: source-line; }
      pre.numberSource code > span > a:first-child::before
        { content: counter(source-line);
          position: relative; left: -1em; text-align: right; vertical-align: baseline;
          border: none; display: inline-block;
          -webkit-touch-callout: none; -webkit-user-select: none;
          -khtml-user-select: none; -moz-user-select: none;
          -ms-user-select: none; user-select: none;
          padding: 0 4px; width: 4em;
          color: #aaaaaa;
        }
      pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
      div.sourceCode
        {  background-color: #f6f8fa; }
      @media screen {
      pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
      }
      code span. { } /* Normal */
      code span.al { color: #ff0000; } /* Alert */
      code span.an { } /* Annotation */
      code span.at { } /* Attribute */
      code span.bn { color: #9f6807; } /* BaseN */
      code span.bu { color: #9f6807; } /* BuiltIn */
      code span.cf { color: #00607c; } /* ControlFlow */
      code span.ch { color: #9f6807; } /* Char */
      code span.cn { } /* Constant */
      code span.co { color: #008000; font-style: italic; } /* Comment */
      code span.cv { color: #008000; font-style: italic; } /* CommentVar */
      code span.do { color: #008000; } /* Documentation */
      code span.dt { color: #00607c; } /* DataType */
      code span.dv { color: #9f6807; } /* DecVal */
      code span.er { color: #ff0000; font-weight: bold; } /* Error */
      code span.ex { } /* Extension */
      code span.fl { color: #9f6807; } /* Float */
      code span.fu { } /* Function */
      code span.im { } /* Import */
      code span.in { color: #008000; } /* Information */
      code span.kw { color: #00607c; } /* Keyword */
      code span.op { color: #af1915; } /* Operator */
      code span.ot { } /* Other */
      code span.pp { color: #6f4e37; } /* Preprocessor */
      code span.re { } /* RegionMarker */
      code span.sc { color: #9f6807; } /* SpecialChar */
      code span.ss { color: #9f6807; } /* SpecialString */
      code span.st { color: #9f6807; } /* String */
      code span.va { } /* Variable */
      code span.vs { color: #9f6807; } /* VerbatimString */
      code span.wa { color: #008000; font-weight: bold; } /* Warning */
      code.diff {color: #898887}
      code.diff span.va {color: #006e28}
      code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
}
div.wrapper {
max-width: 60em;
margin: auto;
}
ul {
list-style-type: none;
padding-left: 2em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
a.self-link {
position: absolute;
top: 0;
left: calc(-1 * (3.5rem - 26px));
width: calc(3.5rem - 26px);
height: 2em;
text-align: center;
border: none;
transition: opacity .2s;
opacity: .5;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }

a.index:target {
display: inline;
}
.indexitems {
margin-left: 2em;
text-indent: -2em;
}
div.itemdescr {
margin-left: 3em;
}
.bnf {
font-family: serif;
margin-left: 40pt;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.ncbnf {
font-family: serif;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
}
.ncsimplebnf {
font-family: serif;
font-style: italic;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
background: inherit; 
}
span.textnormal {
font-style: normal;
font-family: serif;
white-space: normal;
display: inline-block;
}
span.rlap {
display: inline-block;
width: 0px;
}
span.descr { font-style: normal; font-family: serif; }
span.grammarterm { font-style: italic; }
span.term { font-style: italic; }
span.terminal { font-family: monospace; font-style: normal; }
span.nonterminal { font-style: italic; }
span.tcode { font-family: monospace; font-style: normal; }
span.textbf { font-weight: bold; }
span.textsc { font-variant: small-caps; }
a.nontermdef { font-style: italic; font-family: serif; }
span.emph { font-style: italic; }
span.techterm { font-style: italic; }
span.mathit { font-style: italic; }
span.mathsf { font-family: sans-serif; }
span.mathrm { font-family: serif; font-style: normal; }
span.textrm { font-family: serif; }
span.textsl { font-style: italic; }
span.mathtt { font-family: monospace; font-style: normal; }
span.mbox { font-family: serif; font-style: normal; }
span.ungap { display: inline-block; width: 2pt; }
span.textit { font-style: italic; }
span.texttt { font-family: monospace; }
span.tcode_in_codeblock { font-family: monospace; font-style: normal; }
span.phantom { color: white; }

span.math { font-style: normal; }
span.mathblock {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1.2em;
margin-bottom: 1.2em;
text-align: center;
}
span.mathalpha {
font-style: italic;
}
span.synopsis {
font-weight: bold;
margin-top: 0.5em;
display: block;
}
span.definition {
font-weight: bold;
display: block;
}
.codeblock {
margin-left: 1.2em;
line-height: 127%;
}
.outputblock {
margin-left: 1.2em;
line-height: 127%;
}
div.itemdecl {
margin-top: 2ex;
}
code.itemdeclcode {
white-space: pre;
display: block;
}
span.textsuperscript {
vertical-align: super;
font-size: smaller;
line-height: 0;
}
.footnotenum { vertical-align: super; font-size: smaller; line-height: 0; }
.footnote {
font-size: small;
margin-left: 2em;
margin-right: 2em;
margin-top: 0.6em;
margin-bottom: 0.6em;
}
div.minipage {
display: inline-block;
margin-right: 3em;
}
div.numberedTable {
text-align: center;
margin: 2em;
}
div.figure {
text-align: center;
margin: 2em;
}
table {
border: 1px solid black;
border-collapse: collapse;
margin-left: auto;
margin-right: auto;
margin-top: 0.8em;
text-align: left;
hyphens: none; 
}
td, th {
padding-left: 1em;
padding-right: 1em;
vertical-align: top;
}
td.empty {
padding: 0px;
padding-left: 1px;
}
td.left {
text-align: left;
}
td.right {
text-align: right;
}
td.center {
text-align: center;
}
td.justify {
text-align: justify;
}
td.border {
border-left: 1px solid black;
}
tr.rowsep, td.cline {
border-top: 1px solid black;
}
tr.even, tr.odd {
border-bottom: 1px solid black;
}
tr.capsep {
border-top: 3px solid black;
border-top-style: double;
}
tr.header {
border-bottom: 3px solid black;
border-bottom-style: double;
}
th {
border-bottom: 1px solid black;
}
span.centry {
font-weight: bold;
}
div.table {
display: block;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 90%;
}
span.indented {
display: block;
margin-left: 2em;
margin-bottom: 1em;
margin-top: 1em;
}
ol.enumeratea { list-style-type: none; background: inherit; }
ol.enumerate { list-style-type: none; background: inherit; }

code.sourceCode > span { display: inline; }
</style>
  <style type="text/css">a {
color : #4183C4;
text-decoration: underline;
}
a.marginalized {
text-decoration: none;
}
a.self-link {
text-decoration: none;
}
h1#toctitle {
border-bottom: 1px solid #cccccc;
}
#TOC li {
margin-top: 1px;
margin-bottom: 1px;
}
#TOC ul>li:before { display: none; }
h3.subtitle { margin-top: -15px; }
h1:target { background-color: transparent; }
h2:target { background-color: transparent; }
h3:target { background-color: transparent; }
h4:target { background-color: transparent; }
h5:target { background-color: transparent; }
h6:target { background-color: transparent; }
code span.co { font-family: monospace; }
table tr {
background-color: white;
}
table tr:nth-child(2n) {
background-color: #f6f8fa;
}
#title-block-header > table tr:nth-child(2n) {
background-color: white;
}
td > div.sourceCode {
background-color: inherit;
}
table {
border-collapse: collapse;
}
table td, table th {
border: 1px solid #cccccc;
}
table th {
border-bottom: 1px solid black;
text-align: center;
}
table tr:first-child th {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child,
table tr th:first-child {
border-left: 0;
}
table tr td:last-child,
table tr th:last-child {
border-right: 0;
}
table tbody tr:first-child td {
border-top: 1px solid black;
}
#title-block-header td { border: 0; }
@media all {
body {
margin: 2em;
}
}
@media screen and (min-width: 480px) {
body {
margin: 5em;
}
}
#refs code{padding-left: 0px; text-indent: 0px;}
:root {
--diff-ins: #e6ffed;
--diff-strongins: #acf2bd;
--diff-del: #ffdddd;
--diff-strongdel: #ff8888;
}
span.diffins {
background-color: var(--diff-strongins);
}
span.diffdel {
background-color: var(--diff-strongdel);
}
div.rm { text-decoration: line-through; }
div.rm code.sourceCode { text-decoration: line-through; }
div.addu, span.addu {
color: #006e28;
background-color: var(--diff-ins);
}

div.rm pre, div.add pre { background-color: #f6f8fa; }
div.addu pre { background-color: var(--diff-ins); }
div.add, div.add pre { background-color: var(--diff-ins); }
div.addu blockquote {
border-left: 4px solid #00a000;
padding: 0 15px;
color: #006e28;
text-decoration: none;
}
div.addu blockquote code.sourceCode { text-decoration: none; }
div.addu blockquote pre { text-decoration: none; }
div.addu blockquote pre code { text-decoration: none; }
div.quote {
border-left: 7px solid #ccc;
background: #f9f9f9;
margin: 1.5em 10px;
padding-left: 20px;
}
code.diff span.va { color: #000000; background-color: var(--diff-ins); }
code.diff span.st { color: #000000; background-color: var(--diff-del); }
</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
  
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">const prvalues in the conditional operator</h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3177R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-03-17</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      EWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Barry Revzin<br>&lt;<a href="mailto:barry.revzin@gmail.com" class="email">barry.revzin@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>

</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#introduction"><span class="toc-section-number">1</span> Introduction<span></span></a>
<ul>
<li><a href="#pessimizing-assignment"><span class="toc-section-number">1.1</span> Pessimizing Assignment<span></span></a></li>
<li><a href="#extra-wrapping"><span class="toc-section-number">1.2</span> Extra Wrapping<span></span></a></li>
</ul></li>
<li><a href="#status-quo"><span class="toc-section-number">2</span> Status Quo<span></span></a></li>
<li><a href="#proposal"><span class="toc-section-number">3</span> Proposal<span></span></a></li>
<li><a href="#bibliography"><span class="toc-section-number">4</span> References<span></span></a></li>
</ul>
</div>
<style type="text/css">
td.orange { background-color: #ffa500; }
td.yellow { background-color: #ffff00; }
span.orange { background-color: #ffa500; }
span.yellow { background-color: #ffff00; }
</style>
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="introduction"><span class="header-section-number">1</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>The conditional (or ternary) operator (<span>7.6.16 <a href="https://wg21.link/expr.cond">[expr.cond]</a></span>) is one of the most surprisingly complex parts of the language. The goal of this paper is to fix a surprising interaction in it, that is also causing an issue that we’d otherwise have to resolve in the library.</p>
<p>The issue at hand is about this:</p>
<blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a><span class="co">// a version of declval but which doesn&#39;t add rvalue references</span></span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb1-3"><a href="#cb1-3"></a><span class="kw">auto</span> make<span class="op">()</span> <span class="op">-&gt;</span> T;</span>
<span id="cb1-4"><a href="#cb1-4"></a></span>
<span id="cb1-5"><a href="#cb1-5"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T, <span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb1-6"><a href="#cb1-6"></a><span class="kw">using</span> cond <span class="op">=</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">true</span> <span class="op">?</span> make<span class="op">&lt;</span>T<span class="op">&gt;()</span> <span class="op">:</span> make<span class="op">&lt;</span>U<span class="op">&gt;())</span>;</span>
<span id="cb1-7"><a href="#cb1-7"></a></span>
<span id="cb1-8"><a href="#cb1-8"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb1-9"><a href="#cb1-9"></a><span class="kw">using</span> cref <span class="op">=</span> cond<span class="op">&lt;</span>T, T <span class="kw">const</span><span class="op">&amp;&gt;</span>;</span></code></pre></div>
</blockquote>
<p>What do you expect the type of <code class="sourceCode cpp">cref<span class="op">&lt;</span>T<span class="op">&gt;</span></code> to be? Well, it’s obviously some kind of a <code class="sourceCode cpp">T</code> (since both sides are <code class="sourceCode cpp">T</code>, so nothing to convert). It cannot be <code class="sourceCode cpp">T<span class="op">&amp;</span></code> (which cannot bind to either operand) or <code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code> (which cannot bind to <code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>). It could potentially have been <code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code> (to do conditional lifetime extension) but it would be odd to elevate the prvalue to lvalue in this context. <code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code> is a type that most people never think of, and I think in this context we should also not think about it.</p>
<p>I think at this point many people would expect that this leaves <code class="sourceCode cpp">T</code> amongst the options and conclude that <code class="sourceCode cpp">cref<span class="op">&lt;</span>T<span class="op">&gt;</span></code> is simply <code class="sourceCode cpp">T</code>. But it turns out that’s not quite the case. For <em>scalar types</em>, <code class="sourceCode cpp">cref<span class="op">&lt;</span>T<span class="op">&gt;</span></code> is <code class="sourceCode cpp">T</code>. But for <em>class types</em>, <code class="sourceCode cpp">cref<span class="op">&lt;</span>T<span class="op">&gt;</span></code> is actually <code class="sourceCode cpp">T <span class="kw">const</span></code>.</p>
<p>This has some negative consequences, in addition to simply being a surprising difference.</p>
<h2 data-number="1.1" id="pessimizing-assignment"><span class="header-section-number">1.1</span> Pessimizing Assignment<a href="#pessimizing-assignment" class="self-link"></a></h2>
<p>First, consider this case:</p>
<blockquote>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1"></a><span class="kw">auto</span> get<span class="op">()</span> <span class="op">-&gt;</span> T;</span>
<span id="cb2-2"><a href="#cb2-2"></a><span class="kw">auto</span> lookup<span class="op">()</span> <span class="op">-&gt;</span> T <span class="kw">const</span><span class="op">&amp;</span>;</span>
<span id="cb2-3"><a href="#cb2-3"></a></span>
<span id="cb2-4"><a href="#cb2-4"></a>T obj;</span>
<span id="cb2-5"><a href="#cb2-5"></a>obj <span class="op">=</span> <em>flag</em> <span class="op">?</span> get<span class="op">()</span> <span class="op">:</span> lookup<span class="op">()</span>;</span></code></pre></div>
</blockquote>
<p>For scalar types, this is a copy anyway, doesn’t matter. But for class types, because the right-hand side is a <code class="sourceCode cpp">T <span class="kw">const</span></code>, that means that this is always a copy-assignment. Or, put differently, this is the different behavior based on whether the conditional operator yielded <code class="sourceCode cpp">T <span class="kw">const</span></code> or <code class="sourceCode cpp">T</code> in this case:</p>
<table>
<tr>
<th>
<code class="sourceCode cpp"><em>flag</em></code>
</th>
<th>
<code class="sourceCode cpp">T <span class="kw">const</span></code>
</th>
<th>
<code class="sourceCode cpp">T</code>
</th>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="kw">true</span></code>
</td>
<td>
copy assignment
</td>
<td>
move assignment
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp"><span class="kw">false</span></code>
</td>
<td>
copy construction then copy assignment
</td>
<td>
copy construction then move assignment
</td>
</tr>
</table>
<p>Note that either way this is less efficient than <code class="sourceCode cpp"><span class="cf">if</span> <span class="op">(</span><em>flag</em><span class="op">)</span> <span class="op">{</span> obj <span class="op">=</span> get<span class="op">()</span>; <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span> obj <span class="op">=</span> lookup<span class="op">()</span>; <span class="op">}</span></code> which is either a move assignment or a copy assignment without the extra potential copy construction, which is unfortunate.</p>
<p>This already seems like a relic of a pre-move-semantics era.</p>
<h2 data-number="1.2" id="extra-wrapping"><span class="header-section-number">1.2</span> Extra Wrapping<a href="#extra-wrapping" class="self-link"></a></h2>
<p>A second issue comes on up on the library side with ranges.</p>
<p>C++23 introduced a <code class="sourceCode cpp">views<span class="op">::</span>as_const</code> <span class="citation" data-cites="P2278R4">[<a href="#ref-P2278R4" role="doc-biblioref">P2278R4</a>]</span> which is a range adaptor that tries to wrap a range, if necessary, to make it a constant range. It detects whether such wrapping is necessary by checking to see if the range’s reference type would change by wrapping. That formula is, from <span>25.5.3.2 <a href="https://wg21.link/const.iterators.alias">[const.iterators.alias]</a></span></p>
<blockquote>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1"></a><span class="kw">template</span><span class="op">&lt;</span>indirectly_readable It<span class="op">&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2"></a>  <span class="kw">using</span> iter_const_reference_t <span class="op">=</span></span>
<span id="cb3-3"><a href="#cb3-3"></a>    common_reference_t<span class="op">&lt;</span><span class="kw">const</span> iter_value_t<span class="op">&lt;</span>It<span class="op">&gt;&amp;&amp;</span>, iter_reference_t<span class="op">&lt;</span>It<span class="op">&gt;&gt;</span>;</span>
<span id="cb3-4"><a href="#cb3-4"></a></span>
<span id="cb3-5"><a href="#cb3-5"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> It<span class="op">&gt;</span></span>
<span id="cb3-6"><a href="#cb3-6"></a>  <span class="kw">concept</span> <em>constant-iterator</em> <span class="op">=</span>                                                   <span class="co">// exposition only</span></span>
<span id="cb3-7"><a href="#cb3-7"></a>    input_iterator<span class="op">&lt;</span>It<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> same_as<span class="op">&lt;</span>iter_const_reference_t<span class="op">&lt;</span>It<span class="op">&gt;</span>, iter_reference_t<span class="op">&lt;</span>It<span class="op">&gt;&gt;</span>;</span>
<span id="cb3-8"><a href="#cb3-8"></a></span>
<span id="cb3-9"><a href="#cb3-9"></a><span class="kw">template</span><span class="op">&lt;</span>input_iterator I<span class="op">&gt;</span></span>
<span id="cb3-10"><a href="#cb3-10"></a>  <span class="kw">using</span> const_iterator <span class="op">=</span> <em>see below</em>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_1" id="pnum_1">1</a></span> <em>Result</em>: If <code class="sourceCode cpp">I</code> models <code class="sourceCode cpp"><em>constant-iterator</em></code>, <code class="sourceCode cpp">I</code>. Otherwise, <code class="sourceCode cpp">basic_const_iterator<span class="op">&lt;</span>I<span class="op">&gt;</span></code>.</p>
</blockquote>
<p>Now, consider an iterator over a non-proxy prvalue:</p>
<blockquote>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb4-2"><a href="#cb4-2"></a><span class="kw">struct</span> Priterator <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3"></a>  <span class="kw">using</span> value_type <span class="op">=</span> T<span class="op">:</span></span>
<span id="cb4-4"><a href="#cb4-4"></a>  <span class="kw">auto</span> <span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</span> <span class="op">-&gt;</span> T;</span>
<span id="cb4-5"><a href="#cb4-5"></a></span>
<span id="cb4-6"><a href="#cb4-6"></a>  <span class="co">// other stuff</span></span>
<span id="cb4-7"><a href="#cb4-7"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>While <code class="sourceCode cpp">common_reference</code> is the most complex type trait in the standard library, in this particular case it reduces to the much more manageable:</p>
<blockquote>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2"></a><span class="kw">auto</span> make<span class="op">()</span> <span class="op">-&gt;</span> T;</span>
<span id="cb5-3"><a href="#cb5-3"></a></span>
<span id="cb5-4"><a href="#cb5-4"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> I<span class="op">&gt;</span></span>
<span id="cb5-5"><a href="#cb5-5"></a><span class="kw">using</span> const_reference_t <span class="op">=</span> cond<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span> <span class="kw">const</span><span class="op">&amp;&amp;</span>, iter_reference_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span>;</span></code></pre></div>
</blockquote>
<p>Which, for <code class="sourceCode cpp">Priterator<span class="op">&lt;</span>T<span class="op">&gt;</span></code>, is <code class="sourceCode cpp">cond<span class="op">&lt;</span>T <span class="kw">const</span><span class="op">&amp;&amp;</span>, T<span class="op">&gt;</span></code>.</p>
<p>This is the same construct we saw at the beginning of the paper, just that it’s a <code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code> instead of a <code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>. But the rules end up being the same: if <code class="sourceCode cpp">T</code> is a scalar type, <code class="sourceCode cpp">const_reference_t<span class="op">&lt;</span>T<span class="op">&gt;</span></code> is <code class="sourceCode cpp">T</code>. If <code class="sourceCode cpp">T</code> is a class type, then <code class="sourceCode cpp">const_reference_t<span class="op">&lt;</span>T<span class="op">&gt;</span></code> is <code class="sourceCode cpp">T <span class="kw">const</span></code>.</p>
<p>The result of this is that <code class="sourceCode cpp">Priterator<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code> <em>is</em> considered a constant iterator (because its <code class="sourceCode cpp">iter_const_reference_t</code> is <code class="sourceCode cpp"><span class="dt">int</span></code>, which is the same as its reference type) while <code class="sourceCode cpp">Priterator<span class="op">&lt;</span>SomeClass<span class="op">&gt;</span></code> <em>is not</em> considered a constant iterator (because its <code class="sourceCode cpp">iter_const_reference_t</code> becomes <code class="sourceCode cpp">SomeClass <span class="kw">const</span></code>, which is now a different type). Which means that a range of prvalue class type isn’t considered a constant range, and <code class="sourceCode cpp">views<span class="op">::</span>as_const</code> would pointlessly wrap it.</p>
<p>This isn’t just unnecessary wrapping and template instantiation - this now means instead of a range of prvalues, we end up with a range of <em>const</em> prvalues - which means copying when we could have potentially been moving.</p>
<p>At the very least, this is an issue we have to solve in the library (whether by special-casing this in the <code class="sourceCode cpp"><em>constant-iterator</em></code> logic or, less desirably, in the <code class="sourceCode cpp">common_reference</code> logic). But this isn’t uniquely a problem with <code class="sourceCode cpp">views<span class="op">::</span>as_const</code>, it’s simply the utility in which I first ran into this issue.</p>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="status-quo"><span class="header-section-number">2</span> Status Quo<a href="#status-quo" class="self-link"></a></h1>
<p>The conditional operator between two operands of the same underlying type (excluding value category and const-ness) produces the following today for scalar vs class types:</p>
<table>
<thead>
<tr class="header" style="text-align:center">
<th>
<strong><code class="sourceCode cpp"><span class="op">?:</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T</code>
</th>
<th>
<strong><code class="sourceCode cpp">T <span class="kw">const</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T<span class="op">&amp;</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code>
</th>
</tr>
</thead>
<tbody>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T</code>
</th>
<td>
<code class="sourceCode cpp">T</code>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td>
<code class="sourceCode cpp">T</code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td>
<code class="sourceCode cpp">T</code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T<span class="op">&amp;</span></code>
</td>
<td>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T<span class="op">&amp;</span></code>
</td>
<td>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
</td>
<td>
<code class="sourceCode cpp">T</code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code>
</td>
<td>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code>
</td>
</tr>
</tbody>
</table>
<p>For most of the entries, the result of the conditional operator is the same regardless of whether <code class="sourceCode cpp">T</code> is a scalar type or a class type. For all of the marked entries (whether <span class="yellow">yellow</span> or <span class="orange">orange</span>), the current behavior is that scalar types produce <code class="sourceCode cpp">T</code> and class types produce <code class="sourceCode cpp">T <span class="kw">const</span></code>.</p>
<p>These themselves can be divided into two groups:</p>
<ul>
<li>the entries marked <span class="yellow">yellow</span> have one operand that starts out as a const prvalue (i.e. <code class="sourceCode cpp">T <span class="kw">const</span></code>).</li>
<li>the entries marked <span class="orange">orange</span> have neither operand operand as a const prvalue.</li>
</ul>
<p>Now, for those entries marked <span class="orange">orange</span> (including the two cases examined in this paper so far in the first row), the language is materializing a const prvalue itself. This just seems erroneous - the language shouldn’t be doing this.</p>
<p>For those entries marked <span class="yellow">yellow</span>, there was <em>already</em> a const prvalue. Here the question is different. Did the user really intend to create a const prvalue? If they did, maybe we should respect that intention. It’s not entirely without merit to do so - it used to be a recommendation for functions to return <code class="sourceCode cpp">T <span class="kw">const</span></code> so that <code class="sourceCode cpp">f<span class="op">()</span> <span class="op">=</span> x;</code> would be ill-formed. Although that recommendation went out of style with the adoption of move semantics (since doing so pessimizes assignment from <code class="sourceCode cpp">f<span class="op">()</span></code>) and with the adoption of ref-qualifiers for assignment (although these still don’t seem to be very widely used). These cases also strike me as less important overall, simply because const prvalues don’t come up very often (and will come up even less if we fix the <span class="orange">orange</span>s).</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="proposal"><span class="header-section-number">3</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>There are two potential proposals here: the <em>weak</em> proposal and the <em>strong</em> proposal.</p>
<p>The <em>weak</em> proposal: if both operands have the same underlying type (excluding value category and const), then the result of the conditional operator should only be a const prvalue if at least one of the operands is a const prvalue. Otherwise, it should be a non-const prvalue. That is, we change the <span class="orange">orange</span> entries below to be <code class="sourceCode cpp">T</code> for both scalar and class types:</p>
<table>
<thead>
<tr class="header" style="text-align:center">
<th>
<strong><code class="sourceCode cpp"><span class="op">?:</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T</code>
</th>
<th>
<strong><code class="sourceCode cpp">T <span class="kw">const</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T<span class="op">&amp;</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code>
</th>
</tr>
</thead>
<tbody>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T</code>
</th>
<td>
<code class="sourceCode cpp">T</code>
</td>
<td>
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td>
<code class="sourceCode cpp">T</code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code>
</td>
<td>
<code class="sourceCode cpp">T</code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td>
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td>
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td>
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td>
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T<span class="op">&amp;</span></code>
</td>
<td>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T<span class="op">&amp;</span></code>
</td>
<td>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
</td>
<td>
<code class="sourceCode cpp">T</code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code>
</td>
<td>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code>
</td>
</tr>
</tbody>
</table>
<p>The <em>strong</em> proposal: if both operands have the same underlying type (excluding value category and const), then the result of the conditional operator should never be a const prvalue (i.e. do as the <code class="sourceCode cpp"><span class="dt">int</span></code>s do). That is, we change all of the <span class="orange">orange</span> and <span class="yellow">yellow</span> entries to just be <code class="sourceCode cpp">T</code> for both scalar and class types:</p>
<table>
<thead>
<tr class="header" style="text-align:center">
<th>
<strong><code class="sourceCode cpp"><span class="op">?:</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T</code>
</th>
<th>
<strong><code class="sourceCode cpp">T <span class="kw">const</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T<span class="op">&amp;</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code>
</th>
</tr>
</thead>
<tbody>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T</code>
</th>
<td>
<code class="sourceCode cpp">T</code>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code>
</td>
<td>
<code class="sourceCode cpp">T</code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code>
</td>
<td>
<code class="sourceCode cpp">T</code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T<span class="op">&amp;</span></code>
</td>
<td>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T<span class="op">&amp;</span></code>
</td>
<td>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
</td>
<td>
<code class="sourceCode cpp">T</code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code>
</td>
<td>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code>
</td>
</tr>
</tbody>
</table>
<p>The weak proposal is sufficient to address the <a href="#pessimizing-assignment">pessimizing assignment issue</a> and the <a href="#extra-wrapping">const wrapping issue</a>.</p>
<p>Notably, one odd quirk of the strong proposal is that the type of <code class="sourceCode cpp">cond<span class="op">&lt;</span>T, T<span class="op">&gt;</span></code> is <code class="sourceCode cpp">T</code> for all types, value categories, and const. Except one: <code class="sourceCode cpp">T <span class="kw">const</span></code>. In the strong proposal, <code class="sourceCode cpp">cond<span class="op">&lt;</span>T <span class="kw">const</span>, T <span class="kw">const</span><span class="op">&gt;</span></code> becomes <code class="sourceCode cpp">T</code>. Now, it technically is already just <code class="sourceCode cpp">T</code> for scalar types - but it’s not possible to even have a const prvalue of scalar type, so this doesn’t really matter. So we could alter the strong proposal to say that <code class="sourceCode cpp">cond<span class="op">&lt;</span>T, U<span class="op">&gt;</span></code> is only ever a const prvalue in the specific case of <code class="sourceCode cpp">cond<span class="op">&lt;</span>T <span class="kw">const</span>, T <span class="kw">const</span><span class="op">&gt;</span></code> - otherwise all prvalues are non-const. This would still technically give different answers between scalar and class types, but not in a meaningfully observed way. This last version would produce this outcome (preserving the status quo for specifically <code class="sourceCode cpp">cond<span class="op">&lt;</span>T <span class="kw">const</span>, T <span class="kw">const</span><span class="op">&gt;</span></code>):</p>
<table>
<thead>
<tr class="header" style="text-align:center">
<th>
<strong><code class="sourceCode cpp"><span class="op">?:</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T</code>
</th>
<th>
<strong><code class="sourceCode cpp">T <span class="kw">const</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T<span class="op">&amp;</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code>
</th>
<th>
<strong><code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code>
</th>
</tr>
</thead>
<tbody>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T</code>
</th>
<td>
<code class="sourceCode cpp">T</code>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code>
</td>
<td>
<code class="sourceCode cpp">T</code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code>
</td>
<td>
<code class="sourceCode cpp">T</code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T</code> | <code class="sourceCode cpp">T <span class="kw">const</span></code>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code>
</td>
<td class="yellow">
<code class="sourceCode cpp">T</code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T<span class="op">&amp;</span></code>
</td>
<td>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T<span class="op">&amp;</span></code>
</td>
<td>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
</td>
<td>
<code class="sourceCode cpp">T</code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;</span></code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code>
</td>
<td class="orange">
<code class="sourceCode cpp">T</code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T<span class="op">&amp;&amp;</span></code>
</td>
<td>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code>
</td>
</tr>
<tr style="text-align:center">
<th>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
<code class="sourceCode cpp">T <span class="kw">const</span><span class="op">&amp;&amp;</span></code>
</td>
</tr>
</tbody>
</table>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">4</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references hanging-indent" role="doc-bibliography">
<div id="ref-P2278R4">
<p>[P2278R4] Barry Revzin. 2022-06-17. cbegin should always return a constant iterator. <br />
<a href="https://wg21.link/p2278r4">https://wg21.link/p2278r4</a></p>
</div>
</div>
</div>
</div>
</body>
</html>
