<!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="2023-01-28" />
  <title>`std::constexpr_v`</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::constexpr_v</code></h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2781R1</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2023-01-28</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-I<br>
      LEWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      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>
</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-stdconstexpr_v-and-stdc_" id="toc-the-difference-in-template-parameters-to-stdconstexpr_v-and-stdc_"><span class="toc-section-number">3.2</span> The difference in template
parameters to <code class="sourceCode default">std::constexpr_v</code>
and
<code class="sourceCode default">std::c_</code><span></span></a></li>
</ul></li>
<li><a href="#making-constexpr_v-more-useful" id="toc-making-constexpr_v-more-useful"><span class="toc-section-number">4</span> Making
<code class="sourceCode default">constexpr_v</code> more
useful<span></span></a></li>
<li><a href="#what-about-strings" id="toc-what-about-strings"><span class="toc-section-number">5</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">6</span> An example using
<code class="sourceCode default">operator()</code><span></span></a></li>
<li><a href="#a-concept-for-detecting-types-like-stdconstexpr_v" id="toc-a-concept-for-detecting-types-like-stdconstexpr_v"><span class="toc-section-number">7</span> A concept for detecting types like
<code class="sourceCode default">std::constexpr_v</code><span></span></a></li>
<li><a href="#design" id="toc-design"><span class="toc-section-number">8</span> Design<span></span></a>
<ul>
<li><a href="#add-constexpr_v" id="toc-add-constexpr_v"><span class="toc-section-number">8.1</span> Add
<code class="sourceCode default">constexpr_v</code><span></span></a></li>
<li><a href="#add-constexpr_value" id="toc-add-constexpr_value"><span class="toc-section-number">8.2</span> Add
<code class="sourceCode default">constexpr_value</code><span></span></a></li>
<li><a href="#add-a-feature-macro" id="toc-add-a-feature-macro"><span class="toc-section-number">8.3</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">9</span> Implementation
experience<span></span></a></li>
<li><a href="#possible-polls-for-lewg" id="toc-possible-polls-for-lewg"><span class="toc-section-number">10</span> Possible polls for
LEWG<span></span></a></li>
<li><a href="#wording" id="toc-wording"><span class="toc-section-number">11</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>
<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 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_v</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>c_<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;</span>, std<span class="op">::</span>c_<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 releative convenience of
<code class="sourceCode default">std::integral_constant</code> versus
the proposed
<code class="sourceCode default">std::constexpr_v</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::constexpr_v</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> X</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">X::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">constexpr_v</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="kw">class</span> T, T X<span class="op">&gt;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> same_as<span class="op">&lt;</span>remove_cvref_t<span class="op">&lt;</span>T<span class="op">&gt;</span>, T<span class="op">&gt;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> constexpr_v</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> T value <span class="op">=</span> X;</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">using</span> value_type <span class="op">=</span> T;</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> type <span class="op">=</span> constexpr_v;</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-11"><a href="#cb4-11" 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="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>    <span class="co">// The rest of the members are discussed below ....</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb4-15"><a href="#cb4-15" 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>X<span class="op">&lt;</span>T<span class="op">&gt;</span> x<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>    x<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>constexpr_v<span class="op">&lt;</span><span class="dt">int</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>    x<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>constexpr_v<span class="op">&lt;</span>std<span class="op">::</span><span class="dt">size_t</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>    x<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>constexpr_v<span class="op">&lt;</span><span class="dt">double</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>    x<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>constexpr_v<span class="op">&lt;</span><span class="dt">float</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>    x<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>constexpr_v<span class="op">&lt;</span><span class="dt">short</span>, foo<span class="op">&gt;{})</span>;</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    x<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>constexpr_v<span class="op">&lt;</span>my_complex, 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">c_</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="kw">auto</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">inline</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span>remove_const_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X<span class="op">)&gt;</span>, X<span class="op">&gt;</span> c_<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>X<span class="op">&lt;</span>T<span class="op">&gt;</span> x<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>    x<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>c_<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>    x<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>c_<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>    x<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>c_<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>    x<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>c_<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>    x<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>c_<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>    x<span class="op">.</span>f<span class="op">(</span>std<span class="op">::</span>c_<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-stdconstexpr_v-and-stdc_"><span class="header-section-number">3.2</span> The difference in template
parameters to <code class="sourceCode default">std::constexpr_v</code>
and <code class="sourceCode default">std::c_</code><a href="#the-difference-in-template-parameters-to-stdconstexpr_v-and-stdc_" class="self-link"></a></h2>
<p><code class="sourceCode default">std::c_</code> takes an
<code class="sourceCode default">auto</code> NTTP.
<code class="sourceCode default">std::constexpr_v</code> takes a type
<code class="sourceCode default">T</code> and an NTTP
<code class="sourceCode default">X</code> for type
<code class="sourceCode default">T</code>. Why is this?</p>
<p>The rationale is that when a user writes
<code class="sourceCode default">std::c_&lt;foo&gt;</code>, we want the
notation to be as terse as possible. Moreover, the user is in complete
control of the <code class="sourceCode default">X</code> value that she
puts in the brackets. In a generic context, that might not always be the
case; you sometimes might want to force the type held by your
<code class="sourceCode default">std::constexpr_v</code> to be a
particular type, say <code class="sourceCode default">size_t</code>. For
instance, say you have an existing function
<code class="sourceCode default">foo()</code>:</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">template</span><span class="op">&lt;</span><span class="dt">size_t</span> X<span class="op">&gt;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> foo<span class="op">(</span>std<span class="op">::</span>constexpr_v<span class="op">&lt;</span><span class="dt">size_t</span>, X<span class="op">&gt;</span> x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="co">/* ... */</span>;</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And now let’s say you want to write a function
<code class="sourceCode default">bar()</code> such that
<code class="sourceCode default">bar&lt;X&gt;()</code> calls <code class="sourceCode default">foo(std::constexpr&lt;size_t, X&gt;{})</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="kw">auto</span> X<span class="op">&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> bar<span class="op">()</span> <span class="op">{</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>constexpr_v<span class="op">&lt;</span><span class="dt">size_t</span>, X<span class="op">&gt;</span> x;</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> y <span class="op">=</span> bar<span class="op">(</span>x<span class="op">)</span>;</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Use y ....</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If you didn’t care what type the
<code class="sourceCode default">T</code> parameter to
<code class="sourceCode default">std::constexpr_v</code> was, you could
use <code class="sourceCode default">std::c_&lt;X&gt;</code> instead.
Having both notational options is useful.</p>
<h1 data-number="4" id="making-constexpr_v-more-useful"><span class="header-section-number">4</span> Making
<code class="sourceCode default">constexpr_v</code> more useful<a href="#making-constexpr_v-more-useful" class="self-link"></a></h1>
<p><code class="sourceCode default">constexpr_v</code> is essentially a
wrapper. It takes a value <code class="sourceCode default">X</code> of
some structural type <code class="sourceCode default">T</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">constexpr_v</code> should be implicitly
convertible to <code class="sourceCode default">T</code>; this is
already reflected in the design presented above. For the same reason,
<code class="sourceCode default">constexpr_v</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">T</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">constexpr_v</code> as natural to use as
many of the types it might wrap.</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">namespace</span> std <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, T X<span class="op">&gt;</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> same_as<span class="op">&lt;</span>remove_cvref_t<span class="op">&lt;</span>T<span class="op">&gt;</span>, T<span class="op">&gt;</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> constexpr_v</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> T value <span class="op">=</span> X;</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> value_type <span class="op">=</span> T;</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> type <span class="op">=</span> constexpr_v;</span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-11"><a href="#cb10-11" 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="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a>    <span class="co">// unary -</span></span>
<span id="cb10-14"><a href="#cb10-14" 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">const</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(-</span>X<span class="op">)</span>, <span class="op">-</span>X<span class="op">&gt;{}</span>; <span class="op">}</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(-</span>X<span class="op">)</span>, <span class="op">-</span>X<span class="op">&gt;{}</span>; <span class="op">}</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>    <span class="co">// binary + and -</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">+</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">+</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">+(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> not_constexpr_v<span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">+</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">+</span> X<span class="op">)&gt;</span></span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">+(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">-</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">-</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb10-28"><a href="#cb10-28" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">-(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb10-29"><a href="#cb10-29" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb10-30"><a href="#cb10-30" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> not_constexpr_v<span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb10-31"><a href="#cb10-31" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">-</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">-</span> X<span class="op">)&gt;</span></span>
<span id="cb10-32"><a href="#cb10-32" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">-(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb10-33"><a href="#cb10-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-34"><a href="#cb10-34" aria-hidden="true" tabindex="-1"></a>    <span class="co">// etc... (full listing later)</span></span>
<span id="cb10-35"><a href="#cb10-35" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb10-36"><a href="#cb10-36" 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">T</code> and
<code class="sourceCode default">U</code> values would, including
promotions and coercions. For example:</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">static_assert</span><span class="op">(</span>std<span class="op">::</span>is_same_v<span class="op">&lt;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>              <span class="kw">decltype</span><span class="op">(</span>std<span class="op">::</span>c_<span class="op">&lt;</span><span class="dv">42</span><span class="op">&gt;</span> <span class="op">-</span> std<span class="op">::</span>c_<span class="op">&lt;</span><span class="dv">13</span><span class="bu">u</span><span class="op">&gt;)</span>,</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>              std<span class="op">::</span>constexpr_v<span class="op">&lt;</span><span class="dt">unsigned</span> <span class="dt">int</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> and
<code class="sourceCode default">Y</code> is defined. Each operation
additionally requires that the result of the underlying operation have a
structural type.</p>
<p>The mutating operations are left out, because none of them makes
sense – the type of the mutated value would have to change, since the
value is itself part of the type.</p>
<p>All the remaining 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.</p>
<p>The only downside to adding
<code class="sourceCode default">std::constexpr_v::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.</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::constexpr_v</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="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">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="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> foo<span class="op">()</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb12-5"><a href="#cb12-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>c_<span class="op">&lt;</span><span class="dv">42</span><span class="op">&gt;</span>;  <span class="co">// Ok.</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb12-7"><a href="#cb12-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::constexpr_v</code> is not limited
to integral types.</p>
<h1 data-number="5" id="what-about-strings"><span class="header-section-number">5</span> What about strings?<a href="#what-about-strings" class="self-link"></a></h1>
<p>As pointed out on the reflector,
<code class="sourceCode default">std::c_&lt;&quot;foo&quot;&gt;</code>
does not work, because of language rules. However, it’s pretty easy for
users to add an NTTP-friendly string wrapper type, and then use that
with <code class="sourceCode default">std::c_&lt;&gt;</code>.</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">template</span><span class="op">&lt;</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> strlit</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb13-4"><a href="#cb13-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="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-6"><a href="#cb13-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="cb13-7"><a href="#cb13-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="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb13-9"><a href="#cb13-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="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-12"><a href="#cb13-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="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb13-14"><a href="#cb13-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="cb13-15"><a href="#cb13-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="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-18"><a href="#cb13-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="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</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="dt">int</span> main<span class="op">()</span></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> f <span class="op">=</span> std<span class="op">::</span>c_<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="cb13-24"><a href="#cb13-24" 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="cb13-25"><a href="#cb13-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h1 data-number="6" id="an-example-using-operator"><span class="header-section-number">6</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="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">namespace</span> parse <span class="op">{</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-3"><a href="#cb14-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="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> or_parser;</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-6"><a href="#cb14-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="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> str_parser</span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb14-9"><a href="#cb14-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="cb14-10"><a href="#cb14-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="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> lit <span class="op">==</span> str_;</span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb14-14"><a href="#cb14-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="cb14-15"><a href="#cb14-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="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span></span>
<span id="cb14-17"><a href="#cb14-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="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true" tabindex="-1"></a>        strlit<span class="op">&lt;</span>N<span class="op">&gt;</span> str_;</span>
<span id="cb14-20"><a href="#cb14-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb14-21"><a href="#cb14-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-22"><a href="#cb14-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="cb14-23"><a href="#cb14-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> or_parser</span>
<span id="cb14-24"><a href="#cb14-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb14-25"><a href="#cb14-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="cb14-26"><a href="#cb14-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="cb14-27"><a href="#cb14-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span></span>
<span id="cb14-28"><a href="#cb14-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="cb14-29"><a href="#cb14-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb14-30"><a href="#cb14-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="cb14-31"><a href="#cb14-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="cb14-32"><a href="#cb14-32" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span></span>
<span id="cb14-33"><a href="#cb14-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="cb14-34"><a href="#cb14-34" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb14-35"><a href="#cb14-35" aria-hidden="true" tabindex="-1"></a>        L l_;</span>
<span id="cb14-36"><a href="#cb14-36" aria-hidden="true" tabindex="-1"></a>        R r_;</span>
<span id="cb14-37"><a href="#cb14-37" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb14-38"><a href="#cb14-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-39"><a href="#cb14-39" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb14-40"><a href="#cb14-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-41"><a href="#cb14-41" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> foo<span class="op">()</span></span>
<span id="cb14-42"><a href="#cb14-42" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb14-43"><a href="#cb14-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="cb14-44"><a href="#cb14-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="cb14-45"><a href="#cb14-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="cb14-46"><a href="#cb14-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-47"><a href="#cb14-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="cb14-48"><a href="#cb14-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-49"><a href="#cb14-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="cb14-50"><a href="#cb14-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="cb14-51"><a href="#cb14-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="cb14-52"><a href="#cb14-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="cb14-53"><a href="#cb14-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="cb14-54"><a href="#cb14-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="cb14-55"><a href="#cb14-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::constexpr_v</code>
expressions. Having to work around the absence of
<code class="sourceCode default">std::constexpr_v::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::c_</code>.</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="dt">int</span> bar<span class="op">()</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb15-3"><a href="#cb15-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="cb15-4"><a href="#cb15-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="cb15-5"><a href="#cb15-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="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-7"><a href="#cb15-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>c_<span class="op">&lt;</span>p1<span class="op">&gt;</span> <span class="op">|</span> std<span class="op">::</span>c_<span class="op">&lt;</span>p2<span class="op">&gt;</span> <span class="op">|</span> std<span class="op">::</span>c_<span class="op">&lt;</span>p3<span class="op">&gt;</span>;</span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-9"><a href="#cb15-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>c_<span class="op">&lt;</span>strlit<span class="op">(</span><span class="st">&quot;&quot;</span><span class="op">)&gt;)</span>;</span>
<span id="cb15-10"><a href="#cb15-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="cb15-11"><a href="#cb15-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>c_<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="cb15-12"><a href="#cb15-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="cb15-13"><a href="#cb15-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>c_<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="cb15-14"><a href="#cb15-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="cb15-15"><a href="#cb15-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="7" id="a-concept-for-detecting-types-like-stdconstexpr_v"><span class="header-section-number">7</span> A concept for detecting types
like <code class="sourceCode default">std::constexpr_v</code><a href="#a-concept-for-detecting-types-like-stdconstexpr_v" class="self-link"></a></h1>
<p>It was suggested in the 2023-02 Issaquah meeting review that it might
be useful also to standardize a concept that could be used to detect
<code class="sourceCode default">std::constexpr_v</code>-like types –
that is, types that have a
<code class="sourceCode default">static</code>,
<code class="sourceCode default">constepxr</code> data member called
<code class="sourceCode default">value</code>. Such a concept is easy to
write.</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="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">typename</span> ValueType<span class="op">&gt;</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> constexpr_value <span class="op">=</span> <span class="kw">requires</span> <span class="op">{</span> <span class="kw">constexpr</span> ValueType x <span class="op">=</span> T<span class="op">::</span>value; <span class="op">}</span>;</span></code></pre></div>
<p>This concept allows you to conveniently express the requirements on
function parameters that must be usable as constant expressions within
your function.</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">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, T Value<span class="op">&gt;</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> my_constant</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> T value <span class="op">=</span> Value;</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="co">// Other API ...</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> plus<span class="op">(</span>constexpr_value<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> <span class="kw">auto</span> x, constexpr_value<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> <span class="kw">auto</span> y<span class="op">)</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a><span class="op">{</span> <span class="cf">return</span> std<span class="op">::</span>c_<span class="op">&lt;</span>x<span class="op">.</span>value <span class="op">+</span> y<span class="op">.</span>value<span class="op">&gt;</span>; <span class="op">}</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> h<span class="op">()</span></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="co">// All results are equal to std::c_&lt;1&gt;.</span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> result_1 <span class="op">=</span> plus<span class="op">(</span>std<span class="op">::</span>c_<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;</span>, std<span class="op">::</span>c_<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;)</span>;                        <span class="co">// Ok.</span></span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> result_2 <span class="op">=</span> plus<span class="op">(</span>std<span class="op">::</span>c_<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;</span>, std<span class="op">::</span>integral_constant<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">1</span><span class="op">&gt;{})</span>;  <span class="co">// Also ok.</span></span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> result_3 <span class="op">=</span> plus<span class="op">(</span>std<span class="op">::</span>c_<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;</span>, my_constant<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">1</span><span class="op">&gt;{})</span>;             <span class="co">// Still ok.</span></span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>However, you sometimes might want to constain a parameter to types
that contain a <code class="sourceCode default">value</code> member of
any type. For example, say you want to define
<code class="sourceCode default">std::constexpr_v</code>-style operator
overloads for several constant-wrapping types you might have, without
relying on <code class="sourceCode default">std::constexpr_v</code>’s
operators at all. For that, you would want a slightly different
concept.</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="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> constexpr_value <span class="op">=</span> <span class="kw">requires</span> <span class="op">{</span> <span class="kw">constexpr</span> <span class="kw">auto</span> x <span class="op">=</span> T<span class="op">::</span>value; <span class="op">}</span>;</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> <span class="kw">operator</span><span class="op">+(</span>constexpr_value <span class="kw">auto</span> x, constexpr_value <span class="kw">auto</span> y<span class="op">)</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> <span class="kw">decltype</span><span class="op">(</span>std<span class="op">::</span>c_<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>x<span class="op">)::</span>value <span class="op">+</span> <span class="kw">decltype</span><span class="op">(</span>y<span class="op">)::</span>value<span class="op">&gt;)</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a><span class="op">{</span> <span class="cf">return</span> std<span class="op">::</span>c_<span class="op">&lt;</span>x<span class="op">.</span>value <span class="op">+</span> y<span class="op">.</span>value<span class="op">&gt;</span>; <span class="op">}</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> i<span class="op">()</span></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">// result is equal to std::c_&lt;1&gt;.</span></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> result <span class="op">=</span> std<span class="op">::</span>integral_constant<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">0</span><span class="op">&gt;{}</span> <span class="op">+</span> my_constant<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">1</span><span class="op">&gt;{}</span>;</span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In the design below, the concept is called
<code class="sourceCode default">constexpr_value</code>, and it is
possible to use it in both the ways just demonstrated.</p>
<h1 data-number="8" id="design"><span class="header-section-number">8</span> Design<a href="#design" class="self-link"></a></h1>
<h2 data-number="8.1" id="add-constexpr_v"><span class="header-section-number">8.1</span> Add
<code class="sourceCode default">constexpr_v</code><a href="#add-constexpr_v" class="self-link"></a></h2>
<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">namespace</span> std <span class="op">{</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, T X<span class="op">&gt;</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> same_as<span class="op">&lt;</span>remove_cvref_t<span class="op">&lt;</span>T<span class="op">&gt;</span>, T<span class="op">&gt;</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>      <span class="kw">struct</span> constexpr_v;</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-6"><a href="#cb19-6" 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="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> <em>not-constexpr-t</em> <span class="op">=</span> <span class="kw">true</span>;                      <span class="co">// <em>exposition only</em></span></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, T X<span class="op">&gt;</span></span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">bool</span> <em>not-constexpr-t</em><span class="op">&lt;</span>constexpr_v<span class="op">&lt;</span>T, X<span class="op">&gt;&gt;</span> <span class="op">=</span> <span class="kw">false</span>;  <span class="co">// <em>exposition only</em></span></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, T X<span class="op">&gt;</span></span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> same_as<span class="op">&lt;</span>remove_cvref_t<span class="op">&lt;</span>T<span class="op">&gt;</span>, T<span class="op">&gt;</span></span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> constexpr_v</span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb19-15"><a href="#cb19-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> T value <span class="op">=</span> X;</span>
<span id="cb19-16"><a href="#cb19-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-17"><a href="#cb19-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> value_type <span class="op">=</span> T;</span>
<span id="cb19-18"><a href="#cb19-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> type <span class="op">=</span> constexpr_v;</span>
<span id="cb19-19"><a href="#cb19-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-20"><a href="#cb19-20" 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="cb19-21"><a href="#cb19-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-22"><a href="#cb19-22" 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">const</span></span>
<span id="cb19-23"><a href="#cb19-23" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(+</span>X<span class="op">)</span>, <span class="op">+</span>X<span class="op">&gt;{}</span>; <span class="op">}</span></span>
<span id="cb19-24"><a href="#cb19-24" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(+</span>X<span class="op">)</span>, <span class="op">+</span>X<span class="op">&gt;{}</span>; <span class="op">}</span></span>
<span id="cb19-25"><a href="#cb19-25" 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">const</span></span>
<span id="cb19-26"><a href="#cb19-26" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(-</span>X<span class="op">)</span>, <span class="op">-</span>X<span class="op">&gt;{}</span>; <span class="op">}</span></span>
<span id="cb19-27"><a href="#cb19-27" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(-</span>X<span class="op">)</span>, <span class="op">-</span>X<span class="op">&gt;{}</span>; <span class="op">}</span></span>
<span id="cb19-28"><a href="#cb19-28" 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">const</span></span>
<span id="cb19-29"><a href="#cb19-29" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(~</span>X<span class="op">)</span>, <span class="op">~</span>X<span class="op">&gt;{}</span>; <span class="op">}</span></span>
<span id="cb19-30"><a href="#cb19-30" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(~</span>X<span class="op">)</span>, <span class="op">~</span>X<span class="op">&gt;{}</span>; <span class="op">}</span></span>
<span id="cb19-31"><a href="#cb19-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> <span class="kw">const</span></span>
<span id="cb19-32"><a href="#cb19-32" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(!</span>X<span class="op">)</span>, <span class="op">!</span>X<span class="op">&gt;{}</span>; <span class="op">}</span></span>
<span id="cb19-33"><a href="#cb19-33" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(!</span>X<span class="op">)</span>, <span class="op">!</span>X<span class="op">&gt;{}</span>; <span class="op">}</span></span>
<span id="cb19-34"><a href="#cb19-34" 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">const</span></span>
<span id="cb19-35"><a href="#cb19-35" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(&amp;</span>X<span class="op">)</span>, <span class="op">&amp;</span>X<span class="op">&gt;{}</span>; <span class="op">}</span></span>
<span id="cb19-36"><a href="#cb19-36" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(&amp;</span>X<span class="op">)</span>, <span class="op">&amp;</span>X<span class="op">&gt;{}</span>; <span class="op">}</span></span>
<span id="cb19-37"><a href="#cb19-37" 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">const</span></span>
<span id="cb19-38"><a href="#cb19-38" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(*</span>X<span class="op">)</span>, <span class="op">*</span>X<span class="op">&gt;{}</span>; <span class="op">}</span></span>
<span id="cb19-39"><a href="#cb19-39" aria-hidden="true" tabindex="-1"></a>        <span class="op">{</span> <span class="cf">return</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(*</span>X<span class="op">)</span>, <span class="op">*</span>X<span class="op">&gt;{}</span>; <span class="op">}</span></span>
<span id="cb19-40"><a href="#cb19-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-41"><a href="#cb19-41" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-42"><a href="#cb19-42" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">&lt;&lt;</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">&lt;&lt;</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-43"><a href="#cb19-43" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">&lt;&lt;(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-44"><a href="#cb19-44" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-45"><a href="#cb19-45" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-46"><a href="#cb19-46" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">&lt;&lt;</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">&lt;&lt;</span> X<span class="op">)&gt;</span></span>
<span id="cb19-47"><a href="#cb19-47" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">&lt;&lt;(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-48"><a href="#cb19-48" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-49"><a href="#cb19-49" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">&gt;&gt;</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">&gt;&gt;</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-50"><a href="#cb19-50" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">&gt;&gt;(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-51"><a href="#cb19-51" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-52"><a href="#cb19-52" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-53"><a href="#cb19-53" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">&gt;&gt;</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">&gt;&gt;</span> X<span class="op">)&gt;</span></span>
<span id="cb19-54"><a href="#cb19-54" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">&gt;&gt;(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-55"><a href="#cb19-55" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-56"><a href="#cb19-56" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">*</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">*</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-57"><a href="#cb19-57" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">*(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-58"><a href="#cb19-58" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-59"><a href="#cb19-59" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-60"><a href="#cb19-60" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">*</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">*</span> X<span class="op">)&gt;</span></span>
<span id="cb19-61"><a href="#cb19-61" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">*(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-62"><a href="#cb19-62" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-63"><a href="#cb19-63" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">/</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">/</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-64"><a href="#cb19-64" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">/(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-65"><a href="#cb19-65" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-66"><a href="#cb19-66" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-67"><a href="#cb19-67" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">/</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">/</span> X<span class="op">)&gt;</span></span>
<span id="cb19-68"><a href="#cb19-68" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">/(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-69"><a href="#cb19-69" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-70"><a href="#cb19-70" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">%</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">%</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-71"><a href="#cb19-71" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">%(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-72"><a href="#cb19-72" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-73"><a href="#cb19-73" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-74"><a href="#cb19-74" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">%</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">%</span> X<span class="op">)&gt;</span></span>
<span id="cb19-75"><a href="#cb19-75" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">%(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-76"><a href="#cb19-76" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-77"><a href="#cb19-77" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">+</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">+</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-78"><a href="#cb19-78" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">+(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-79"><a href="#cb19-79" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-80"><a href="#cb19-80" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-81"><a href="#cb19-81" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">+</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">+</span> X<span class="op">)&gt;</span></span>
<span id="cb19-82"><a href="#cb19-82" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">+(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-83"><a href="#cb19-83" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-84"><a href="#cb19-84" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">-</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">-</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-85"><a href="#cb19-85" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">-(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-86"><a href="#cb19-86" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-87"><a href="#cb19-87" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-88"><a href="#cb19-88" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">-</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">-</span> X<span class="op">)&gt;</span></span>
<span id="cb19-89"><a href="#cb19-89" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">-(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-90"><a href="#cb19-90" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-91"><a href="#cb19-91" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-92"><a href="#cb19-92" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">&lt;</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">&lt;</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-93"><a href="#cb19-93" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">&lt;(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-94"><a href="#cb19-94" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-95"><a href="#cb19-95" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-96"><a href="#cb19-96" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">&lt;</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">&lt;</span> X<span class="op">)&gt;</span></span>
<span id="cb19-97"><a href="#cb19-97" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">&lt;(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-98"><a href="#cb19-98" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-99"><a href="#cb19-99" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">&gt;</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">&gt;</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-100"><a href="#cb19-100" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">&gt;(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-101"><a href="#cb19-101" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-102"><a href="#cb19-102" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-103"><a href="#cb19-103" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">&gt;</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">&gt;</span> X<span class="op">)&gt;</span></span>
<span id="cb19-104"><a href="#cb19-104" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">&gt;(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-105"><a href="#cb19-105" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-106"><a href="#cb19-106" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">&lt;=</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">&lt;=</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-107"><a href="#cb19-107" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">&lt;=(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-108"><a href="#cb19-108" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-109"><a href="#cb19-109" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-110"><a href="#cb19-110" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">&lt;=</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">&lt;=</span> X<span class="op">)&gt;</span></span>
<span id="cb19-111"><a href="#cb19-111" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">&lt;=(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-112"><a href="#cb19-112" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-113"><a href="#cb19-113" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">&gt;=</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">&gt;=</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-114"><a href="#cb19-114" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">&gt;=(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-115"><a href="#cb19-115" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-116"><a href="#cb19-116" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-117"><a href="#cb19-117" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">&gt;=</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">&gt;=</span> X<span class="op">)&gt;</span></span>
<span id="cb19-118"><a href="#cb19-118" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">&gt;=(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-119"><a href="#cb19-119" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-120"><a href="#cb19-120" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">==</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">==</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-121"><a href="#cb19-121" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">==(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-122"><a href="#cb19-122" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-123"><a href="#cb19-123" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-124"><a href="#cb19-124" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">==</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">==</span> X<span class="op">)&gt;</span></span>
<span id="cb19-125"><a href="#cb19-125" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">==(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-126"><a href="#cb19-126" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-127"><a href="#cb19-127" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">!=</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">!=</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-128"><a href="#cb19-128" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">!=(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-129"><a href="#cb19-129" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-130"><a href="#cb19-130" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-131"><a href="#cb19-131" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">!=</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">!=</span> X<span class="op">)&gt;</span></span>
<span id="cb19-132"><a href="#cb19-132" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">!=(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-133"><a href="#cb19-133" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-134"><a href="#cb19-134" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">&lt;=&gt;</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">&lt;=&gt;</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-135"><a href="#cb19-135" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">&lt;=&gt;(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-136"><a href="#cb19-136" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-137"><a href="#cb19-137" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-138"><a href="#cb19-138" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">&lt;=&gt;</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">&lt;=&gt;</span> X<span class="op">)&gt;</span></span>
<span id="cb19-139"><a href="#cb19-139" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">&lt;=&gt;(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-140"><a href="#cb19-140" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-141"><a href="#cb19-141" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-142"><a href="#cb19-142" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">&amp;&amp;</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">&amp;&amp;</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-143"><a href="#cb19-143" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">&amp;&amp;(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-144"><a href="#cb19-144" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-145"><a href="#cb19-145" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-146"><a href="#cb19-146" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">&amp;&amp;</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">&amp;&amp;</span> X<span class="op">)&gt;</span></span>
<span id="cb19-147"><a href="#cb19-147" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">&amp;&amp;(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-148"><a href="#cb19-148" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-149"><a href="#cb19-149" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">||</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">||</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-150"><a href="#cb19-150" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">||(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-151"><a href="#cb19-151" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-152"><a href="#cb19-152" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-153"><a href="#cb19-153" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">||</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">||</span> X<span class="op">)&gt;</span></span>
<span id="cb19-154"><a href="#cb19-154" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">||(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-155"><a href="#cb19-155" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-156"><a href="#cb19-156" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">&amp;</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">&amp;</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-157"><a href="#cb19-157" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">&amp;(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-158"><a href="#cb19-158" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-159"><a href="#cb19-159" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-160"><a href="#cb19-160" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">&amp;</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">&amp;</span> X<span class="op">)&gt;</span></span>
<span id="cb19-161"><a href="#cb19-161" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">&amp;(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-162"><a href="#cb19-162" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-163"><a href="#cb19-163" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">|</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">|</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-164"><a href="#cb19-164" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">|(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-165"><a href="#cb19-165" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-166"><a href="#cb19-166" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-167"><a href="#cb19-167" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">|</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">|</span> X<span class="op">)&gt;</span></span>
<span id="cb19-168"><a href="#cb19-168" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">|(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-169"><a href="#cb19-169" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-170"><a href="#cb19-170" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">^</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">^</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-171"><a href="#cb19-171" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">^(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-172"><a href="#cb19-172" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-173"><a href="#cb19-173" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-174"><a href="#cb19-174" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">^</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">^</span> X<span class="op">)&gt;</span></span>
<span id="cb19-175"><a href="#cb19-175" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">^(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-176"><a href="#cb19-176" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-177"><a href="#cb19-177" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-178"><a href="#cb19-178" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X , U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X , U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-179"><a href="#cb19-179" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span>,<span class="op">(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-180"><a href="#cb19-180" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-181"><a href="#cb19-181" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-182"><a href="#cb19-182" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value , X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value , X<span class="op">)&gt;</span></span>
<span id="cb19-183"><a href="#cb19-183" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span>,<span class="op">(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-184"><a href="#cb19-184" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-185"><a href="#cb19-185" aria-hidden="true" tabindex="-1"></a>      <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X <span class="op">-&gt;*</span> U<span class="op">::</span>value<span class="op">)</span>, <span class="op">(</span>X <span class="op">-&gt;*</span> U<span class="op">::</span>value<span class="op">)&gt;</span></span>
<span id="cb19-186"><a href="#cb19-186" aria-hidden="true" tabindex="-1"></a>        <span class="kw">operator</span><span class="op">-&gt;*(</span>constexpr_v, U<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-187"><a href="#cb19-187" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb19-188"><a href="#cb19-188" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <em>not-constexpr-t</em><span class="op">&lt;</span>U<span class="op">&gt;</span></span>
<span id="cb19-189"><a href="#cb19-189" aria-hidden="true" tabindex="-1"></a>        <span class="kw">friend</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>U<span class="op">::</span>value <span class="op">-&gt;*</span> X<span class="op">)</span>, <span class="op">(</span>U<span class="op">::</span>value <span class="op">-&gt;*</span> X<span class="op">)&gt;</span></span>
<span id="cb19-190"><a href="#cb19-190" aria-hidden="true" tabindex="-1"></a>          <span class="kw">operator</span><span class="op">-&gt;*(</span>U, constexpr_v<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span></span>
<span id="cb19-191"><a href="#cb19-191" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-192"><a href="#cb19-192" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb19-193"><a href="#cb19-193" 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>Args<span class="op">...</span> args<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb19-194"><a href="#cb19-194" aria-hidden="true" tabindex="-1"></a>        <span class="op">-&gt;</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X<span class="op">(</span>Args<span class="op">::</span>value<span class="op">...))</span>, X<span class="op">(</span>Args<span class="op">::</span>value<span class="op">...)&gt;</span></span>
<span id="cb19-195"><a href="#cb19-195" 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="cb19-196"><a href="#cb19-196" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb19-197"><a href="#cb19-197" 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>Args<span class="op">...</span> args<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb19-198"><a href="#cb19-198" aria-hidden="true" tabindex="-1"></a>        <span class="op">-&gt;</span> constexpr_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X<span class="op">[</span>Args<span class="op">::</span>value<span class="op">...])</span>, X<span class="op">[</span>Args<span class="op">::</span>value<span class="op">...]&gt;</span></span>
<span id="cb19-199"><a href="#cb19-199" 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="cb19-200"><a href="#cb19-200" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb19-201"><a href="#cb19-201" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-202"><a href="#cb19-202" 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="cb19-203"><a href="#cb19-203" aria-hidden="true" tabindex="-1"></a>    <span class="kw">inline</span> <span class="kw">constexpr</span> constexpr_v<span class="op">&lt;</span>remove_const_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>X<span class="op">)&gt;</span>, X<span class="op">&gt;</span> c_<span class="op">{}</span>;</span>
<span id="cb19-204"><a href="#cb19-204" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="8.2" id="add-constexpr_value"><span class="header-section-number">8.2</span> Add
<code class="sourceCode default">constexpr_value</code><a href="#add-constexpr_value" class="self-link"></a></h2>
<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">namespace</span> std <span class="op">{</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">typename</span> ValueType <span class="op">=</span> <span class="dt">void</span><span class="op">&gt;</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> constexpr_value <span class="op">=</span> <em>see below</em>;</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This concept is equivalent to <code class="sourceCode default">requires { constexpr auto x = T::value; }</code>
when <code class="sourceCode default">ValueType</code> is
<code class="sourceCode default">void</code>, and <code class="sourceCode default">requires { constexpr ValueType x = T::value; }</code>
otherwise.</p>
<h2 data-number="8.3" id="add-a-feature-macro"><span class="header-section-number">8.3</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_constexpr_v</code>.</p>
<h1 data-number="9" id="implementation-experience"><span class="header-section-number">9</span> Implementation experience<a href="#implementation-experience" class="self-link"></a></h1>
<p>Look up a few lines to see an implementation of
<code class="sourceCode default">std::constexpr_v</code>. At the time of
this writing, there is one caveat:
<code class="sourceCode default">operator[]()</code> looks correct to
the authors, but does not work in any compiler tested, due to the very
limited multi-variate <code class="sourceCode default">operator[]</code>
support in even the latest compilers.</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="10" id="possible-polls-for-lewg"><span class="header-section-number">10</span> Possible polls for LEWG<a href="#possible-polls-for-lewg" class="self-link"></a></h1>
<ul>
<li><p>We should call
<code class="sourceCode default">std::constexpr_v</code>:</p>
<ul>
<li><code class="sourceCode default">std::constexpr_v</code></li>
<li><code class="sourceCode default">std::constexpr_t</code></li>
<li><code class="sourceCode default">std::constexpr_value</code></li>
<li><code class="sourceCode default">std::constant_v</code></li>
<li><code class="sourceCode default">std::constant_t</code></li>
<li><code class="sourceCode default">std::constant_value</code></li>
<li><code class="sourceCode default">std::const_v</code></li>
<li><code class="sourceCode default">std::const_t</code></li>
<li><code class="sourceCode default">std::const_value</code></li>
</ul></li>
<li><p>We should call
<code class="sourceCode default">std::c_</code>:</p>
<ul>
<li><code class="sourceCode default">std::c_</code></li>
<li><code class="sourceCode default">std::c</code></li>
<li><code class="sourceCode default">std::co</code></li>
<li><code class="sourceCode default">std::ct</code></li>
<li><code class="sourceCode default">std::_C</code></li>
<li><code class="sourceCode default">std::cx</code></li>
<li><code class="sourceCode default">std::c_v</code></li>
<li><code class="sourceCode default">std::cv</code></li>
<li><code class="sourceCode default">std::v_</code></li>
<li><code class="sourceCode default">std::_v</code></li>
<li><code class="sourceCode default">std::cn</code></li>
<li><code class="sourceCode default">std::con</code></li>
<li><code class="sourceCode default">std::cnt</code></li>
<li><code class="sourceCode default">std::cnst</code></li>
<li><code class="sourceCode default">std::const_</code></li>
<li><code class="sourceCode default">std::Const</code></li>
<li>All of the above in a nested namespace.</li>
</ul></li>
<li><p>We want a concept like
<code class="sourceCode default">std::constexpr_value</code> that
identifies types that have a
<code class="sourceCode default">static</code>,
<code class="sourceCode default">constexpr</code> data member named
<code class="sourceCode default">value</code> convertible to a specific
type.</p></li>
<li><p>We want a concept like
<code class="sourceCode default">std::any_constexpr_value</code> that
identifies types that have a
<code class="sourceCode default">static</code>,
<code class="sourceCode default">constexpr</code> data member named
<code class="sourceCode default">value</code> of any type.</p></li>
</ul>
<h1 data-number="11" id="wording"><span class="header-section-number">11</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="cb21"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>template&lt;class T, T X&gt;</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>  requires same_as&lt;remove_cvref_t&lt;T&gt;, T&gt;</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>struct constexpr_v;</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>template&lt;class T&gt;</span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>  constexpr bool <em>not-constexpr-t</em> = true;                      // <em>exposition only</em></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>template&lt;class T, T X&gt;</span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>  constexpr bool <em>not-constexpr-t</em>&lt;constexpr_v&lt;T, X&gt;&gt; = false;  // <em>exposition only</em></span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>template&lt;auto X&gt;</span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a>  inline constexpr constexpr_v&lt;remove_const_t&lt;decltype(X)&gt;, X&gt; c_;</span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a>template&lt;typename T, typename ValueType = void&gt;</span>
<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a>  concept constexpr_value = <em>see below</em>;</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="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, T X&gt;</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>  requires same_as&lt;remove_cvref_t&lt;T&gt;, T&gt;</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>struct constexpr_v</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>{</span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>  static constexpr T value = X;</span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>  using value_type = T;</span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>  using type = constexpr_v;</span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a>  constexpr operator value_type() const { return X; }</span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>  constexpr auto operator+() const</span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a>    requires requires { constexpr_v&lt;decltype(+X), +X&gt;{}; }</span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a>      { return constexpr_v&lt;decltype(+X), +X&gt;{}; }</span>
<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a>  constexpr auto operator-() const</span>
<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a>    requires requires { constexpr_v&lt;decltype(-X), -X&gt;{}; }</span>
<span id="cb22-17"><a href="#cb22-17" aria-hidden="true" tabindex="-1"></a>      { return constexpr_v&lt;decltype(-X), -X&gt;{}; }</span>
<span id="cb22-18"><a href="#cb22-18" aria-hidden="true" tabindex="-1"></a>  constexpr auto operator~() const</span>
<span id="cb22-19"><a href="#cb22-19" aria-hidden="true" tabindex="-1"></a>    requires requires { constexpr_v&lt;decltype(~X), ~X&gt;{}; }</span>
<span id="cb22-20"><a href="#cb22-20" aria-hidden="true" tabindex="-1"></a>      { return constexpr_v&lt;decltype(~X), ~X&gt;{}; }</span>
<span id="cb22-21"><a href="#cb22-21" aria-hidden="true" tabindex="-1"></a>  constexpr auto operator!() const</span>
<span id="cb22-22"><a href="#cb22-22" aria-hidden="true" tabindex="-1"></a>    requires requires { constexpr_v&lt;decltype(!X), !X&gt;{}; }</span>
<span id="cb22-23"><a href="#cb22-23" aria-hidden="true" tabindex="-1"></a>      { return constexpr_v&lt;decltype(!X), !X&gt;{}; }</span>
<span id="cb22-24"><a href="#cb22-24" aria-hidden="true" tabindex="-1"></a>  constexpr auto operator&amp;() const</span>
<span id="cb22-25"><a href="#cb22-25" aria-hidden="true" tabindex="-1"></a>    requires requires { constexpr_v&lt;decltype(&amp;X), &amp;X&gt;{}; }</span>
<span id="cb22-26"><a href="#cb22-26" aria-hidden="true" tabindex="-1"></a>      { return constexpr_v&lt;decltype(&amp;X), &amp;X&gt;{}; }</span>
<span id="cb22-27"><a href="#cb22-27" aria-hidden="true" tabindex="-1"></a>  constexpr auto operator*() const</span>
<span id="cb22-28"><a href="#cb22-28" aria-hidden="true" tabindex="-1"></a>    requires requires { constexpr_v&lt;decltype(*X), *X&gt;{}; }</span>
<span id="cb22-29"><a href="#cb22-29" aria-hidden="true" tabindex="-1"></a>      { return constexpr_v&lt;decltype(*X), *X&gt;{}; }</span>
<span id="cb22-30"><a href="#cb22-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-31"><a href="#cb22-31" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-32"><a href="#cb22-32" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X &lt;&lt; U::value), (X &lt;&lt; U::value)&gt;</span>
<span id="cb22-33"><a href="#cb22-33" aria-hidden="true" tabindex="-1"></a>      operator&lt;&lt;(constexpr_v, U) { return {}; }</span>
<span id="cb22-34"><a href="#cb22-34" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-35"><a href="#cb22-35" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-36"><a href="#cb22-36" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value &lt;&lt; X), (U::value &lt;&lt; X)&gt;</span>
<span id="cb22-37"><a href="#cb22-37" aria-hidden="true" tabindex="-1"></a>        operator&lt;&lt;(U, constexpr_v) { return {}; }</span>
<span id="cb22-38"><a href="#cb22-38" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-39"><a href="#cb22-39" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X &gt;&gt; U::value), (X &gt;&gt; U::value)&gt;</span>
<span id="cb22-40"><a href="#cb22-40" aria-hidden="true" tabindex="-1"></a>      operator&gt;&gt;(constexpr_v, U) { return {}; }</span>
<span id="cb22-41"><a href="#cb22-41" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-42"><a href="#cb22-42" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-43"><a href="#cb22-43" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value &gt;&gt; X), (U::value &gt;&gt; X)&gt;</span>
<span id="cb22-44"><a href="#cb22-44" aria-hidden="true" tabindex="-1"></a>        operator&gt;&gt;(U, constexpr_v) { return {}; }</span>
<span id="cb22-45"><a href="#cb22-45" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-46"><a href="#cb22-46" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X * U::value), (X * U::value)&gt;</span>
<span id="cb22-47"><a href="#cb22-47" aria-hidden="true" tabindex="-1"></a>      operator*(constexpr_v, U) { return {}; }</span>
<span id="cb22-48"><a href="#cb22-48" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-49"><a href="#cb22-49" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-50"><a href="#cb22-50" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value * X), (U::value * X)&gt;</span>
<span id="cb22-51"><a href="#cb22-51" aria-hidden="true" tabindex="-1"></a>        operator*(U, constexpr_v) { return {}; }</span>
<span id="cb22-52"><a href="#cb22-52" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-53"><a href="#cb22-53" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X / U::value), (X / U::value)&gt;</span>
<span id="cb22-54"><a href="#cb22-54" aria-hidden="true" tabindex="-1"></a>      operator/(constexpr_v, U) { return {}; }</span>
<span id="cb22-55"><a href="#cb22-55" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-56"><a href="#cb22-56" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-57"><a href="#cb22-57" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value / X), (U::value / X)&gt;</span>
<span id="cb22-58"><a href="#cb22-58" aria-hidden="true" tabindex="-1"></a>        operator/(U, constexpr_v) { return {}; }</span>
<span id="cb22-59"><a href="#cb22-59" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-60"><a href="#cb22-60" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X % U::value), (X % U::value)&gt;</span>
<span id="cb22-61"><a href="#cb22-61" aria-hidden="true" tabindex="-1"></a>      operator%(constexpr_v, U) { return {}; }</span>
<span id="cb22-62"><a href="#cb22-62" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-63"><a href="#cb22-63" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-64"><a href="#cb22-64" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value % X), (U::value % X)&gt;</span>
<span id="cb22-65"><a href="#cb22-65" aria-hidden="true" tabindex="-1"></a>        operator%(U, constexpr_v) { return {}; }</span>
<span id="cb22-66"><a href="#cb22-66" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-67"><a href="#cb22-67" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X + U::value), (X + U::value)&gt;</span>
<span id="cb22-68"><a href="#cb22-68" aria-hidden="true" tabindex="-1"></a>      operator+(constexpr_v, U) { return {}; }</span>
<span id="cb22-69"><a href="#cb22-69" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-70"><a href="#cb22-70" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-71"><a href="#cb22-71" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value + X), (U::value + X)&gt;</span>
<span id="cb22-72"><a href="#cb22-72" aria-hidden="true" tabindex="-1"></a>        operator+(U, constexpr_v) { return {}; }</span>
<span id="cb22-73"><a href="#cb22-73" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-74"><a href="#cb22-74" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X - U::value), (X - U::value)&gt;</span>
<span id="cb22-75"><a href="#cb22-75" aria-hidden="true" tabindex="-1"></a>      operator-(constexpr_v, U) { return {}; }</span>
<span id="cb22-76"><a href="#cb22-76" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-77"><a href="#cb22-77" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-78"><a href="#cb22-78" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value - X), (U::value - X)&gt;</span>
<span id="cb22-79"><a href="#cb22-79" aria-hidden="true" tabindex="-1"></a>        operator-(U, constexpr_v) { return {}; }</span>
<span id="cb22-80"><a href="#cb22-80" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-81"><a href="#cb22-81" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-82"><a href="#cb22-82" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X &lt; U::value), (X &lt; U::value)&gt;</span>
<span id="cb22-83"><a href="#cb22-83" aria-hidden="true" tabindex="-1"></a>      operator&lt;(constexpr_v, U) { return {}; }</span>
<span id="cb22-84"><a href="#cb22-84" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-85"><a href="#cb22-85" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-86"><a href="#cb22-86" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value &lt; X), (U::value &lt; X)&gt;</span>
<span id="cb22-87"><a href="#cb22-87" aria-hidden="true" tabindex="-1"></a>        operator&lt;(U, constexpr_v) { return {}; }</span>
<span id="cb22-88"><a href="#cb22-88" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-89"><a href="#cb22-89" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X &gt; U::value), (X &gt; U::value)&gt;</span>
<span id="cb22-90"><a href="#cb22-90" aria-hidden="true" tabindex="-1"></a>      operator&gt;(constexpr_v, U) { return {}; }</span>
<span id="cb22-91"><a href="#cb22-91" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-92"><a href="#cb22-92" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-93"><a href="#cb22-93" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value &gt; X), (U::value &gt; X)&gt;</span>
<span id="cb22-94"><a href="#cb22-94" aria-hidden="true" tabindex="-1"></a>        operator&gt;(U, constexpr_v) { return {}; }</span>
<span id="cb22-95"><a href="#cb22-95" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-96"><a href="#cb22-96" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X &lt;= U::value), (X &lt;= U::value)&gt;</span>
<span id="cb22-97"><a href="#cb22-97" aria-hidden="true" tabindex="-1"></a>      operator&lt;=(constexpr_v, U) { return {}; }</span>
<span id="cb22-98"><a href="#cb22-98" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-99"><a href="#cb22-99" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-100"><a href="#cb22-100" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value &lt;= X), (U::value &lt;= X)&gt;</span>
<span id="cb22-101"><a href="#cb22-101" aria-hidden="true" tabindex="-1"></a>        operator&lt;=(U, constexpr_v) { return {}; }</span>
<span id="cb22-102"><a href="#cb22-102" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-103"><a href="#cb22-103" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X &gt;= U::value), (X &gt;= U::value)&gt;</span>
<span id="cb22-104"><a href="#cb22-104" aria-hidden="true" tabindex="-1"></a>      operator&gt;=(constexpr_v, U) { return {}; }</span>
<span id="cb22-105"><a href="#cb22-105" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-106"><a href="#cb22-106" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-107"><a href="#cb22-107" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value &gt;= X), (U::value &gt;= X)&gt;</span>
<span id="cb22-108"><a href="#cb22-108" aria-hidden="true" tabindex="-1"></a>        operator&gt;=(U, constexpr_v) { return {}; }</span>
<span id="cb22-109"><a href="#cb22-109" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-110"><a href="#cb22-110" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X == U::value), (X == U::value)&gt;</span>
<span id="cb22-111"><a href="#cb22-111" aria-hidden="true" tabindex="-1"></a>      operator==(constexpr_v, U) { return {}; }</span>
<span id="cb22-112"><a href="#cb22-112" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-113"><a href="#cb22-113" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-114"><a href="#cb22-114" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value == X), (U::value == X)&gt;</span>
<span id="cb22-115"><a href="#cb22-115" aria-hidden="true" tabindex="-1"></a>        operator==(U, constexpr_v) { return {}; }</span>
<span id="cb22-116"><a href="#cb22-116" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-117"><a href="#cb22-117" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X != U::value), (X != U::value)&gt;</span>
<span id="cb22-118"><a href="#cb22-118" aria-hidden="true" tabindex="-1"></a>      operator!=(constexpr_v, U) { return {}; }</span>
<span id="cb22-119"><a href="#cb22-119" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-120"><a href="#cb22-120" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-121"><a href="#cb22-121" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value != X), (U::value != X)&gt;</span>
<span id="cb22-122"><a href="#cb22-122" aria-hidden="true" tabindex="-1"></a>        operator!=(U, constexpr_v) { return {}; }</span>
<span id="cb22-123"><a href="#cb22-123" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-124"><a href="#cb22-124" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X &lt;=&gt; U::value), (X &lt;=&gt; U::value)&gt;</span>
<span id="cb22-125"><a href="#cb22-125" aria-hidden="true" tabindex="-1"></a>      operator&lt;=&gt;(constexpr_v, U) { return {}; }</span>
<span id="cb22-126"><a href="#cb22-126" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-127"><a href="#cb22-127" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-128"><a href="#cb22-128" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value &lt;=&gt; X), (U::value &lt;=&gt; X)&gt;</span>
<span id="cb22-129"><a href="#cb22-129" aria-hidden="true" tabindex="-1"></a>        operator&lt;=&gt;(U, constexpr_v) { return {}; }</span>
<span id="cb22-130"><a href="#cb22-130" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-131"><a href="#cb22-131" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-132"><a href="#cb22-132" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X &amp;&amp; U::value), (X &amp;&amp; U::value)&gt;</span>
<span id="cb22-133"><a href="#cb22-133" aria-hidden="true" tabindex="-1"></a>      operator&amp;&amp;(constexpr_v, U) { return {}; }</span>
<span id="cb22-134"><a href="#cb22-134" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-135"><a href="#cb22-135" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-136"><a href="#cb22-136" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value &amp;&amp; X), (U::value &amp;&amp; X)&gt;</span>
<span id="cb22-137"><a href="#cb22-137" aria-hidden="true" tabindex="-1"></a>        operator&amp;&amp;(U, constexpr_v) { return {}; }</span>
<span id="cb22-138"><a href="#cb22-138" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-139"><a href="#cb22-139" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X || U::value), (X || U::value)&gt;</span>
<span id="cb22-140"><a href="#cb22-140" aria-hidden="true" tabindex="-1"></a>      operator||(constexpr_v, U) { return {}; }</span>
<span id="cb22-141"><a href="#cb22-141" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-142"><a href="#cb22-142" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-143"><a href="#cb22-143" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value || X), (U::value || X)&gt;</span>
<span id="cb22-144"><a href="#cb22-144" aria-hidden="true" tabindex="-1"></a>        operator||(U, constexpr_v) { return {}; }</span>
<span id="cb22-145"><a href="#cb22-145" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-146"><a href="#cb22-146" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X &amp; U::value), (X &amp; U::value)&gt;</span>
<span id="cb22-147"><a href="#cb22-147" aria-hidden="true" tabindex="-1"></a>      operator&amp;(constexpr_v, U) { return {}; }</span>
<span id="cb22-148"><a href="#cb22-148" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-149"><a href="#cb22-149" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-150"><a href="#cb22-150" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value &amp; X), (U::value &amp; X)&gt;</span>
<span id="cb22-151"><a href="#cb22-151" aria-hidden="true" tabindex="-1"></a>        operator&amp;(U, constexpr_v) { return {}; }</span>
<span id="cb22-152"><a href="#cb22-152" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-153"><a href="#cb22-153" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X | U::value), (X | U::value)&gt;</span>
<span id="cb22-154"><a href="#cb22-154" aria-hidden="true" tabindex="-1"></a>      operator|(constexpr_v, U) { return {}; }</span>
<span id="cb22-155"><a href="#cb22-155" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-156"><a href="#cb22-156" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-157"><a href="#cb22-157" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value | X), (U::value | X)&gt;</span>
<span id="cb22-158"><a href="#cb22-158" aria-hidden="true" tabindex="-1"></a>        operator|(U, constexpr_v) { return {}; }</span>
<span id="cb22-159"><a href="#cb22-159" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-160"><a href="#cb22-160" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X ^ U::value), (X ^ U::value)&gt;</span>
<span id="cb22-161"><a href="#cb22-161" aria-hidden="true" tabindex="-1"></a>      operator^(constexpr_v, U) { return {}; }</span>
<span id="cb22-162"><a href="#cb22-162" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-163"><a href="#cb22-163" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-164"><a href="#cb22-164" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value ^ X), (U::value ^ X)&gt;</span>
<span id="cb22-165"><a href="#cb22-165" aria-hidden="true" tabindex="-1"></a>        operator^(U, constexpr_v) { return {}; }</span>
<span id="cb22-166"><a href="#cb22-166" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-167"><a href="#cb22-167" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-168"><a href="#cb22-168" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X , U::value), (X , U::value)&gt;</span>
<span id="cb22-169"><a href="#cb22-169" aria-hidden="true" tabindex="-1"></a>      operator,(constexpr_v, U) { return {}; }</span>
<span id="cb22-170"><a href="#cb22-170" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-171"><a href="#cb22-171" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-172"><a href="#cb22-172" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value , X), (U::value , X)&gt;</span>
<span id="cb22-173"><a href="#cb22-173" aria-hidden="true" tabindex="-1"></a>        operator,(U, constexpr_v) { return {}; }</span>
<span id="cb22-174"><a href="#cb22-174" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-175"><a href="#cb22-175" aria-hidden="true" tabindex="-1"></a>    friend constexpr constexpr_v&lt;decltype(X -&gt;* U::value), (X -&gt;* U::value)&gt;</span>
<span id="cb22-176"><a href="#cb22-176" aria-hidden="true" tabindex="-1"></a>      operator-&gt;*(constexpr_v, U) { return {}; }</span>
<span id="cb22-177"><a href="#cb22-177" aria-hidden="true" tabindex="-1"></a>  template&lt;class U&gt;</span>
<span id="cb22-178"><a href="#cb22-178" aria-hidden="true" tabindex="-1"></a>    requires <em>not-constexpr-t</em>&lt;U&gt;</span>
<span id="cb22-179"><a href="#cb22-179" aria-hidden="true" tabindex="-1"></a>      friend constexpr constexpr_v&lt;decltype(U::value -&gt;* X), (U::value -&gt;* X)&gt;</span>
<span id="cb22-180"><a href="#cb22-180" aria-hidden="true" tabindex="-1"></a>        operator-&gt;*(U, constexpr_v) { return {}; }</span>
<span id="cb22-181"><a href="#cb22-181" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-182"><a href="#cb22-182" aria-hidden="true" tabindex="-1"></a>  template&lt;class... Args&gt;</span>
<span id="cb22-183"><a href="#cb22-183" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator()(Args... args) const</span>
<span id="cb22-184"><a href="#cb22-184" aria-hidden="true" tabindex="-1"></a>      -&gt; constexpr_v&lt;decltype(X(Args::value...)), X(Args::value...)&gt;</span>
<span id="cb22-185"><a href="#cb22-185" aria-hidden="true" tabindex="-1"></a>        { return {}; }</span>
<span id="cb22-186"><a href="#cb22-186" aria-hidden="true" tabindex="-1"></a>  template&lt;class... Args&gt;</span>
<span id="cb22-187"><a href="#cb22-187" aria-hidden="true" tabindex="-1"></a>    constexpr auto operator()(Args... args) const</span>
<span id="cb22-188"><a href="#cb22-188" aria-hidden="true" tabindex="-1"></a>      -&gt; constexpr_v&lt;decltype(X[Args::value...]), X[Args::value...]&gt;</span>
<span id="cb22-189"><a href="#cb22-189" aria-hidden="true" tabindex="-1"></a>        { return {}; }</span>
<span id="cb22-190"><a href="#cb22-190" aria-hidden="true" tabindex="-1"></a>};</span>
<span id="cb22-191"><a href="#cb22-191" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-192"><a href="#cb22-192" aria-hidden="true" tabindex="-1"></a>template&lt;auto X&gt;</span>
<span id="cb22-193"><a href="#cb22-193" aria-hidden="true" tabindex="-1"></a>  inline constexpr constexpr_v&lt;remove_const_t&lt;decltype(X)&gt;, X&gt; c_{};</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
The class template <code class="sourceCode default">constexpr_v</code>
aids in metaprogramming by ensuring that the evaluation of expressions
comprised entirely of
<code class="sourceCode default">constexpr_v</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">constexpr_v</code> values that are
passed as arguments to <code class="sourceCode default">constexpr</code>
functions to be used as template parameters.</p>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
The variable template <code class="sourceCode default">c_</code> is
provided as a convenient way to nominate
<code class="sourceCode default">constexpr_v</code> values.</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode default default"><code class="sourceCode default"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a>template&lt;typename T, typename ValueType = void&gt;</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>  concept constexpr_value = <em>see below</em>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
The <code class="sourceCode default">constexpr_value</code> concept
specifies the requirements on types that are compatible with the
operator overloads of
<code class="sourceCode default">constexpr_v</code>.
<code class="sourceCode default">constexpr_value</code> is equivalent to
<code class="sourceCode default">requires { constexpr auto x = T::value; }</code>
if <code class="sourceCode default">ValueType</code> is
<code class="sourceCode default">void</code>, and <code class="sourceCode default">requires { constexpr ValueType x = T::value; }</code>
otherwise.</p>
</div>
<p>Add to [version.syn]:</p>
<div class="add" style="color: #006e28">

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

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