<!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="2025-02-16" />
  <title>`std::constant_wrapper`</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.csl-block{margin-left: 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; }
      .sourceCode { overflow: visible; }
      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;
text-align: justify;
}
@media screen and (max-width: 30em) {
body {
margin: 1.5em;
}
}
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>
  <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"><code class="sourceCode default">std::constant_wrapper</code></h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2781R6</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2025-02-16</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>
      LEWG<br>
      LWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Hana Dusíková<br>&lt;<a href="mailto:hanicka@hanicka.net" class="email">hanicka@hanicka.net</a>&gt;<br>
      Matthias Kretz<br>&lt;<a href="mailto:m.kretz@gsi.de" class="email">m.kretz@gsi.de</a>&gt;<br>
      Zach Laine<br>&lt;<a href="mailto:whatwasthataddress@gmail.com" class="email">whatwasthataddress@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="#changelog" id="toc-changelog"><span class="toc-section-number">1</span> Changelog<span></span></a>
<ul>
<li><a href="#changes-since-r0" id="toc-changes-since-r0"><span class="toc-section-number">1.1</span> Changes since
R0<span></span></a></li>
<li><a href="#changes-since-r1" id="toc-changes-since-r1"><span class="toc-section-number">1.2</span> Changes since
R1<span></span></a></li>
<li><a href="#changes-since-r2" id="toc-changes-since-r2"><span class="toc-section-number">1.3</span> Changes since
R2<span></span></a></li>
<li><a href="#changes-since-r3" id="toc-changes-since-r3"><span class="toc-section-number">1.4</span> Changes since
R3<span></span></a></li>
<li><a href="#changes-since-r4" id="toc-changes-since-r4"><span class="toc-section-number">1.5</span> Changes since
R4<span></span></a></li>
<li><a href="#changes-since-r5" id="toc-changes-since-r5"><span class="toc-section-number">1.6</span> Changes since
R5<span></span></a></li>
</ul></li>
<li><a href="#relationship-to-previous-work" id="toc-relationship-to-previous-work"><span class="toc-section-number">2</span> Relationship to previous
work<span></span></a></li>
<li><a href="#the-ergonomics-of-stdintegral_constantint-are-bad" id="toc-the-ergonomics-of-stdintegral_constantint-are-bad"><span class="toc-section-number">3</span> The ergonomics of <code class="sourceCode default">std::integral_constant&lt;int&gt;</code> are
bad<span></span></a>
<ul>
<li><a href="#replacing-the-uses-of-stdintegral_constant-is-not-enough" id="toc-replacing-the-uses-of-stdintegral_constant-is-not-enough"><span class="toc-section-number">3.1</span> Replacing the uses of
<code class="sourceCode default">std::integral_constant</code> is not
enough<span></span></a></li>
<li><a href="#the-difference-in-template-parameters-to-stdconstant_wrapper-and-stdcw" id="toc-the-difference-in-template-parameters-to-stdconstant_wrapper-and-stdcw"><span class="toc-section-number">3.2</span> The difference in template
parameters to
<code class="sourceCode default">std::constant_wrapper</code> and
<code class="sourceCode default">std::cw</code><span></span></a></li>
</ul></li>
<li><a href="#the-type-of-x" id="toc-the-type-of-x"><span class="toc-section-number">4</span> The type of
<code class="sourceCode default">X</code><span></span></a></li>
<li><a href="#making-constant_wrapper-more-useful" id="toc-making-constant_wrapper-more-useful"><span class="toc-section-number">5</span> Making
<code class="sourceCode default">constant_wrapper</code> more
useful<span></span></a></li>
<li><a href="#what-about-strings" id="toc-what-about-strings"><span class="toc-section-number">6</span> What about
strings?<span></span></a></li>
<li><a href="#an-example-using-operator" id="toc-an-example-using-operator"><span class="toc-section-number">7</span> An example using
<code class="sourceCode default">operator()</code><span></span></a></li>
<li><a href="#what-about-the-mutating-operators" id="toc-what-about-the-mutating-operators"><span class="toc-section-number">8</span> What about the mutating
operators?<span></span></a></li>
<li><a href="#what-about-operator-" id="toc-what-about-operator-"><span class="toc-section-number">9</span> What about
<code class="sourceCode default">operator-&gt;</code>?<span></span></a></li>
<li><a href="#convertibility-to-and-from-stdintegral_constant" id="toc-convertibility-to-and-from-stdintegral_constant"><span class="toc-section-number">10</span> Convertibility to and from
<code class="sourceCode default">std::integral_constant</code><span></span></a></li>
<li><a href="#design" id="toc-design"><span class="toc-section-number">11</span> Design<span></span></a>
<ul>
<li><a href="#add-constant_wrapper" id="toc-add-constant_wrapper"><span class="toc-section-number">11.1</span> Add
<code class="sourceCode default">constant_wrapper</code><span></span></a></li>
<li><a href="#add-a-feature-macro" id="toc-add-a-feature-macro"><span class="toc-section-number">11.2</span> Add a feature
macro<span></span></a></li>
</ul></li>
<li><a href="#implementation-experience" id="toc-implementation-experience"><span class="toc-section-number">12</span> Implementation
experience<span></span></a></li>
<li><a href="#wording" id="toc-wording"><span class="toc-section-number">13</span> Wording<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="changelog"><span class="header-section-number">1</span> Changelog<a href="#changelog" class="self-link"></a></h1>
<h2 data-number="1.1" id="changes-since-r0"><span class="header-section-number">1.1</span> Changes since R0<a href="#changes-since-r0" class="self-link"></a></h2>
<ul>
<li>Remove discussion of literals for
<code class="sourceCode default">std::integral_constant</code> and
<code class="sourceCode default">std::constexpr_v</code>, based on LEWG
feedback.</li>
<li>Change the title to reflect the loss of the literals.</li>
<li>Add an explicit example involving
<code class="sourceCode default">std::constexpr_v::operator()</code>, as
requested by LEWG.</li>
<li>Add concept
<code class="sourceCode default">std::constexpr_value</code>, as
suggested by LEWG.</li>
<li>Wording.</li>
</ul>
<h2 data-number="1.2" id="changes-since-r1"><span class="header-section-number">1.2</span> Changes since R1<a href="#changes-since-r1" class="self-link"></a></h2>
<ul>
<li>Remove the <code class="sourceCode default">constexpr_value</code>
concept.</li>
<li>Use an <code class="sourceCode default">auto</code> NTTP parameter
for <code class="sourceCode default">constexpr_v</code>, and default its
type template parameter.</li>
<li>Add the option for adding the mutating overloadable operators.</li>
<li>Add a note about
<code class="sourceCode default">operator-&gt;</code>.</li>
<li>Add remarks about interconvertibility with
<code class="sourceCode default">std::integral_constant</code>.</li>
<li>Reduce the number of naming options.</li>
<li>Simplify the implementation.</li>
</ul>
<h2 data-number="1.3" id="changes-since-r2"><span class="header-section-number">1.3</span> Changes since R2<a href="#changes-since-r2" class="self-link"></a></h2>
<ul>
<li>Remove unnecessary uses of trailing return type.</li>
<li>Remove use of <code class="sourceCode default">and</code>,
<code class="sourceCode default">or</code> and
<code class="sourceCode default">not</code> keywords.</li>
<li>Correct the requirements in the exposition only
<code class="sourceCode default"><em>constexpr-param</em></code>
concept.</li>
<li>Add a note about the imperfect nature of ADL support given by
<code class="sourceCode default">constexpr_v</code>’s
<code class="sourceCode default">T</code> template parameter.</li>
</ul>
<h2 data-number="1.4" id="changes-since-r3"><span class="header-section-number">1.4</span> Changes since R3<a href="#changes-since-r3" class="self-link"></a></h2>
<ul>
<li>Fix IFNDR in unary operator overloads (including
<code class="sourceCode default">operator()</code> and
<code class="sourceCode default">operator[]</code>).</li>
<li>Add mutating operators, like
<code class="sourceCode default">operator++</code> and
<code class="sourceCode default">operator-=</code>.</li>
<li>Change the defaulted template parameter of the
<code class="sourceCode default">constexpr_v</code> (formerly
“<code class="sourceCode default">T</code>”) to be exposition-only.</li>
<li><code class="sourceCode default">constexpr_v</code> -&gt;
<code class="sourceCode default">constant_wrapper</code>, and
<code class="sourceCode default">c_</code> -&gt;
<code class="sourceCode default">cw</code>.</li>
</ul>
<h2 data-number="1.5" id="changes-since-r4"><span class="header-section-number">1.5</span> Changes since R4<a href="#changes-since-r4" class="self-link"></a></h2>
<ul>
<li>Remove superfluous <code class="sourceCode default">inline</code>
from <code class="sourceCode default">constexpr</code> variable
templates. “Thanks,” Casey.</li>
<li>Modified implementation to support array types, including string
literals.</li>
</ul>
<h2 data-number="1.6" id="changes-since-r5"><span class="header-section-number">1.6</span> Changes since R5<a href="#changes-since-r5" class="self-link"></a></h2>
<ul>
<li>Several wording corrections pointed out during LEWG review.</li>
</ul>
<h1 data-number="2" id="relationship-to-previous-work"><span class="header-section-number">2</span> Relationship to previous work<a href="#relationship-to-previous-work" class="self-link"></a></h1>
<p>This paper is co-authored in part by the authors of P2725R1
(“<code class="sourceCode default">std::integral_constant</code>
Literals”) and P2772R0
(“<code class="sourceCode default">std::integral_constant</code>
literals do not suffice —
<code class="sourceCode default">constexpr_t</code>?”). This paper
supersedes both of those previous papers.</p>
<h1 data-number="3" id="the-ergonomics-of-stdintegral_constantint-are-bad"><span class="header-section-number">3</span> The ergonomics of <code class="sourceCode default">std::integral_constant&lt;int&gt;</code> are
bad<a href="#the-ergonomics-of-stdintegral_constantint-are-bad" class="self-link"></a></h1>
<p><code class="sourceCode default">std::integral_constant&lt;int&gt;</code> is
used in lots of places to communicate a constant integral value to a
given interface. The length of its spelling makes it very verbose.
Fortunately, we can do a lot better.</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Before</strong>
</div></th>
<th><div style="text-align:center">
<strong>After</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">// From P2630R1</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> <span class="kw">const</span> sir <span class="op">=</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>strided_index_range<span class="op">{</span>std<span class="op">::</span>integral_constant<span class="op">&lt;</span><span class="dt">size_t</span>, <span class="dv">0</span><span class="op">&gt;{}</span>,</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>                           std<span class="op">::</span>integral_constant<span class="op">&lt;</span><span class="dt">size_t</span>, <span class="dv">10</span><span class="op">&gt;{}</span>,</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>                           <span class="dv">3</span><span class="op">}</span>;</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> y <span class="op">=</span> submdspan<span class="op">(</span>x, sir<span class="op">)</span>;</span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> y <span class="op">=</span> submdspan<span class="op">(</span>x, std<span class="op">::</span>strided_index_range<span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>cw<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;</span>, std<span class="op">::</span>cw<span class="op">&lt;</span><span class="dv">10</span><span class="op">&gt;</span>, <span class="dv">3</span><span class="op">})</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>The “after” case above would require that
<code class="sourceCode default">std::strided_index_range</code> be
changed; that is not being proposed here. The point of the example is to
show the relative convenience of
<code class="sourceCode default">std::integral_constant</code> versus
the proposed
<code class="sourceCode default">std::constant_wrapper</code>.</p>
<h2 data-number="3.1" id="replacing-the-uses-of-stdintegral_constant-is-not-enough"><span class="header-section-number">3.1</span> Replacing the uses of
<code class="sourceCode default">std::integral_constant</code> is not
enough<a href="#replacing-the-uses-of-stdintegral_constant-is-not-enough" class="self-link"></a></h2>
<p>Parameters passed to a
<code class="sourceCode default">constexpr</code> function lose their
<code class="sourceCode default">constexpr</code>-ness when used inside
the function. Replacing
<code class="sourceCode default">std::integral_constant</code> with
<code class="sourceCode default">std::constant_wrapper</code> has the
potential to improve a lot more uses of compile-time constants than just
integrals; what about all the other
<code class="sourceCode default">constexpr</code>-friendly C++
types?</p>
<p>Consider:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> my_complex</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    T re, im;</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="dt">short</span> foo <span class="op">=</span> <span class="dv">2</span>;</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> f<span class="op">(</span><span class="kw">auto</span> c<span class="op">)</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>        <span class="co">// c is to be used as a constexpr value here</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>We would like to be able to call
<code class="sourceCode default">S::f()</code> with a value, and have
that value keep its
<code class="sourceCode default">constexpr</code>-ness. Let’s introduce
a template “<code class="sourceCode default">constant_wrapper</code>”
that holds a <code class="sourceCode default">constexpr</code> value
that it is given as an non-type template parameter.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="co">/* ... */</span> X<span class="op">&gt;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> constant_wrapper</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> value_type <span class="op">=</span> <span class="kw">typename</span> <span class="kw">decltype</span><span class="op">(</span>X<span class="op">)::</span>type;</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> type <span class="op">=</span> constant_wrapper;</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">const</span> <span class="kw">auto</span> <span class="op">&amp;</span> value <span class="op">=</span> X<span class="op">.</span>data;</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">operator</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)()</span> <span class="kw">const</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> value; <span class="op">}</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>    <span class="co">// The rest of the members are discussed below ....</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Now we can write this.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> g<span class="op">(</span>S<span class="op">&lt;</span>T<span class="op">&gt;</span> s<span class="op">)</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    s<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>constant_wrapper<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;{})</span>;</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    s<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>constant_wrapper<span class="op">&lt;</span><span class="dv">2</span><span class="bu">u</span><span class="er">z</span><span class="op">&gt;{})</span>;</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>    s<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>constant_wrapper<span class="op">&lt;</span><span class="fl">3.0</span><span class="op">&gt;{})</span>;</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>    s<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>constant_wrapper<span class="op">&lt;</span><span class="fl">4.</span><span class="bu">f</span><span class="op">&gt;{})</span>;</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    s<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>constant_wrapper<span class="op">&lt;</span>foo<span class="op">&gt;{})</span>;</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    s<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>constant_wrapper<span class="op">&lt;</span>my_complex<span class="op">(</span><span class="fl">1.</span><span class="bu">f</span>, <span class="fl">1.</span><span class="bu">f</span><span class="op">)&gt;{})</span>;</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Let’s now add a <code class="sourceCode default">constexpr</code>
variable template with a shorter name, say
<code class="sourceCode default">cw</code>.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="co">/* ... */</span> X<span class="op">&gt;</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> constant_wrapper<span class="op">&lt;</span>X<span class="op">&gt;</span> cw<span class="op">{}</span>;</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And now we can write this.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> g<span class="op">(</span>S<span class="op">&lt;</span>T<span class="op">&gt;</span> s<span class="op">)</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    s<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>cw<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;)</span>;</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>    s<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>cw<span class="op">&lt;</span><span class="dv">2</span><span class="bu">u</span><span class="er">z</span><span class="op">&gt;)</span>;</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>    s<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>cw<span class="op">&lt;</span><span class="fl">3.0</span><span class="op">&gt;)</span>;</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>    s<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>cw<span class="op">&lt;</span><span class="fl">4.</span><span class="bu">f</span><span class="op">&gt;)</span>;</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>    s<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>cw<span class="op">&lt;</span>foo<span class="op">&gt;)</span>;</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>    s<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>cw<span class="op">&lt;</span>my_complex<span class="op">(</span><span class="fl">1.</span><span class="bu">f</span>, <span class="fl">1.</span><span class="bu">f</span><span class="op">)&gt;)</span>;</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="3.2" id="the-difference-in-template-parameters-to-stdconstant_wrapper-and-stdcw"><span class="header-section-number">3.2</span> The difference in template
parameters to
<code class="sourceCode default">std::constant_wrapper</code> and
<code class="sourceCode default">std::cw</code><a href="#the-difference-in-template-parameters-to-stdconstant_wrapper-and-stdcw" class="self-link"></a></h2>
<p>If you look at the wording below, you will see that
<code class="sourceCode default">std::cw</code> takes a single NTTP,
whereas <code class="sourceCode default">std::constant_wrapper</code>
takes an NTTP <code class="sourceCode default">X</code>, and an
exposition-only, unnamed parameter, which is defaulted to <code class="sourceCode default">remove_cvref_t&lt;decltype(X)&gt;</code>. Why
is this? ADL, of course! Even though the type of
<code class="sourceCode default">X</code> is deduced with or without the
unnmaed paramter, without the unnamed parameter, some natural uses of
<code class="sourceCode default">constant_wrapper</code> cease to work.
For instance:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> f <span class="op">=</span> std<span class="op">::</span>cw<span class="op">&lt;</span><span class="st">&quot;foo&quot;</span><span class="op">&gt;</span>;</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> f <span class="op">&lt;&lt;</span> <span class="st">&quot;</span><span class="sc">\n</span><span class="st">&quot;</span>;</span></code></pre></div>
<p>The stream insertion breaks without the unnamed parameter, which is
<code class="sourceCode default">char const [4]</code>, and which in
turn pulls the proper
<code class="sourceCode default">operator&lt;&lt;</code> into
consideration during ADL. Note that this ADL support is imperfect. An
earlier version of the paper showed using <code class="sourceCode default">std::cw&lt;strlit(&quot;foo)&quot;&gt;</code>
in a stream insertion operation, where
<code class="sourceCode default">strlit</code> is a strucutral type that
contains the bytes that comprise
<code class="sourceCode default">&quot;foo&quot;</code>:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> strlit</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> strlit<span class="op">(</span><span class="dt">char</span> <span class="kw">const</span> <span class="op">(&amp;</span>str<span class="op">)[</span>N<span class="op">])</span> <span class="op">{</span> std<span class="op">::</span>copy_n<span class="op">(</span>str, N, value<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="dt">size_t</span> M<span class="op">&gt;</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>strlit<span class="op">&lt;</span>M<span class="op">&gt;</span> rhs<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> std<span class="op">::</span>ranges<span class="op">::</span>equal<span class="op">(</span>bytes_, rhs<span class="op">.</span>bytes_<span class="op">)</span>;</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> std<span class="op">::</span>ostream <span class="op">&amp;</span> <span class="kw">operator</span><span class="op">&lt;&lt;(</span>std<span class="op">::</span>ostream <span class="op">&amp;</span> os, strlit l<span class="op">)</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>        <span class="ot">assert</span><span class="op">(!</span>l<span class="op">.</span>value<span class="op">[</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">]</span> <span class="op">&amp;&amp;</span> <span class="st">&quot;value must be null-terminated&quot;</span><span class="op">)</span>;</span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> os<span class="op">.</span>write<span class="op">(</span>l<span class="op">.</span>value, N <span class="op">-</span> <span class="dv">1</span><span class="op">)</span>;</span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> value<span class="op">[</span>N<span class="op">]</span>;</span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span></span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> print_foo<span class="op">()</span></span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb9-24"><a href="#cb9-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> f <span class="op">=</span> std<span class="op">::</span>cw<span class="op">&lt;</span>strlit<span class="op">(</span><span class="st">&quot;foo&quot;</span><span class="op">)&gt;</span>;</span>
<span id="cb9-25"><a href="#cb9-25" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> f; <span class="co">// Prints &quot;foo&quot;.</span></span>
<span id="cb9-26"><a href="#cb9-26" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> std<span class="op">::</span>cw<span class="op">&lt;</span><span class="st">&quot;foo&quot;</span><span class="op">&gt;</span>; <span class="co">// Prints &quot;foo&quot;.</span></span>
<span id="cb9-27"><a href="#cb9-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This worked because of the way the
<code class="sourceCode default">operator&lt;&lt;</code> above is
declared – as a <code class="sourceCode default">friend</code>.</p>
<p>If it were instead declared as a
non-<code class="sourceCode default">friend</code>:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>ostream <span class="op">&amp;</span> <span class="kw">operator</span><span class="op">&lt;&lt;(</span>std<span class="op">::</span>ostream <span class="op">&amp;</span> os, strlit<span class="op">&lt;</span>N<span class="op">&gt;</span> l<span class="op">)</span> <span class="op">{</span> <span class="co">/* ...*/</span> <span class="op">}</span></span></code></pre></div>
<p>… ADL’s help doesn’t suffice. The deduction of
<code class="sourceCode default">N</code> is not possible from a type
that isn’t a <code class="sourceCode default">strlit&lt;N&gt;</code>
itself (e.g. base class) even if it is implicitly convertible to
<code class="sourceCode default">strlit&lt;N&gt;</code>.</p>
<h1 data-number="4" id="the-type-of-x"><span class="header-section-number">4</span> The type of
<code class="sourceCode default">X</code><a href="#the-type-of-x" class="self-link"></a></h1>
<p>The type of <code class="sourceCode default">X</code> was elided
above for simplicity; now let’s look at it. This is what is used:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> fixed_value <span class="op">{</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> type <span class="op">=</span> T;</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> fixed_value<span class="op">(</span>type v<span class="op">)</span> <span class="kw">noexcept</span><span class="op">:</span> data<span class="op">(</span>v<span class="op">)</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>  T data;</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, <span class="dt">size_t</span> Extent<span class="op">&gt;</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> fixed_value<span class="op">&lt;</span>T<span class="op">[</span>Extent<span class="op">]&gt;</span> <span class="op">{</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> type <span class="op">=</span> T<span class="op">[</span>Extent<span class="op">]</span>;</span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> fixed_value<span class="op">(</span>T <span class="op">(&amp;</span>arr<span class="op">)[</span>Extent<span class="op">])</span> <span class="kw">noexcept</span><span class="op">:</span> fixed_value<span class="op">(</span>arr, std<span class="op">::</span>make_index_sequence<span class="op">&lt;</span>Extent<span class="op">&gt;())</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>  T data<span class="op">[</span>Extent<span class="op">]</span>;</span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="dt">size_t</span><span class="op">...</span> Idx<span class="op">&gt;</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> fixed_value<span class="op">(</span>T <span class="op">(&amp;</span>arr<span class="op">)[</span>Extent<span class="op">]</span>, std<span class="op">::</span>index_sequence<span class="op">&lt;</span>Idx<span class="op">...&gt;)</span> <span class="kw">noexcept</span><span class="op">:</span> data<span class="op">{</span>arr<span class="op">[</span>Idx<span class="op">]...}</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, <span class="dt">size_t</span> Extent<span class="op">&gt;</span></span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a>fixed_value<span class="op">(</span>T <span class="op">(&amp;)[</span>Extent<span class="op">])</span> <span class="op">-&gt;</span> fixed_value<span class="op">&lt;</span>T<span class="op">[</span>Extent<span class="op">]&gt;</span>;</span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true" tabindex="-1"></a>fixed_value<span class="op">(</span>T<span class="op">)</span> <span class="op">-&gt;</span> fixed_value<span class="op">&lt;</span>T<span class="op">&gt;</span>;</span></code></pre></div>
<p>By writing <code class="sourceCode default">constant_wrapper</code>
as <code class="sourceCode default">constant_wrapper&lt;fixed_value X&gt;</code>,
we are able to use CTAD in
<code class="sourceCode default">fixed_value X</code> to defer writing
the type of the underlying value, and use deduction to cosntruct the
write specialization of
<code class="sourceCode default">fixed_value</code> at the point of
specialization of
<code class="sourceCode default">constant_wrapper</code>:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> foo <span class="op">=</span> constant_wrapper<span class="op">&lt;</span><span class="st">&quot;foo&quot;</span><span class="op">&gt;</span>;</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>same_as<span class="op">&lt;</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">decltype</span><span class="op">(</span>foo<span class="op">)</span>,</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">const</span> constant_wrapper<span class="op">&lt;</span>fixed_value<span class="op">&lt;</span><span class="kw">const</span> <span class="dt">char</span><span class="op">[</span><span class="dv">4</span><span class="op">]&gt;{</span><span class="st">&quot;foo&quot;</span><span class="op">}&gt;&gt;)</span>;</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> bar <span class="op">=</span> constant_wrapper<span class="op">&lt;</span><span class="dv">42</span><span class="op">&gt;</span>;</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>same_as<span class="op">&lt;</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">decltype</span><span class="op">(</span>bar<span class="op">)</span>,</span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>                  <span class="kw">const</span> constant_wrapper<span class="op">&lt;</span>fixed_value<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;{</span><span class="dv">42</span><span class="op">}&gt;&gt;)</span>;</span></code></pre></div>
<p>This indirection allows the support for arrays that was added in this
revision of the paper.</p>
<h1 data-number="5" id="making-constant_wrapper-more-useful"><span class="header-section-number">5</span> Making
<code class="sourceCode default">constant_wrapper</code> more useful<a href="#making-constant_wrapper-more-useful" class="self-link"></a></h1>
<p><code class="sourceCode default">constant_wrapper</code> is
essentially a wrapper. It takes a value
<code class="sourceCode default">X</code> of some structural type
<code class="sourceCode default">value_type</code>, and represents
<code class="sourceCode default">X</code> in such a way that we can
continue to use <code class="sourceCode default">X</code> as a
compile-time constant, regardless of context. As such,
<code class="sourceCode default">constant_wrapper</code> should be
implicitly convertible to
<code class="sourceCode default">value_type</code>; this is already
reflected in the design presented above. For the same reason,
<code class="sourceCode default">constant_wrapper</code> should provide
all the operations that the underlying type has. Though we cannot
predict what named members the underlying type
<code class="sourceCode default">value_type</code> has, we <em>can</em>
guess at all the operator overloads it might have.</p>
<p>So, by adding conditionally-defined overloads for all the
overloadable operators, we can make
<code class="sourceCode default">constant_wrapper</code> as natural to
use as many of the types it might wrap.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> operators <span class="op">{</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// unary -</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span>constexpr_param T<span class="op">&gt;</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">-(</span>T<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(-</span>T<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// binary + and -</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span>constexpr_param L, constexpr_param R<span class="op">&gt;</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">+(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">+</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span>constexpr_param L, constexpr_param R<span class="op">&gt;</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">-(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">-</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>    <span class="co">// etc... (full listing later)</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span> X<span class="op">&gt;</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> constant_wrapper <span class="op">:</span> operators <span class="op">{</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> value_type <span class="op">=</span> remove_cvref_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X<span class="op">)&gt;</span>;</span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> type <span class="op">=</span> constant_wrapper;</span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">operator</span> value_type<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> X; <span class="op">}</span></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> value_type value <span class="op">=</span> X;</span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>These operators are defined in such a way that they behave just like
the operations on underlying the
<code class="sourceCode default">U</code> and
<code class="sourceCode default">V</code> values would, including
promotions and coercions. For example:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>std<span class="op">::</span>is_same_v<span class="op">&lt;</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>              <span class="kw">decltype</span><span class="op">(</span>std<span class="op">::</span>cw<span class="op">&lt;</span><span class="dv">42</span><span class="op">&gt;</span> <span class="op">-</span> std<span class="op">::</span>cw<span class="op">&lt;</span><span class="dv">13</span><span class="bu">u</span><span class="op">&gt;)</span>,</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>              std<span class="op">::</span>constant_wrapper<span class="op">&lt;</span><span class="dv">29</span><span class="bu">u</span><span class="op">&gt;&gt;)</span>;</span></code></pre></div>
<p>Each operation is only defined if the underlying operation on
<code class="sourceCode default">X</code> is defined. Each operation
additionally requires that the result of the underlying operation have a
structural type.</p>
<p>All the overloadable operations are included, even the index and call
operators. The rationale for this is that a user may want to make some
sort of compile-time domain-specific embedded language using operator
overloading, and having all but a couple of the operators specified
would frustrate that effort. The only exception to this is
<code class="sourceCode default">operator-&gt;</code> which must
eventually return a pointer type, which is not very useful at compile
time.</p>
<p>The only downside to adding <code class="sourceCode default">std::constant_wrapper::operator()</code> is
that it would represent a break from the design of
<code class="sourceCode default">std::integral_constant</code>, making
it an imperfect drop-in replacement for that template. Nullary <code class="sourceCode default">std::constant_wrapper::operator()</code> with
the same semantics as <code class="sourceCode default">std::integral_constant::operator()</code> is
defined when <code class="sourceCode default">requires (!std::invocable&lt;value_type&gt;)</code>
is <code class="sourceCode default">true</code>, so this incompatibility
is truly a corner case.</p>
<p>The operators are designed to interoperate with other types and
templates that have a constexpr static
<code class="sourceCode default">value</code> member. This works with
<code class="sourceCode default">std::constant_wrapper</code>s of
course, but also
<code class="sourceCode default">std::integral_constant</code>s, and
user-provided types as well. For example:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> my_type <span class="op">{</span> <span class="kw">constexpr</span> <span class="kw">static</span> <span class="dt">int</span> value <span class="op">=</span> <span class="dv">42</span>; <span class="op">}</span>;</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> foo<span class="op">()</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> zero <span class="op">=</span> my_type<span class="op">{}</span> <span class="op">-</span> std<span class="op">::</span>cw<span class="op">&lt;</span><span class="dv">42</span><span class="op">&gt;</span>;  <span class="co">// Ok.</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Note that the addition of these operators is in line with the
poll:</p>
<p>“Add a new robust integral constant type with all the numerical
operators, as proposed in P2772R0, and use that for these literals
instead of
<code class="sourceCode default">std::integral_constant</code>”?</p>
<table style="width:31%;">
<colgroup>
<col style="width: 6%" />
<col style="width: 5%" />
<col style="width: 5%" />
<col style="width: 5%" />
<col style="width: 6%" />
</colgroup>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>SF</strong>
</div></th>
<th><div style="text-align:center">
<strong>F</strong>
</div></th>
<th><div style="text-align:center">
<strong>N</strong>
</div></th>
<th><div style="text-align:center">
<strong>A</strong>
</div></th>
<th><div style="text-align:center">
<strong>SA</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>4</td>
<td>7</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
</tbody>
</table>
<p>… taken in the 2023-01-17 Library Evolution telecon.</p>
<p>Note that the one SA said he would not be opposed if the word
“integral” was stricken from the poll, and the design of
<code class="sourceCode default">std::constant_wrapper</code> is not
limited to integral types.</p>
<h1 data-number="6" id="what-about-strings"><span class="header-section-number">6</span> What about strings?<a href="#what-about-strings" class="self-link"></a></h1>
<p>As mentioned above, in earlier versions of the paper,
<code class="sourceCode default">std::cw&lt;&quot;foo&quot;&gt;</code>
did not work, because language rules prohibit using a reference to an
array as an NTTP. However, the latest implementation uses an
exposition-only structural type
<code class="sourceCode default"><em>cw-fixed-value</em></code> as the
<code class="sourceCode default">constant_wrapper</code> NTTP;
<code class="sourceCode default"><em>cw-fixed-value</em></code> can be
constructed from a variety of different types, including arrays. This
allows an array to be given as the template parameter to
<code class="sourceCode default">std::cw</code>, including an array of
<code class="sourceCode default">char</code>, like a string literal. For
instance:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> print_foo<span class="op">()</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> std<span class="op">::</span>cw<span class="op">&lt;</span><span class="st">&quot;foo&quot;</span><span class="op">&gt;</span>; <span class="co">// Prints &quot;foo&quot;.</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This is not without its problems, however. Consider these two
uses.</p>
<p>First, <code class="sourceCode default">std::cw&lt;&quot;foo&quot;&gt; == std::cw&lt;&quot;foo&quot;&gt;</code>.
This is expression is true, but it only compares pointers.</p>
<p>Second, <code class="sourceCode default">std::cw&lt;&quot;bar&quot;&gt; &lt; std::cw&lt;&quot;foo&quot;&gt;</code>
is not a constant expression. Runtime evaluation compares the pointers
of “foo” and “bar”. That’s a footgun.</p>
<p>In general, strings and other array types are not passed nearly as
ofter as arguments to <code class="sourceCode default">constexpr</code>
functions. It is questionable whether we should delay the very useful
semantics of <code class="sourceCode default">std::cw&lt;&gt;</code>
<code class="sourceCode default">constexpr</code> function arguments
trying to find a design that supports array types. This is a question
that LEWG should answer.</p>
<p>Option 1: Support array values as NTTP template arguments to
<code class="sourceCode default">std::constant_wrapper</code>. This is
the option represented in the code that follows, based on LEWG
polling.</p>
<p>Option 2: Leave all the code in place to support array value as NTTP
template arguments to
<code class="sourceCode default">std::constant_wrapper</code>, except
disable the specialization that enables array values to work.</p>
<h1 data-number="7" id="an-example-using-operator"><span class="header-section-number">7</span> An example using
<code class="sourceCode default">operator()</code><a href="#an-example-using-operator" class="self-link"></a></h1>
<p>The addition of non-arithmetic operators may seem academic at first.
However, consider this
<code class="sourceCode default">constexpr</code>-friendly parser
combinator mini-library.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> parse <span class="op">{</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> L, <span class="kw">typename</span> R<span class="op">&gt;</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> or_parser;</span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> str_parser</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>        <span class="kw">template</span><span class="op">&lt;</span><span class="dt">size_t</span> M<span class="op">&gt;</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">()(</span>strlit<span class="op">&lt;</span>M<span class="op">&gt;</span> lit<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> lit <span class="op">==</span> str_;</span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>        <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> P<span class="op">&gt;</span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>        <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">|(</span>P parser<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span></span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> or_parser<span class="op">&lt;</span>str_parser, P<span class="op">&gt;{*</span><span class="kw">this</span>, parser<span class="op">}</span>;</span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb17-19"><a href="#cb17-19" aria-hidden="true" tabindex="-1"></a>        strlit<span class="op">&lt;</span>N<span class="op">&gt;</span> str_;</span>
<span id="cb17-20"><a href="#cb17-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb17-21"><a href="#cb17-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-22"><a href="#cb17-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> L, <span class="kw">typename</span> R<span class="op">&gt;</span></span>
<span id="cb17-23"><a href="#cb17-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> or_parser</span>
<span id="cb17-24"><a href="#cb17-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb17-25"><a href="#cb17-25" aria-hidden="true" tabindex="-1"></a>        <span class="kw">template</span><span class="op">&lt;</span><span class="dt">size_t</span> M<span class="op">&gt;</span></span>
<span id="cb17-26"><a href="#cb17-26" aria-hidden="true" tabindex="-1"></a>        <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">()(</span>strlit<span class="op">&lt;</span>M<span class="op">&gt;</span> lit<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb17-27"><a href="#cb17-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span></span>
<span id="cb17-28"><a href="#cb17-28" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> l_<span class="op">(</span>lit<span class="op">)</span> <span class="op">||</span> r_<span class="op">(</span>lit<span class="op">)</span>;</span>
<span id="cb17-29"><a href="#cb17-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb17-30"><a href="#cb17-30" aria-hidden="true" tabindex="-1"></a>        <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> P<span class="op">&gt;</span></span>
<span id="cb17-31"><a href="#cb17-31" aria-hidden="true" tabindex="-1"></a>        <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">|(</span>P parser<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb17-32"><a href="#cb17-32" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span></span>
<span id="cb17-33"><a href="#cb17-33" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> or_parser<span class="op">&lt;</span>or_parser, P<span class="op">&gt;{*</span><span class="kw">this</span>, parser<span class="op">}</span>;</span>
<span id="cb17-34"><a href="#cb17-34" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb17-35"><a href="#cb17-35" aria-hidden="true" tabindex="-1"></a>        L l_;</span>
<span id="cb17-36"><a href="#cb17-36" aria-hidden="true" tabindex="-1"></a>        R r_;</span>
<span id="cb17-37"><a href="#cb17-37" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb17-38"><a href="#cb17-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-39"><a href="#cb17-39" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb17-40"><a href="#cb17-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-41"><a href="#cb17-41" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> foo<span class="op">()</span></span>
<span id="cb17-42"><a href="#cb17-42" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb17-43"><a href="#cb17-43" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> parse<span class="op">::</span>str_parser p1<span class="op">{</span>strlit<span class="op">(</span><span class="st">&quot;neg&quot;</span><span class="op">)}</span>;</span>
<span id="cb17-44"><a href="#cb17-44" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> parse<span class="op">::</span>str_parser p2<span class="op">{</span>strlit<span class="op">(</span><span class="st">&quot;incr&quot;</span><span class="op">)}</span>;</span>
<span id="cb17-45"><a href="#cb17-45" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> parse<span class="op">::</span>str_parser p3<span class="op">{</span>strlit<span class="op">(</span><span class="st">&quot;decr&quot;</span><span class="op">)}</span>;</span>
<span id="cb17-46"><a href="#cb17-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-47"><a href="#cb17-47" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> p <span class="op">=</span> p1 <span class="op">|</span> p2 <span class="op">|</span> p3;</span>
<span id="cb17-48"><a href="#cb17-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-49"><a href="#cb17-49" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> matches_empty <span class="op">=</span> p<span class="op">(</span>strlit<span class="op">(</span><span class="st">&quot;&quot;</span><span class="op">))</span>;</span>
<span id="cb17-50"><a href="#cb17-50" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static_assert</span><span class="op">(!</span>matches_empty<span class="op">)</span>;</span>
<span id="cb17-51"><a href="#cb17-51" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> matches_pos <span class="op">=</span> p<span class="op">(</span>strlit<span class="op">(</span><span class="st">&quot;pos&quot;</span><span class="op">))</span>;</span>
<span id="cb17-52"><a href="#cb17-52" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static_assert</span><span class="op">(!</span>matches_pos<span class="op">)</span>;</span>
<span id="cb17-53"><a href="#cb17-53" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> matches_decr <span class="op">=</span> p<span class="op">(</span>strlit<span class="op">(</span><span class="st">&quot;decr&quot;</span><span class="op">))</span>;</span>
<span id="cb17-54"><a href="#cb17-54" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static_assert</span><span class="op">(</span>matches_decr<span class="op">)</span>;</span>
<span id="cb17-55"><a href="#cb17-55" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>(This relies on the <code class="sourceCode default">strlit</code>
struct shown just previously.)</p>
<p>Say we wanted to use the templates in namespace
<code class="sourceCode default">parser</code> along side other values,
like <code class="sourceCode default">int</code>s and
<code class="sourceCode default">float</code>s. We would want that not
to break our
<code class="sourceCode default">std::constant_wrapper</code>
expressions. Having to work around the absence of <code class="sourceCode default">std::constant_wrapper::operator()</code>
would require us to write a lot more code. Here is the equivalent of the
function <code class="sourceCode default">foo()</code> above, but with
all the variables wrapped using
<code class="sourceCode default">std::cw</code>.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> bar<span class="op">()</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> parse<span class="op">::</span>str_parser p1<span class="op">{</span>strlit<span class="op">(</span><span class="st">&quot;neg&quot;</span><span class="op">)}</span>;</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> parse<span class="op">::</span>str_parser p2<span class="op">{</span>strlit<span class="op">(</span><span class="st">&quot;incr&quot;</span><span class="op">)}</span>;</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> parse<span class="op">::</span>str_parser p3<span class="op">{</span>strlit<span class="op">(</span><span class="st">&quot;decr&quot;</span><span class="op">)}</span>;</span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> p_ <span class="op">=</span> std<span class="op">::</span>cw<span class="op">&lt;</span>p1<span class="op">&gt;</span> <span class="op">|</span> std<span class="op">::</span>cw<span class="op">&lt;</span>p2<span class="op">&gt;</span> <span class="op">|</span> std<span class="op">::</span>cw<span class="op">&lt;</span>p3<span class="op">&gt;</span>;</span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> matches_empty_ <span class="op">=</span> p_<span class="op">(</span>std<span class="op">::</span>cw<span class="op">&lt;</span>strlit<span class="op">(</span><span class="st">&quot;&quot;</span><span class="op">)&gt;)</span>;</span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static_assert</span><span class="op">(!</span>matches_empty_<span class="op">)</span>;</span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> matches_pos_ <span class="op">=</span> p_<span class="op">(</span>std<span class="op">::</span>cw<span class="op">&lt;</span>strlit<span class="op">(</span><span class="st">&quot;pos&quot;</span><span class="op">)&gt;)</span>;</span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static_assert</span><span class="op">(!</span>matches_pos_<span class="op">)</span>;</span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> matches_decr_ <span class="op">=</span> p_<span class="op">(</span>std<span class="op">::</span>cw<span class="op">&lt;</span>strlit<span class="op">(</span><span class="st">&quot;decr&quot;</span><span class="op">)&gt;)</span>;</span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static_assert</span><span class="op">(</span>matches_decr_<span class="op">)</span>;</span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>As you can see, everything works as it did before. The presence of
<code class="sourceCode default">operator()</code> does not enable any
new functionality, it just keeps code that happens to use it from
breaking.</p>
<h1 data-number="8" id="what-about-the-mutating-operators"><span class="header-section-number">8</span> What about the mutating
operators?<a href="#what-about-the-mutating-operators" class="self-link"></a></h1>
<p>It may seem at first that these operators are nonsensical, since all
the operations on a
<code class="sourceCode default">constant_wrapper</code> must be
nonmutating.</p>
<p>However, some DSLs may wish to use these operations with atypical
semantics.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> weirdo</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">int</span> <span class="kw">operator</span><span class="op">++()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> <span class="dv">1</span>; <span class="op">}</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> result <span class="op">=</span> <span class="op">++</span>std<span class="op">::</span>cw<span class="op">&lt;</span>weirdo<span class="op">{}&gt;</span>;</span></code></pre></div>
<p><code class="sourceCode default">result</code> is obviously
<code class="sourceCode default">std::cw&lt;1&gt;</code> here, and no
mutation occurred. You can imagine a more elaborate use case, say a
library that is used to create expression templates. For example:</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> expr <span class="op">=</span> std<span class="op">::</span>cw<span class="op">&lt;</span>var0<span class="op">&gt;</span> <span class="op">+=</span> std<span class="op">::</span>cw<span class="op">&lt;</span>var1<span class="op">&gt;</span>;</span></code></pre></div>
<p>In this case, <code class="sourceCode default">var0</code> and
<code class="sourceCode default">var1</code> would be some terminal
types in the expression template library, and
<code class="sourceCode default">operator+=</code> would return a
<code class="sourceCode default">constexpr</code> expression tree,
rather than mutating the left side of the
<code class="sourceCode default">+=</code>.</p>
<p>These operators are now part of the proposal, based on this LEWG poll
from Kona 2023:</p>
<p>“We should add mutating operations
(i.e. <code class="sourceCode default">#define IF_LEWG_SAYS_SO 1</code>
and <code class="sourceCode default">++</code> and
<code class="sourceCode default">--</code>) to P2781R3”</p>
<table style="width:31%;">
<colgroup>
<col style="width: 6%" />
<col style="width: 5%" />
<col style="width: 5%" />
<col style="width: 5%" />
<col style="width: 6%" />
</colgroup>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>SF</strong>
</div></th>
<th><div style="text-align:center">
<strong>F</strong>
</div></th>
<th><div style="text-align:center">
<strong>N</strong>
</div></th>
<th><div style="text-align:center">
<strong>A</strong>
</div></th>
<th><div style="text-align:center">
<strong>SA</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>2</td>
<td>6</td>
<td>5</td>
<td>2</td>
<td>0</td>
</tr>
</tbody>
</table>
<h1 data-number="9" id="what-about-operator-"><span class="header-section-number">9</span> What about
<code class="sourceCode default">operator-&gt;</code>?<a href="#what-about-operator-" class="self-link"></a></h1>
<p>We’re not proposing it, because of its very specific semantics – it
must yield a pointer, or something that eventually does. That’s not a
very useful operation during constant evaluation.</p>
<h1 data-number="10" id="convertibility-to-and-from-stdintegral_constant"><span class="header-section-number">10</span> Convertibility to and from
<code class="sourceCode default">std::integral_constant</code><a href="#convertibility-to-and-from-stdintegral_constant" class="self-link"></a></h1>
<p>During the LEWG reviews, some attendees suggested that
inter-conversions between
<code class="sourceCode default">std::integral_constant</code> and
<code class="sourceCode default">std::constant_wrapper</code> would be
useful. The important thing to remember is that we want deduction to
occur when calling functions that take a
<code class="sourceCode default">std::constant_wrapper</code>, including
the <code class="sourceCode default">std::constant_wrapper</code>
operator overloads. Conversions and deductions are at odds with one
another, because deducing parameter types disables the conversion
rules.</p>
<p>If you look at the operator overloads proposed here, you will see
that they are deduction operations at their most essential. The types of
the parameters do not matter, except that each conveys a value that is a
core constant expression because it is embedded in the type system. The
fact that a
<code class="sourceCode default">std::constant_wrapper</code> conveys
that value instead of a
<code class="sourceCode default">std::integral_constant</code> is
immaterial, and in fact the operators are written in such a way that
they operate on either template (as long as at least one parameter is a
specialization of
<code class="sourceCode default">std::constant_wrapper</code>). Users
can and should write their code using these kinds of values-as-types in
a similar way. Relying on conversions is a less-useful way to get
interoperability.</p>
<h1 data-number="11" id="design"><span class="header-section-number">11</span> Design<a href="#design" class="self-link"></a></h1>
<h2 data-number="11.1" id="add-constant_wrapper"><span class="header-section-number">11.1</span> Add
<code class="sourceCode default">constant_wrapper</code><a href="#add-constant_wrapper" class="self-link"></a></h2>
<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-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="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> <em>cw-fixed-value</em>;                                                        <span class="co">// <em>exposition only</em></span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><em>cw-fixed-value</em> X,</span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>           <span class="kw">class</span> <span class="op">=</span> <span class="kw">typename</span> <span class="kw">decltype</span><span class="op">(</span><em>cw-fixed-value</em><span class="op">(</span>X<span class="op">))::</span>type<span class="op">&gt;</span>                    <span class="co">// <em>exposition only</em></span></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> constant_wrapper;</span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-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="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> <em>constexpr-param</em> <span class="op">=</span> <span class="kw">requires</span> <span class="op">{</span> <span class="kw">typename</span> constant_wrapper<span class="op">&lt;</span>T<span class="op">::</span>value<span class="op">&gt;</span>; <span class="op">}</span>;  <span class="co">// <em>exposition only</em></span></span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-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="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> <em>cw-fixed-value</em> <span class="op">{</span>                                                         <span class="co">// <em>exposition only</em></span></span>
<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> type <span class="op">=</span> T;</span>
<span id="cb21-15"><a href="#cb21-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>cw-fixed-value</em><span class="op">(</span>type v<span class="op">)</span> <span class="kw">noexcept</span><span class="op">:</span> data<span class="op">(</span>v<span class="op">)</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb21-16"><a href="#cb21-16" aria-hidden="true" tabindex="-1"></a>    T data;</span>
<span id="cb21-17"><a href="#cb21-17" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb21-18"><a href="#cb21-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-19"><a href="#cb21-19" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, <span class="dt">size_t</span> Extent<span class="op">&gt;</span></span>
<span id="cb21-20"><a href="#cb21-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> <em>cw-fixed-value</em><span class="op">&lt;</span>T<span class="op">[</span>Extent<span class="op">]&gt;</span> <span class="op">{</span>                                              <span class="co">// <em>exposition only</em></span></span>
<span id="cb21-21"><a href="#cb21-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> type <span class="op">=</span> T<span class="op">[</span>Extent<span class="op">]</span>;</span>
<span id="cb21-22"><a href="#cb21-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>cw-fixed-value</em><span class="op">(</span>T <span class="op">(&amp;</span>arr<span class="op">)[</span>Extent<span class="op">])</span> <span class="kw">noexcept</span><span class="op">:</span> <em>cw-fixed-value</em><span class="op">(</span>arr, std<span class="op">::</span>make_index_sequence<span class="op">&lt;</span>Extent<span class="op">&gt;())</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb21-23"><a href="#cb21-23" aria-hidden="true" tabindex="-1"></a>    T data<span class="op">[</span>Extent<span class="op">]</span>;</span>
<span id="cb21-24"><a href="#cb21-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-25"><a href="#cb21-25" aria-hidden="true" tabindex="-1"></a>  <span class="kw">private</span><span class="op">:</span></span>
<span id="cb21-26"><a href="#cb21-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="dt">size_t</span><span class="op">...</span> Idx<span class="op">&gt;</span></span>
<span id="cb21-27"><a href="#cb21-27" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>cw-fixed-value</em><span class="op">(</span>T <span class="op">(&amp;</span>arr<span class="op">)[</span>Extent<span class="op">]</span>, std<span class="op">::</span>index_sequence<span class="op">&lt;</span>Idx<span class="op">...&gt;)</span> <span class="kw">noexcept</span><span class="op">:</span> data<span class="op">{</span>arr<span class="op">[</span>Idx<span class="op">]...}</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb21-28"><a href="#cb21-28" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb21-29"><a href="#cb21-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-30"><a href="#cb21-30" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, <span class="dt">size_t</span> Extent<span class="op">&gt;</span></span>
<span id="cb21-31"><a href="#cb21-31" aria-hidden="true" tabindex="-1"></a>    <em>cw-fixed-value</em><span class="op">(</span>T <span class="op">(&amp;)[</span>Extent<span class="op">])</span> <span class="op">-&gt;</span> <em>cw-fixed-value</em><span class="op">&lt;</span>T<span class="op">[</span>Extent<span class="op">]&gt;</span>;                   <span class="co">// <em>exposition only</em></span></span>
<span id="cb21-32"><a href="#cb21-32" aria-hidden="true" tabindex="-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="cb21-33"><a href="#cb21-33" aria-hidden="true" tabindex="-1"></a>    <em>cw-fixed-value</em><span class="op">(</span>T<span class="op">)</span> <span class="op">-&gt;</span> <em>cw-fixed-value</em><span class="op">&lt;</span>T<span class="op">&gt;</span>;                                       <span class="co">// <em>exposition only</em></span></span>
<span id="cb21-34"><a href="#cb21-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-35"><a href="#cb21-35" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> <em>cw-operators</em> <span class="op">{</span>                                                           <span class="co">// <em>exposition only</em></span></span>
<span id="cb21-36"><a href="#cb21-36" aria-hidden="true" tabindex="-1"></a>    <span class="co">// unary operators</span></span>
<span id="cb21-37"><a href="#cb21-37" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T<span class="op">&gt;</span></span>
<span id="cb21-38"><a href="#cb21-38" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">+(</span>T<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(+</span>T<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-39"><a href="#cb21-39" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T<span class="op">&gt;</span></span>
<span id="cb21-40"><a href="#cb21-40" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">-(</span>T<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(-</span>T<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-41"><a href="#cb21-41" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T<span class="op">&gt;</span></span>
<span id="cb21-42"><a href="#cb21-42" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">~(</span>T<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(~</span>T<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-43"><a href="#cb21-43" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T<span class="op">&gt;</span></span>
<span id="cb21-44"><a href="#cb21-44" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">!(</span>T<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(!</span>T<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-45"><a href="#cb21-45" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T<span class="op">&gt;</span></span>
<span id="cb21-46"><a href="#cb21-46" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&amp;(</span>T<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(&amp;</span>T<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-47"><a href="#cb21-47" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T<span class="op">&gt;</span></span>
<span id="cb21-48"><a href="#cb21-48" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">*(</span>T<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(*</span>T<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-49"><a href="#cb21-49" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-50"><a href="#cb21-50" aria-hidden="true" tabindex="-1"></a>    <span class="co">// binary operators</span></span>
<span id="cb21-51"><a href="#cb21-51" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-52"><a href="#cb21-52" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">+(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">+</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-53"><a href="#cb21-53" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-54"><a href="#cb21-54" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">-(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">-</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-55"><a href="#cb21-55" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-56"><a href="#cb21-56" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">*(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">*</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-57"><a href="#cb21-57" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-58"><a href="#cb21-58" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">/(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">/</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-59"><a href="#cb21-59" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-60"><a href="#cb21-60" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">%(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">%</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-61"><a href="#cb21-61" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-62"><a href="#cb21-62" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-63"><a href="#cb21-63" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&lt;&lt;(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">&lt;&lt;</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-64"><a href="#cb21-64" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-65"><a href="#cb21-65" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&gt;&gt;(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">&gt;&gt;</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-66"><a href="#cb21-66" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-67"><a href="#cb21-67" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&amp;(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">&amp;</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-68"><a href="#cb21-68" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-69"><a href="#cb21-69" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">|(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">|</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-70"><a href="#cb21-70" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-71"><a href="#cb21-71" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">^(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">^</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-72"><a href="#cb21-72" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-73"><a href="#cb21-73" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-74"><a href="#cb21-74" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&amp;&amp;(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">&amp;&amp;</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-75"><a href="#cb21-75" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-76"><a href="#cb21-76" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">||(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">||</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-77"><a href="#cb21-77" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-78"><a href="#cb21-78" aria-hidden="true" tabindex="-1"></a>    <span class="co">// comparisons</span></span>
<span id="cb21-79"><a href="#cb21-79" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-80"><a href="#cb21-80" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&lt;=&gt;(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">&lt;=&gt;</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-81"><a href="#cb21-81" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-82"><a href="#cb21-82" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&lt;(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">&lt;</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-83"><a href="#cb21-83" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-84"><a href="#cb21-84" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&lt;=(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">&lt;=</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-85"><a href="#cb21-85" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-86"><a href="#cb21-86" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">==(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">==</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-87"><a href="#cb21-87" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-88"><a href="#cb21-88" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">!=(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">!=</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-89"><a href="#cb21-89" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-90"><a href="#cb21-90" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&gt;(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">&gt;</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-91"><a href="#cb21-91" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-92"><a href="#cb21-92" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&gt;=(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>L<span class="op">::</span>value <span class="op">&gt;=</span> R<span class="op">::</span>value<span class="op">)&gt;</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-93"><a href="#cb21-93" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-94"><a href="#cb21-94" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-95"><a href="#cb21-95" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span>,<span class="op">(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;</span><span class="kw">operator</span>,<span class="op">(</span>L<span class="op">::</span>value, R<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb21-96"><a href="#cb21-96" aria-hidden="true" tabindex="-1"></a>         <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-97"><a href="#cb21-97" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> L, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-98"><a href="#cb21-98" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">-&gt;*(</span>L, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;</span><span class="kw">operator</span><span class="op">-&gt;*(</span>L<span class="op">::</span>value, R<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb21-99"><a href="#cb21-99" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-100"><a href="#cb21-100" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-101"><a href="#cb21-101" aria-hidden="true" tabindex="-1"></a>    <span class="co">// call and index</span></span>
<span id="cb21-102"><a href="#cb21-102" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T, <em>constexpr-param</em><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb21-103"><a href="#cb21-103" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">this</span> T, Args<span class="op">...)</span> <span class="kw">noexcept</span></span>
<span id="cb21-104"><a href="#cb21-104" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>T<span class="op">::</span>value_type x, Args<span class="op">...)</span> <span class="op">{</span> x<span class="op">(</span>Args<span class="op">::</span>value<span class="op">...)</span>; <span class="op">}</span></span>
<span id="cb21-105"><a href="#cb21-105" aria-hidden="true" tabindex="-1"></a>          <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;(</span>T<span class="op">::</span>value<span class="op">(</span>Args<span class="op">::</span>value<span class="op">...))&gt;{}</span>; <span class="op">}</span></span>
<span id="cb21-106"><a href="#cb21-106" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T, <em>constexpr-param</em><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb21-107"><a href="#cb21-107" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">[](</span><span class="kw">this</span> T, Args<span class="op">...)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> constant_wrapper<span class="op">&lt;(</span>T<span class="op">::</span>value<span class="op">[</span>Args<span class="op">::</span>value<span class="op">...])&gt;</span></span>
<span id="cb21-108"><a href="#cb21-108" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb21-109"><a href="#cb21-109" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-110"><a href="#cb21-110" aria-hidden="true" tabindex="-1"></a>    <span class="co">// pseudo-mutators</span></span>
<span id="cb21-111"><a href="#cb21-111" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T<span class="op">&gt;</span></span>
<span id="cb21-112"><a href="#cb21-112" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">++(</span><span class="kw">this</span> T<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>T<span class="op">::</span>value_type x<span class="op">)</span> <span class="op">{</span> <span class="op">++</span>x; <span class="op">}</span></span>
<span id="cb21-113"><a href="#cb21-113" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;[]</span> <span class="op">{</span> <span class="kw">auto</span> c <span class="op">=</span> T<span class="op">::</span>value; <span class="cf">return</span> <span class="op">++</span>c; <span class="op">}()&gt;{}</span>; <span class="op">}</span></span>
<span id="cb21-114"><a href="#cb21-114" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T<span class="op">&gt;</span></span>
<span id="cb21-115"><a href="#cb21-115" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">++(</span><span class="kw">this</span> T, <span class="dt">int</span><span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>T<span class="op">::</span>value_type x<span class="op">)</span> <span class="op">{</span> x<span class="op">++</span>; <span class="op">}</span></span>
<span id="cb21-116"><a href="#cb21-116" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;[]</span> <span class="op">{</span> <span class="kw">auto</span> c <span class="op">=</span> T<span class="op">::</span>value; <span class="cf">return</span> c<span class="op">++</span>; <span class="op">}()&gt;{}</span>; <span class="op">}</span></span>
<span id="cb21-117"><a href="#cb21-117" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-118"><a href="#cb21-118" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T<span class="op">&gt;</span></span>
<span id="cb21-119"><a href="#cb21-119" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">--(</span><span class="kw">this</span> T<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>T<span class="op">::</span>value_type x<span class="op">)</span> <span class="op">{</span> <span class="op">--</span>x; <span class="op">}</span></span>
<span id="cb21-120"><a href="#cb21-120" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;[]</span> <span class="op">{</span> <span class="kw">auto</span> c <span class="op">=</span> T<span class="op">::</span>value; <span class="cf">return</span> <span class="op">--</span>c; <span class="op">}()&gt;{}</span>; <span class="op">}</span></span>
<span id="cb21-121"><a href="#cb21-121" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T<span class="op">&gt;</span></span>
<span id="cb21-122"><a href="#cb21-122" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">--(</span><span class="kw">this</span> T, <span class="dt">int</span><span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>T<span class="op">::</span>value_type x<span class="op">)</span> <span class="op">{</span> x<span class="op">--</span>; <span class="op">}</span></span>
<span id="cb21-123"><a href="#cb21-123" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;[]</span> <span class="op">{</span> <span class="kw">auto</span> c <span class="op">=</span> T<span class="op">::</span>value; <span class="cf">return</span> c<span class="op">--</span>; <span class="op">}()&gt;{}</span>; <span class="op">}</span></span>
<span id="cb21-124"><a href="#cb21-124" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-125"><a href="#cb21-125" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-126"><a href="#cb21-126" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">+=(</span><span class="kw">this</span> T, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>T<span class="op">::</span>value_type x<span class="op">)</span> <span class="op">{</span> x <span class="op">+=</span> R<span class="op">::</span>value; <span class="op">}</span></span>
<span id="cb21-127"><a href="#cb21-127" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;[]</span> <span class="op">{</span> <span class="kw">auto</span> v <span class="op">=</span> T<span class="op">::</span>value; <span class="cf">return</span> v <span class="op">+=</span> R<span class="op">::</span>value; <span class="op">}()&gt;{}</span>; <span class="op">}</span></span>
<span id="cb21-128"><a href="#cb21-128" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-129"><a href="#cb21-129" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">-=(</span><span class="kw">this</span> T, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>T<span class="op">::</span>value_type x<span class="op">)</span> <span class="op">{</span> x <span class="op">-=</span> R<span class="op">::</span>value; <span class="op">}</span></span>
<span id="cb21-130"><a href="#cb21-130" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;[]</span> <span class="op">{</span> <span class="kw">auto</span> v <span class="op">=</span> T<span class="op">::</span>value; <span class="cf">return</span> v <span class="op">-=</span> R<span class="op">::</span>value; <span class="op">}()&gt;{}</span>; <span class="op">}</span></span>
<span id="cb21-131"><a href="#cb21-131" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-132"><a href="#cb21-132" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">*=(</span><span class="kw">this</span> T, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>T<span class="op">::</span>value_type x<span class="op">)</span> <span class="op">{</span> x <span class="op">*=</span> R<span class="op">::</span>value; <span class="op">}</span></span>
<span id="cb21-133"><a href="#cb21-133" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;[]</span> <span class="op">{</span> <span class="kw">auto</span> v <span class="op">=</span> T<span class="op">::</span>value; <span class="cf">return</span> v <span class="op">*=</span> R<span class="op">::</span>value; <span class="op">}()&gt;{}</span>; <span class="op">}</span></span>
<span id="cb21-134"><a href="#cb21-134" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-135"><a href="#cb21-135" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">/=(</span><span class="kw">this</span> T, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>T<span class="op">::</span>value_type x<span class="op">)</span> <span class="op">{</span> x <span class="op">/=</span> R<span class="op">::</span>value; <span class="op">}</span></span>
<span id="cb21-136"><a href="#cb21-136" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;[]</span> <span class="op">{</span> <span class="kw">auto</span> v <span class="op">=</span> T<span class="op">::</span>value; <span class="cf">return</span> v <span class="op">/=</span> R<span class="op">::</span>value; <span class="op">}()&gt;{}</span>; <span class="op">}</span></span>
<span id="cb21-137"><a href="#cb21-137" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-138"><a href="#cb21-138" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">%=(</span><span class="kw">this</span> T, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>T<span class="op">::</span>value_type x<span class="op">)</span> <span class="op">{</span> x <span class="op">%=</span> R<span class="op">::</span>value; <span class="op">}</span></span>
<span id="cb21-139"><a href="#cb21-139" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;[]</span> <span class="op">{</span> <span class="kw">auto</span> v <span class="op">=</span> T<span class="op">::</span>value; <span class="cf">return</span> v <span class="op">%=</span> R<span class="op">::</span>value; <span class="op">}()&gt;{}</span>; <span class="op">}</span></span>
<span id="cb21-140"><a href="#cb21-140" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-141"><a href="#cb21-141" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&amp;=(</span><span class="kw">this</span> T, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>T<span class="op">::</span>value_type x<span class="op">)</span> <span class="op">{</span> x <span class="op">&amp;=</span> R<span class="op">::</span>value; <span class="op">}</span></span>
<span id="cb21-142"><a href="#cb21-142" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;[]</span> <span class="op">{</span> <span class="kw">auto</span> v <span class="op">=</span> T<span class="op">::</span>value; <span class="cf">return</span> v <span class="op">&amp;=</span> R<span class="op">::</span>value; <span class="op">}()&gt;{}</span>; <span class="op">}</span></span>
<span id="cb21-143"><a href="#cb21-143" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-144"><a href="#cb21-144" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">|=(</span><span class="kw">this</span> T, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>T<span class="op">::</span>value_type x<span class="op">)</span> <span class="op">{</span> x <span class="op">|=</span> R<span class="op">::</span>value; <span class="op">}</span></span>
<span id="cb21-145"><a href="#cb21-145" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;[]</span> <span class="op">{</span> <span class="kw">auto</span> v <span class="op">=</span> T<span class="op">::</span>value; <span class="cf">return</span> v <span class="op">|=</span> R<span class="op">::</span>value; <span class="op">}()&gt;{}</span>; <span class="op">}</span></span>
<span id="cb21-146"><a href="#cb21-146" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-147"><a href="#cb21-147" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">^=(</span><span class="kw">this</span> T, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>T<span class="op">::</span>value_type x<span class="op">)</span> <span class="op">{</span> x <span class="op">^=</span> R<span class="op">::</span>value; <span class="op">}</span></span>
<span id="cb21-148"><a href="#cb21-148" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;[]</span> <span class="op">{</span> <span class="kw">auto</span> v <span class="op">=</span> T<span class="op">::</span>value; <span class="cf">return</span> v <span class="op">^=</span> R<span class="op">::</span>value; <span class="op">}()&gt;{}</span>; <span class="op">}</span></span>
<span id="cb21-149"><a href="#cb21-149" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-150"><a href="#cb21-150" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&lt;&lt;=(</span><span class="kw">this</span> T, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>T<span class="op">::</span>value_type x<span class="op">)</span> <span class="op">{</span> x <span class="op">&lt;&lt;=</span> R<span class="op">::</span>value; <span class="op">}</span></span>
<span id="cb21-151"><a href="#cb21-151" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;[]</span> <span class="op">{</span> <span class="kw">auto</span> v <span class="op">=</span> T<span class="op">::</span>value; <span class="cf">return</span> v <span class="op">&lt;&lt;=</span> R<span class="op">::</span>value; <span class="op">}()&gt;{}</span>; <span class="op">}</span></span>
<span id="cb21-152"><a href="#cb21-152" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> T, <em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-153"><a href="#cb21-153" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&gt;&gt;=(</span><span class="kw">this</span> T, R<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>T<span class="op">::</span>value_type x<span class="op">)</span> <span class="op">{</span> x <span class="op">&gt;&gt;=</span> R<span class="op">::</span>value; <span class="op">}</span></span>
<span id="cb21-154"><a href="#cb21-154" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;[]</span> <span class="op">{</span> <span class="kw">auto</span> v <span class="op">=</span> T<span class="op">::</span>value; <span class="cf">return</span> v <span class="op">&gt;&gt;=</span> R<span class="op">::</span>value; <span class="op">}()&gt;{}</span>; <span class="op">}</span></span>
<span id="cb21-155"><a href="#cb21-155" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb21-156"><a href="#cb21-156" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-157"><a href="#cb21-157" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><em>cw-fixed-value</em> X, <span class="kw">class</span><span class="op">&gt;</span></span>
<span id="cb21-158"><a href="#cb21-158" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> constant_wrapper<span class="op">:</span> <em>cw-operators</em> <span class="op">{</span></span>
<span id="cb21-159"><a href="#cb21-159" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">const</span> <span class="kw">auto</span> <span class="op">&amp;</span> value <span class="op">=</span> X<span class="op">.</span>data;</span>
<span id="cb21-160"><a href="#cb21-160" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> type <span class="op">=</span> constant_wrapper;</span>
<span id="cb21-161"><a href="#cb21-161" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> value_type <span class="op">=</span> <span class="kw">typename</span> <span class="kw">decltype</span><span class="op">(</span>X<span class="op">)::</span>type;</span>
<span id="cb21-162"><a href="#cb21-162" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-163"><a href="#cb21-163" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><em>constexpr-param</em> R<span class="op">&gt;</span></span>
<span id="cb21-164"><a href="#cb21-164" aria-hidden="true" tabindex="-1"></a>      <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">=(</span>R<span class="op">)</span> <span class="kw">const</span> <span class="kw">noexcept</span> <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>value_type x<span class="op">)</span> <span class="op">{</span> x <span class="op">=</span> R<span class="op">::</span>value; <span class="op">}</span></span>
<span id="cb21-165"><a href="#cb21-165" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;[]</span> <span class="op">{</span> <span class="kw">auto</span> v <span class="op">=</span> value; <span class="cf">return</span> v <span class="op">=</span> R<span class="op">::</span>value; <span class="op">}()&gt;{}</span>; <span class="op">}</span></span>
<span id="cb21-166"><a href="#cb21-166" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-167"><a href="#cb21-167" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">operator</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)()</span> <span class="kw">const</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> value; <span class="op">}</span></span>
<span id="cb21-168"><a href="#cb21-168" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <span class="kw">operator</span><span class="op">()()</span> <span class="kw">const</span> <span class="kw">noexcept</span> <span class="kw">requires</span> <span class="op">(!</span>std<span class="op">::</span>invocable<span class="op">&lt;</span>value_type<span class="op">&gt;)</span> <span class="op">{</span> <span class="cf">return</span> value; <span class="op">}</span></span>
<span id="cb21-169"><a href="#cb21-169" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-170"><a href="#cb21-170" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>cw-operators</em><span class="op">::</span><span class="kw">operator</span><span class="op">()</span>;</span>
<span id="cb21-171"><a href="#cb21-171" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb21-172"><a href="#cb21-172" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-173"><a href="#cb21-173" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><em>cw-fixed-value</em> X<span class="op">&gt;</span></span>
<span id="cb21-174"><a href="#cb21-174" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> cw <span class="op">=</span> constant_wrapper<span class="op">&lt;</span>X<span class="op">&gt;{}</span>;</span>
<span id="cb21-175"><a href="#cb21-175" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="11.2" id="add-a-feature-macro"><span class="header-section-number">11.2</span> Add a feature macro<a href="#add-a-feature-macro" class="self-link"></a></h2>
<p>Add a new feature macro,
<code class="sourceCode default">__cpp_lib_constant_wrapper</code>.</p>
<h1 data-number="12" id="implementation-experience"><span class="header-section-number">12</span> Implementation experience<a href="#implementation-experience" class="self-link"></a></h1>
<p>One of the authors implemented the design in this paper. You can find
it at:</p>
<p><a href="https://github.com/tzlaine/constexpr/blob/master/include/constant_wrapper.hpp">https://github.com/tzlaine/constexpr/blob/master/include/constant_wrapper.hpp</a>.</p>
<p>Additionally, an
<code class="sourceCode default">integral_constant</code> with most of
the operator overloads has been a part of <a href="https://www.boost.org/doc/libs/1_80_0/libs/hana/doc/html/index.html">Boost.Hana</a>
since its initial release in May of 2016. Its operations have been used
by many, many users.</p>
<h1 data-number="13" id="wording"><span class="header-section-number">13</span> Wording<a href="#wording" class="self-link"></a></h1>
<p>Add the following to [meta.type.synop], after
<code class="sourceCode default">false_type</code>:</p>
<div class="add" style="color: #006e28">

<div class="sourceCode" id="cb22"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>template&lt;class T&gt;</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>  struct <em>cw-fixed-value</em>;                                                        // <em>exposition only</em></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>template&lt;<em>cw-fixed-value</em> X,</span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>         class = typename decltype(<em>cw-fixed-value</em>(X))::type&gt;        // <em>exposition only</em></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>  struct constant_wrapper;</span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>template&lt;class T&gt;</span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a>  concept <em>constexpr-param</em> = requires { typename constant_wrapper&lt;T::value&gt;; };  // <em>exposition only</em></span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>struct <em>cw-operators</em>;                                                            // <em>exposition only</em></span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a>template&lt;<em>cw-fixed-value</em> X&gt;</span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a>  constexpr auto cw = constant_wrapper&lt;X&gt;{};</span></code></pre></div>

</div>
<p>Add the following to [meta.help], after
<code class="sourceCode default">integral_constant</code>:</p>
<div class="add" style="color: #006e28">

<div class="sourceCode" id="cb23"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a>template&lt;class T&gt;</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>struct <em>cw-fixed-value</em> {                                                         // <em>exposition only</em></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>  using type = T;</span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>  constexpr <em>cw-fixed-value</em>(type v) noexcept: data(v) { }</span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a>  T data;</span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>};</span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a>template&lt;class T, size_t Extent&gt;</span>
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a>struct <em>cw-fixed-value</em>&lt;T[Extent]&gt; {                                              // <em>exposition only</em></span>
<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a>  using type = T[Extent];</span>
<span id="cb23-11"><a href="#cb23-11" aria-hidden="true" tabindex="-1"></a>  constexpr <em>cw-fixed-value</em>(T (&amp;arr)[Extent]) noexcept: <em>cw-fixed-value</em>(arr, std::make_index_sequence&lt;Extent&gt;()) { }</span>
<span id="cb23-12"><a href="#cb23-12" aria-hidden="true" tabindex="-1"></a>  T data[Extent];</span>
<span id="cb23-13"><a href="#cb23-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-14"><a href="#cb23-14" aria-hidden="true" tabindex="-1"></a>private:</span>
<span id="cb23-15"><a href="#cb23-15" aria-hidden="true" tabindex="-1"></a>  template&lt;size_t... Idx&gt;</span>
<span id="cb23-16"><a href="#cb23-16" aria-hidden="true" tabindex="-1"></a>  constexpr <em>cw-fixed-value</em>(T (&amp;arr)[Extent], std::index_sequence&lt;Idx...&gt;) noexcept: data{arr[Idx]...} { }</span>
<span id="cb23-17"><a href="#cb23-17" aria-hidden="true" tabindex="-1"></a>};</span>
<span id="cb23-18"><a href="#cb23-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-19"><a href="#cb23-19" aria-hidden="true" tabindex="-1"></a>template&lt;class T, size_t Extent&gt;</span>
<span id="cb23-20"><a href="#cb23-20" aria-hidden="true" tabindex="-1"></a>  <em>cw-fixed-value</em>(T (&amp;)[Extent]) -&gt; <em>cw-fixed-value</em>&lt;T[Extent]&gt;;                   // <em>exposition only</em></span>
<span id="cb23-21"><a href="#cb23-21" aria-hidden="true" tabindex="-1"></a>template&lt;class T&gt;</span>
<span id="cb23-22"><a href="#cb23-22" aria-hidden="true" tabindex="-1"></a>  <em>cw-fixed-value</em>(T) -&gt; <em>cw-fixed-value</em>&lt;T&gt;;                                       // <em>exposition only</em></span>
<span id="cb23-23"><a href="#cb23-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-24"><a href="#cb23-24" aria-hidden="true" tabindex="-1"></a>struct <em>cw-operators</em> {                                                           // <em>exposition only</em></span>
<span id="cb23-25"><a href="#cb23-25" aria-hidden="true" tabindex="-1"></a>  // unary operators</span>
<span id="cb23-26"><a href="#cb23-26" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T&gt;</span>
<span id="cb23-27"><a href="#cb23-27" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator+(T) noexcept -&gt; constant_wrapper&lt;(+T::value)&gt; { return {}; }</span>
<span id="cb23-28"><a href="#cb23-28" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T&gt;</span>
<span id="cb23-29"><a href="#cb23-29" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator-(T) noexcept -&gt; constant_wrapper&lt;(-T::value)&gt; { return {}; }</span>
<span id="cb23-30"><a href="#cb23-30" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T&gt;</span>
<span id="cb23-31"><a href="#cb23-31" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator~(T) noexcept -&gt; constant_wrapper&lt;(~T::value)&gt; { return {}; }</span>
<span id="cb23-32"><a href="#cb23-32" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T&gt;</span>
<span id="cb23-33"><a href="#cb23-33" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator!(T) noexcept -&gt; constant_wrapper&lt;(!T::value)&gt; { return {}; }</span>
<span id="cb23-34"><a href="#cb23-34" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T&gt;</span>
<span id="cb23-35"><a href="#cb23-35" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator&amp;(T) noexcept -&gt; constant_wrapper&lt;(&amp;T::value)&gt; { return {}; }</span>
<span id="cb23-36"><a href="#cb23-36" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T&gt;</span>
<span id="cb23-37"><a href="#cb23-37" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator*(T) noexcept -&gt; constant_wrapper&lt;(*T::value)&gt; { return {}; }</span>
<span id="cb23-38"><a href="#cb23-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-39"><a href="#cb23-39" aria-hidden="true" tabindex="-1"></a>  // binary operators</span>
<span id="cb23-40"><a href="#cb23-40" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-41"><a href="#cb23-41" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator+(L, R) noexcept -&gt; constant_wrapper&lt;(L::value + R::value)&gt; { return {}; }</span>
<span id="cb23-42"><a href="#cb23-42" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-43"><a href="#cb23-43" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator-(L, R) noexcept -&gt; constant_wrapper&lt;(L::value - R::value)&gt; { return {}; }</span>
<span id="cb23-44"><a href="#cb23-44" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-45"><a href="#cb23-45" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator*(L, R) noexcept -&gt; constant_wrapper&lt;(L::value * R::value)&gt; { return {}; }</span>
<span id="cb23-46"><a href="#cb23-46" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-47"><a href="#cb23-47" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator/(L, R) noexcept -&gt; constant_wrapper&lt;(L::value / R::value)&gt; { return {}; }</span>
<span id="cb23-48"><a href="#cb23-48" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-49"><a href="#cb23-49" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator%(L, R) noexcept -&gt; constant_wrapper&lt;(L::value % R::value)&gt; { return {}; }</span>
<span id="cb23-50"><a href="#cb23-50" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-51"><a href="#cb23-51" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-52"><a href="#cb23-52" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator&lt;&lt;(L, R) noexcept -&gt; constant_wrapper&lt;(L::value &lt;&lt; R::value)&gt; { return {}; }</span>
<span id="cb23-53"><a href="#cb23-53" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-54"><a href="#cb23-54" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator&gt;&gt;(L, R) noexcept -&gt; constant_wrapper&lt;(L::value &gt;&gt; R::value)&gt; { return {}; }</span>
<span id="cb23-55"><a href="#cb23-55" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-56"><a href="#cb23-56" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator&amp;(L, R) noexcept -&gt; constant_wrapper&lt;(L::value &amp; R::value)&gt; { return {}; }</span>
<span id="cb23-57"><a href="#cb23-57" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-58"><a href="#cb23-58" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator|(L, R) noexcept -&gt; constant_wrapper&lt;(L::value | R::value)&gt; { return {}; }</span>
<span id="cb23-59"><a href="#cb23-59" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-60"><a href="#cb23-60" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator^(L, R) noexcept -&gt; constant_wrapper&lt;(L::value ^ R::value)&gt; { return {}; }</span>
<span id="cb23-61"><a href="#cb23-61" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-62"><a href="#cb23-62" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-63"><a href="#cb23-63" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator&amp;&amp;(L, R) noexcept -&gt; constant_wrapper&lt;(L::value &amp;&amp; R::value)&gt; { return {}; }</span>
<span id="cb23-64"><a href="#cb23-64" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-65"><a href="#cb23-65" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator||(L, R) noexcept -&gt; constant_wrapper&lt;(L::value || R::value)&gt; { return {}; }</span>
<span id="cb23-66"><a href="#cb23-66" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-67"><a href="#cb23-67" aria-hidden="true" tabindex="-1"></a>  // comparisons</span>
<span id="cb23-68"><a href="#cb23-68" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-69"><a href="#cb23-69" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator&lt;=&gt;(L, R) noexcept -&gt; constant_wrapper&lt;(L::value &lt;=&gt; R::value)&gt; { return {}; }</span>
<span id="cb23-70"><a href="#cb23-70" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-71"><a href="#cb23-71" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator&lt;(L, R) noexcept -&gt; constant_wrapper&lt;(L::value &lt; R::value)&gt; { return {}; }</span>
<span id="cb23-72"><a href="#cb23-72" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-73"><a href="#cb23-73" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator&lt;=(L, R) noexcept -&gt; constant_wrapper&lt;(L::value &lt;= R::value)&gt; { return {}; }</span>
<span id="cb23-74"><a href="#cb23-74" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-75"><a href="#cb23-75" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator==(L, R) noexcept -&gt; constant_wrapper&lt;(L::value == R::value)&gt; { return {}; }</span>
<span id="cb23-76"><a href="#cb23-76" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-77"><a href="#cb23-77" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator!=(L, R) noexcept -&gt; constant_wrapper&lt;(L::value != R::value)&gt; { return {}; }</span>
<span id="cb23-78"><a href="#cb23-78" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-79"><a href="#cb23-79" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator&gt;(L, R) noexcept -&gt; constant_wrapper&lt;(L::value &gt; R::value)&gt; { return {}; }</span>
<span id="cb23-80"><a href="#cb23-80" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-81"><a href="#cb23-81" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator&gt;=(L, R) noexcept -&gt; constant_wrapper&lt;(L::value &gt;= R::value)&gt; { return {}; }</span>
<span id="cb23-82"><a href="#cb23-82" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-83"><a href="#cb23-83" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-84"><a href="#cb23-84" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator,(L, R) noexcept -&gt; constant_wrapper&lt;operator,(L::value, R::value)&gt;</span>
<span id="cb23-85"><a href="#cb23-85" aria-hidden="true" tabindex="-1"></a>       { return {}; }</span>
<span id="cb23-86"><a href="#cb23-86" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> L, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-87"><a href="#cb23-87" aria-hidden="true" tabindex="-1"></a>    friend constexpr auto operator-&gt;*(L, R) noexcept -&gt; constant_wrapper&lt;operator-&gt;*(L::value, R::value)&gt;</span>
<span id="cb23-88"><a href="#cb23-88" aria-hidden="true" tabindex="-1"></a>      { return {}; }</span>
<span id="cb23-89"><a href="#cb23-89" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-90"><a href="#cb23-90" aria-hidden="true" tabindex="-1"></a>  // call and index</span>
<span id="cb23-91"><a href="#cb23-91" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T, <em>constexpr-param</em>... Args&gt;</span>
<span id="cb23-92"><a href="#cb23-92" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator()(this T, Args...) noexcept</span>
<span id="cb23-93"><a href="#cb23-93" aria-hidden="true" tabindex="-1"></a>      requires requires(T::value_type x, Args...) { x(Args::value...); }</span>
<span id="cb23-94"><a href="#cb23-94" aria-hidden="true" tabindex="-1"></a>        { return constant_wrapper&lt;(T::value(Args::value...))&gt;{}; }</span>
<span id="cb23-95"><a href="#cb23-95" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T, <em>constexpr-param</em>... Args&gt;</span>
<span id="cb23-96"><a href="#cb23-96" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator[](this T, Args...) noexcept -&gt; constant_wrapper&lt;(T::value[Args::value...])&gt;</span>
<span id="cb23-97"><a href="#cb23-97" aria-hidden="true" tabindex="-1"></a>      { return {}; }</span>
<span id="cb23-98"><a href="#cb23-98" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-99"><a href="#cb23-99" aria-hidden="true" tabindex="-1"></a>  // pseudo-mutators</span>
<span id="cb23-100"><a href="#cb23-100" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T&gt;</span>
<span id="cb23-101"><a href="#cb23-101" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator++(this T) noexcept requires requires(T::value_type x) { ++x; }</span>
<span id="cb23-102"><a href="#cb23-102" aria-hidden="true" tabindex="-1"></a>      { return constant_wrapper&lt;[] { auto c = T::value; return ++c; }()&gt;{}; }</span>
<span id="cb23-103"><a href="#cb23-103" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T&gt;</span>
<span id="cb23-104"><a href="#cb23-104" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator++(this T, int) noexcept requires requires(T::value_type x) { x++; }</span>
<span id="cb23-105"><a href="#cb23-105" aria-hidden="true" tabindex="-1"></a>      { return constant_wrapper&lt;[] { auto c = T::value; return c++; }()&gt;{}; }</span>
<span id="cb23-106"><a href="#cb23-106" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-107"><a href="#cb23-107" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T&gt;</span>
<span id="cb23-108"><a href="#cb23-108" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator--(this T) noexcept requires requires(T::value_type x) { --x; }</span>
<span id="cb23-109"><a href="#cb23-109" aria-hidden="true" tabindex="-1"></a>      { return constant_wrapper&lt;[] { auto c = T::value; return --c; }()&gt;{}; }</span>
<span id="cb23-110"><a href="#cb23-110" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T&gt;</span>
<span id="cb23-111"><a href="#cb23-111" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator--(this T, int) noexcept requires requires(T::value_type x) { x--; }</span>
<span id="cb23-112"><a href="#cb23-112" aria-hidden="true" tabindex="-1"></a>      { return constant_wrapper&lt;[] { auto c = T::value; return c--; }()&gt;{}; }</span>
<span id="cb23-113"><a href="#cb23-113" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-114"><a href="#cb23-114" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-115"><a href="#cb23-115" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator+=(this T, R) noexcept requires requires(T::value_type x) { x += R::value; }</span>
<span id="cb23-116"><a href="#cb23-116" aria-hidden="true" tabindex="-1"></a>      { return constant_wrapper&lt;[] { auto v = T::value; return v += R::value; }()&gt;{}; }</span>
<span id="cb23-117"><a href="#cb23-117" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-118"><a href="#cb23-118" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator-=(this T, R) noexcept requires requires(T::value_type x) { x -= R::value; }</span>
<span id="cb23-119"><a href="#cb23-119" aria-hidden="true" tabindex="-1"></a>      { return constant_wrapper&lt;[] { auto v = T::value; return v -= R::value; }()&gt;{}; }</span>
<span id="cb23-120"><a href="#cb23-120" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-121"><a href="#cb23-121" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator*=(this T, R) noexcept requires requires(T::value_type x) { x *= R::value; }</span>
<span id="cb23-122"><a href="#cb23-122" aria-hidden="true" tabindex="-1"></a>      { return constant_wrapper&lt;[] { auto v = T::value; return v *= R::value; }()&gt;{}; }</span>
<span id="cb23-123"><a href="#cb23-123" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-124"><a href="#cb23-124" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator/=(this T, R) noexcept requires requires(T::value_type x) { x /= R::value; }</span>
<span id="cb23-125"><a href="#cb23-125" aria-hidden="true" tabindex="-1"></a>      { return constant_wrapper&lt;[] { auto v = T::value; return v /= R::value; }()&gt;{}; }</span>
<span id="cb23-126"><a href="#cb23-126" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-127"><a href="#cb23-127" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator%=(this T, R) noexcept requires requires(T::value_type x) { x %= R::value; }</span>
<span id="cb23-128"><a href="#cb23-128" aria-hidden="true" tabindex="-1"></a>      { return constant_wrapper&lt;[] { auto v = T::value; return v %= R::value; }()&gt;{}; }</span>
<span id="cb23-129"><a href="#cb23-129" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-130"><a href="#cb23-130" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator&amp;=(this T, R) noexcept requires requires(T::value_type x) { x &amp;= R::value; }</span>
<span id="cb23-131"><a href="#cb23-131" aria-hidden="true" tabindex="-1"></a>      { return constant_wrapper&lt;[] { auto v = T::value; return v &amp;= R::value; }()&gt;{}; }</span>
<span id="cb23-132"><a href="#cb23-132" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-133"><a href="#cb23-133" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator|=(this T, R) noexcept requires requires(T::value_type x) { x |= R::value; }</span>
<span id="cb23-134"><a href="#cb23-134" aria-hidden="true" tabindex="-1"></a>      { return constant_wrapper&lt;[] { auto v = T::value; return v |= R::value; }()&gt;{}; }</span>
<span id="cb23-135"><a href="#cb23-135" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-136"><a href="#cb23-136" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator^=(this T, R) noexcept requires requires(T::value_type x) { x ^= R::value; }</span>
<span id="cb23-137"><a href="#cb23-137" aria-hidden="true" tabindex="-1"></a>      { return constant_wrapper&lt;[] { auto v = T::value; return v ^= R::value; }()&gt;{}; }</span>
<span id="cb23-138"><a href="#cb23-138" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-139"><a href="#cb23-139" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator&lt;&lt;=(this T, R) noexcept requires requires(T::value_type x) { x &lt;&lt;= R::value; }</span>
<span id="cb23-140"><a href="#cb23-140" aria-hidden="true" tabindex="-1"></a>      { return constant_wrapper&lt;[] { auto v = T::value; return v &lt;&lt;= R::value; }()&gt;{}; }</span>
<span id="cb23-141"><a href="#cb23-141" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> T, <em>constexpr-param</em> R&gt;</span>
<span id="cb23-142"><a href="#cb23-142" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator&gt;&gt;=(this T, R) noexcept requires requires(T::value_type x) { x &gt;&gt;= R::value; }</span>
<span id="cb23-143"><a href="#cb23-143" aria-hidden="true" tabindex="-1"></a>      { return constant_wrapper&lt;[] { auto v = T::value; return v &gt;&gt;= R::value; }()&gt;{}; }</span>
<span id="cb23-144"><a href="#cb23-144" aria-hidden="true" tabindex="-1"></a>};</span>
<span id="cb23-145"><a href="#cb23-145" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-146"><a href="#cb23-146" aria-hidden="true" tabindex="-1"></a>template&lt;<em>cw-fixed-value</em> X, class&gt;</span>
<span id="cb23-147"><a href="#cb23-147" aria-hidden="true" tabindex="-1"></a>struct constant_wrapper: <em>cw-operators</em> {</span>
<span id="cb23-148"><a href="#cb23-148" aria-hidden="true" tabindex="-1"></a>  static constexpr const auto &amp; value = X.data;</span>
<span id="cb23-149"><a href="#cb23-149" aria-hidden="true" tabindex="-1"></a>  using type = constant_wrapper;</span>
<span id="cb23-150"><a href="#cb23-150" aria-hidden="true" tabindex="-1"></a>  using value_type = typename decltype(X)::type;</span>
<span id="cb23-151"><a href="#cb23-151" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-152"><a href="#cb23-152" aria-hidden="true" tabindex="-1"></a>  template&lt;<em>constexpr-param</em> R&gt;</span>
<span id="cb23-153"><a href="#cb23-153" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator=(R) const noexcept requires requires(value_type x) { x = R::value; }</span>
<span id="cb23-154"><a href="#cb23-154" aria-hidden="true" tabindex="-1"></a>      { return constant_wrapper&lt;[] { auto v = value; return v = R::value; }()&gt;{}; }</span>
<span id="cb23-155"><a href="#cb23-155" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-156"><a href="#cb23-156" aria-hidden="true" tabindex="-1"></a>  constexpr operator decltype(auto)() const noexcept { return value; }</span>
<span id="cb23-157"><a href="#cb23-157" aria-hidden="true" tabindex="-1"></a>  constexpr decltype(auto) operator()() const noexcept requires (!std::invocable&lt;value_type&gt;) { return value; }</span>
<span id="cb23-158"><a href="#cb23-158" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-159"><a href="#cb23-159" aria-hidden="true" tabindex="-1"></a>  using <em>cw-operators</em>::operator();</span>
<span id="cb23-160"><a href="#cb23-160" aria-hidden="true" tabindex="-1"></a>};</span>
<span id="cb23-161"><a href="#cb23-161" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-162"><a href="#cb23-162" aria-hidden="true" tabindex="-1"></a>template&lt;<em>cw-fixed-value</em> X&gt;</span>
<span id="cb23-163"><a href="#cb23-163" aria-hidden="true" tabindex="-1"></a>  constexpr auto cw = constant_wrapper&lt;X&gt;{};</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
The class template
<code class="sourceCode default">constant_wrapper</code> aids in
metaprogramming by ensuring that the evaluation of expressions comprised
entirely of <code class="sourceCode default">constant_wrapper</code>s
are core constant expressions ([expr.const]), regardless of the context
in which they appear. In particular, this enables use of
<code class="sourceCode default">constant_wrapper</code> values that are
passed as arguments to <code class="sourceCode default">constexpr</code>
functions to be used in constant expressions.</p>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span></p>
<div class="note">
<p><span>[ <em>Note:</em> </span>The unnamed second template parameter
to <code class="sourceCode default">constant_wrapper</code> is present
to aid argument-dependent lookup (<span>6.5.4
<a href="https://wg21.link/basic.lookup.argdep">[basic.lookup.argdep]</a></span>)
in finding overloads for which
<code class="sourceCode default">constant_wrapper</code>’s wrapped value
is a suitable argument, but for which the
<code class="sourceCode default">constant_wrapper</code> itself is
not.<span> — <em>end note</em> ]</span></p>
</div>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
The variable template <code class="sourceCode default">cw</code> is
provided as a convenient way to nominate
<code class="sourceCode default">constant_wrapper</code> values.</p>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span></p>
<div class="example">
<span>[ <em>Example:</em> </span>
<div class="sourceCode" id="cb24"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a>  constexpr auto initial_phase(auto quantity_1, auto quantity_2) {</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>    return quantity_1 + quantity_2;</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>  constexpr auto middle_phase(auto tbd) {</span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>    return tbd;</span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a>  void final_phase(auto gathered, auto available) {</span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a>    if constexpr (gathered == available)</span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a>      std::cout &lt;&lt; &quot;Profit!\n&quot;;</span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-14"><a href="#cb24-14" aria-hidden="true" tabindex="-1"></a>  void impeccable_underground_planning() {</span>
<span id="cb24-15"><a href="#cb24-15" aria-hidden="true" tabindex="-1"></a>    constexpr auto gathered_quantity = middle_phase(initial_phase(std::cw&lt;42&gt;, std::cw&lt;13&gt;));</span>
<span id="cb24-16"><a href="#cb24-16" aria-hidden="true" tabindex="-1"></a>    static_assert(gathered_quantity == 55);</span>
<span id="cb24-17"><a href="#cb24-17" aria-hidden="true" tabindex="-1"></a>    constexpr auto all_available = std::cw&lt;55&gt;;</span>
<span id="cb24-18"><a href="#cb24-18" aria-hidden="true" tabindex="-1"></a>    final_phase(gathered_quantity, all_available);</span>
<span id="cb24-19"><a href="#cb24-19" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb24-20"><a href="#cb24-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-21"><a href="#cb24-21" aria-hidden="true" tabindex="-1"></a>  void deeply_flawed_underground_planning() {</span>
<span id="cb24-22"><a href="#cb24-22" aria-hidden="true" tabindex="-1"></a>    constexpr auto gathered_quantity = middle_phase(initial_phase(42, 13));</span>
<span id="cb24-23"><a href="#cb24-23" aria-hidden="true" tabindex="-1"></a>    constexpr auto all_available = 55;</span>
<span id="cb24-24"><a href="#cb24-24" aria-hidden="true" tabindex="-1"></a>    final_phase(gathered_quantity, all_available); <em>// error: ‘gathered == available’ is not a constant expression</em></span>
<span id="cb24-25"><a href="#cb24-25" aria-hidden="true" tabindex="-1"></a>  }</span></code></pre></div>
<span> — <em>end example</em> ]</span>
</div>

</div>
<p>Add to [version.syn]:</p>
<div class="add" style="color: #006e28">

<div class="sourceCode" id="cb25"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>#define __cpp_lib_constant_wrapper XXXXXXL // also in &lt;type_traits&gt;</span></code></pre></div>

</div>
</div>
</div>
</body>
</html>
