<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2025-07-13" />
  <title>Why `constant_wrapper` is not a usable replacement for
`nontype`</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;

-webkit-text-size-adjust: none;
-moz-text-size-adjust: none;
text-size-adjust: none;
}
@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">Why
<code class="sourceCode cpp">constant_wrapper</code> is not a usable
replacement for <code class="sourceCode cpp">nontype</code></h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>
      P3792R0
      [<a href="https://wg21.link/P3792">Latest</a>]
      [<a href="https://wg21.link/P3792/status">Status</a>]
    </td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2025-07-13</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, LWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Bronek Kozicki<br>&lt;<a href="mailto:brok@incorrekt.com" class="email">brok@incorrekt.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="#abstract" id="toc-abstract"><span class="toc-section-number">1</span> Abstract<span></span></a></li>
<li><a href="#polls-taken" id="toc-polls-taken"><span class="toc-section-number">2</span> Polls taken<span></span></a></li>
<li><a href="#discussion" id="toc-discussion"><span class="toc-section-number">3</span> Discussion<span></span></a>
<ul>
<li><a href="#why-does-function_ref-take-a-nontype-parameter" id="toc-why-does-function_ref-take-a-nontype-parameter"><span class="toc-section-number">3.1</span> Why does
<code class="sourceCode cpp">function_ref</code> take a
<code class="sourceCode cpp">nontype</code> parameter
?<span></span></a></li>
<li><a href="#would-other-function-wrappers-benefit-from-taking-a-nontype-wrapper" id="toc-would-other-function-wrappers-benefit-from-taking-a-nontype-wrapper"><span class="toc-section-number">3.2</span> Would other function wrappers
benefit from taking a <code class="sourceCode cpp">nontype</code>
wrapper ?<span></span></a></li>
<li><a href="#is-there-a-proposal-to-add-such-constructors-to-other-function-wrappers" id="toc-is-there-a-proposal-to-add-such-constructors-to-other-function-wrappers"><span class="toc-section-number">3.3</span> Is there a proposal to add such
constructors to other function wrappers ?<span></span></a></li>
<li><a href="#whats-the-problem-with-replacing-nontype-with-constant_wrapper" id="toc-whats-the-problem-with-replacing-nontype-with-constant_wrapper"><span class="toc-section-number">3.4</span> What’s the problem with replacing
<code class="sourceCode cpp">nontype</code> with
<code class="sourceCode cpp">constant_wrapper</code>
?<span></span></a></li>
<li><a href="#it-worked-so-whats-the-problem" id="toc-it-worked-so-whats-the-problem"><span class="toc-section-number">3.5</span> It worked, so what’s the problem
?<span></span></a></li>
<li><a href="#example-user-code-breakage" id="toc-example-user-code-breakage"><span class="toc-section-number">3.6</span> Example user code
breakage<span></span></a></li>
<li><a href="#what-about-change-in-invoke-and-invoke_r" id="toc-what-about-change-in-invoke-and-invoke_r"><span class="toc-section-number">3.7</span> What about change in
<code class="sourceCode cpp">invoke</code> and
<code class="sourceCode cpp">invoke_r</code> ?<span></span></a></li>
</ul></li>
<li><a href="#summary" id="toc-summary"><span class="toc-section-number">4</span> Summary<span></span></a></li>
<li><a href="#future" id="toc-future"><span class="toc-section-number">5</span> Future<span></span></a></li>
<li><a href="#acknowledgments" id="toc-acknowledgments"><span class="toc-section-number">6</span>
Acknowledgments<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">7</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="abstract"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p>The lack of LEWG consensus during the Sofia meeting to replace
<code class="sourceCode cpp">nontype</code> with
<code class="sourceCode cpp">constant_wrapper</code> as a
<code class="sourceCode cpp">function_ref</code> construction parameter
has reportedly surprised some members of LWG. Plausibly, it might have
also surprised the wider C++ community. This paper is an attempt to
explain the process and the rationale behind the (lack of) decision for
such a change.</p>
<h1 data-number="2" id="polls-taken"><span class="header-section-number">2</span> Polls taken<a href="#polls-taken" class="self-link"></a></h1>
<p>During the discussion on <span class="citation" data-cites="P3740R1"><a href="https://isocpp.org/files/papers/P3740R1.html" role="doc-biblioref">[P3740R1]</a></span> in Sofia, LEWG took a series
of polls which ultimately led to the decision to keep
<code class="sourceCode cpp">nontype</code> parameters in
<code class="sourceCode cpp">function_ref</code> constructors and rename
it, rather than replace <code class="sourceCode cpp">nontype</code> with
<code class="sourceCode cpp">constant_wrapper</code>, while opening a
path for a possible NB comment which might request such a change.</p>
<p>First, the following three polls were taken as popularity
contest:</p>
<blockquote>
<p><strong>POLL:</strong> Forward “P3740R1: Last chance to fix
<code class="sourceCode cpp">std<span class="op">::</span>nontype</code>”
selecting Option A (change from
<code class="sourceCode cpp">nontype</code> to
<code class="sourceCode cpp">constant_wrapper</code>, also add overloads
to other function wrappers (<code class="sourceCode cpp">std<span class="op">::</span>function</code>)) to
LWG</p>
<table>
<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>0</td>
<td>4</td>
<td>0</td>
<td>7</td>
<td>8</td>
</tr>
</tbody>
</table>
<p>Outcome: No consensus for change</p>
<p><strong>POLL:</strong> Forward “P3740R1: Last chance to fix
<code class="sourceCode cpp">std<span class="op">::</span>nontype</code>”
selecting Option A (change from
<code class="sourceCode cpp">nontype</code> to
<code class="sourceCode cpp">constant_wrapper</code>, DO NOT add
overloads to other function wrappers (<code class="sourceCode cpp">std<span class="op">::</span>function</code>)) to
LWG</p>
<table>
<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>6</td>
<td>7</td>
<td>2</td>
<td>6</td>
<td>0</td>
</tr>
</tbody>
</table>
<p>Outcome: Weak consensus in favor</p>
<p><strong>POLL:</strong> Forward “P3740R1: Last chance to fix
<code class="sourceCode cpp">std<span class="op">::</span>nontype</code>”
selecting Option B (rename
<code class="sourceCode cpp">std<span class="op">::</span>nontype</code>
to <code class="sourceCode cpp">std<span class="op">::</span>constant_arg</code>)
to LWG</p>
<table>
<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>7</td>
<td>9</td>
<td>2</td>
<td>2</td>
<td>1</td>
</tr>
</tbody>
</table>
<p>Outcome: Consensus in favour</p>
</blockquote>
<p>As a result of the popularity contest, the Option B was assumed to
have become the “status quo”, and the two options with (some) consensus
have been pitted against each other in the final poll:</p>
<blockquote>
<p><strong>POLL:</strong> Forward “P3740R1: Last chance to fix
<code class="sourceCode cpp">std<span class="op">::</span>nontype</code>”
selecting Option A (change from
<code class="sourceCode cpp">nontype</code> to
<code class="sourceCode cpp">constant_wrapper</code>, DO NOT add
overloads to other function wrappers (<code class="sourceCode cpp">std<span class="op">::</span>function</code>))
instead of Option B (rename
<code class="sourceCode cpp">std<span class="op">::</span>nontype</code>
to <code class="sourceCode cpp">std<span class="op">::</span>constant_arg</code>)
to LWG</p>
<table>
<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>9</td>
<td>4</td>
<td>2</td>
<td>4</td>
<td>4</td>
</tr>
</tbody>
</table>
<p>Outcome: No consensus for change.</p>
</blockquote>
<p>The final notes from the meeting do recognize that Option B has
received fewer votes than the limited Option A:</p>
<blockquote>
<p>The second poll had no consensus, but got more votes toward the more
extensive change (remove <code class="sourceCode cpp">nontype</code> and
replace with <code class="sourceCode cpp">constant_wrapper</code> in
<code class="sourceCode cpp">funtion_ref</code> only). This will need to
be discussed again if an NB comment is submitted for C++26.</p>
</blockquote>
<h1 data-number="3" id="discussion"><span class="header-section-number">3</span> Discussion<a href="#discussion" class="self-link"></a></h1>
<p>During the discussion leading to the polls, I have argued strongly
against replacing <code class="sourceCode cpp">nontype</code> with
<code class="sourceCode cpp">constant_wrapper</code> as a parameter for
<code class="sourceCode cpp">function_ref</code> construtors, instead
arguing for renaming <code class="sourceCode cpp">nontype</code> to
something that better reflects its use as a
<code class="sourceCode cpp">function_ref</code> construction parameter
(which is the only use of <code class="sourceCode cpp">nontype</code> in
the standard).</p>
<p>This was informed by my implementation experience <span class="citation" data-cites="implementation"><a href="https://github.com/zhihaoy/nontype_functional/pull/13" role="doc-biblioref">[zhihaoy/nontype_functional/pull/13]</a></span>
replacing <code class="sourceCode cpp">nontype</code> with
<code class="sourceCode cpp">constant_wrapper</code> in reference
implementations of <code class="sourceCode cpp">function_ref</code>,
<code class="sourceCode cpp">move_only_function</code> and
<code class="sourceCode cpp">function</code>. The problem was not
related to the implementation (that was the easy part). It was the
result of a discovery of inconsistencies in the standard, which would
potentially lead the users to write error-prone C++ code, had such
change been made.</p>
<h2 data-number="3.1" id="why-does-function_ref-take-a-nontype-parameter"><span class="header-section-number">3.1</span> Why does
<code class="sourceCode cpp">function_ref</code> take a
<code class="sourceCode cpp">nontype</code> parameter ?<a href="#why-does-function_ref-take-a-nontype-parameter" class="self-link"></a></h2>
<p>The details can be found in <span class="citation" data-cites="P2472R3"><a href="https://wg21.link/p2472r3" role="doc-biblioref">[P2472R3]</a></span>, but the short version is that
it provides <code class="sourceCode cpp">function_ref</code> with a
type-erasing constructor from a member function or a free function. The
mechanics of this constructor is simple:</p>
<ul>
<li>initialize the exposition-only
<code class="sourceCode cpp">thunk<span class="op">-</span>ptr</code>
with the address of a function which wraps the
<code class="sourceCode cpp">invoke_r</code> call taking the value
template parameter of <code class="sourceCode cpp">nontype</code> as a
first parameter, and optionally second parameter to be dereferenced from
<code class="sourceCode cpp">bound<span class="op">-</span>entity</code></li>
<li>initialize the exposition-only
<code class="sourceCode cpp">bound<span class="op">-</span>entity</code>
with the optional second constructor parameter (if it is a pointer) or
its address (if it is a reference)</li>
</ul>
<p>This allows the <code class="sourceCode cpp">function_ref</code> to,
for example, wrap a pointer to a member function <em>and</em> the object
reference to call it with.</p>
<h2 data-number="3.2" id="would-other-function-wrappers-benefit-from-taking-a-nontype-wrapper"><span class="header-section-number">3.2</span> Would other function wrappers
benefit from taking a <code class="sourceCode cpp">nontype</code>
wrapper ?<a href="#would-other-function-wrappers-benefit-from-taking-a-nontype-wrapper" class="self-link"></a></h2>
<p>Potentially. In particular
<code class="sourceCode cpp">move_only_function</code> and
<code class="sourceCode cpp">copyable_function</code>, which both apply
small size optimization, might be able to use space more efficiently, if
they performed type-erasure from a
<code class="sourceCode cpp">nontype</code> wrapper (similarly like
<code class="sourceCode cpp">function_ref</code> does) when
instantiating the wrapper to call target.</p>
<p>However, a similar optimization opportunity can be also created
without the use of <code class="sourceCode cpp">nontype</code>. A
function wrapper might recognize that an invocable passed to its
constructor is stateless (e.g. by application of
<code class="sourceCode cpp">is_empty</code> and
<code class="sourceCode cpp">is_trivially_relocatable</code> traits) and
then simply do not waste space trying to store such non-state.</p>
<h2 data-number="3.3" id="is-there-a-proposal-to-add-such-constructors-to-other-function-wrappers"><span class="header-section-number">3.3</span> Is there a proposal to add such
constructors to other function wrappers ?<a href="#is-there-a-proposal-to-add-such-constructors-to-other-function-wrappers" class="self-link"></a></h2>
<p>Initial work has been done by Zhihao Yuan and (separately) by Tomasz
Kamiński.</p>
<h2 data-number="3.4" id="whats-the-problem-with-replacing-nontype-with-constant_wrapper"><span class="header-section-number">3.4</span> What’s the problem with
replacing <code class="sourceCode cpp">nontype</code> with
<code class="sourceCode cpp">constant_wrapper</code> ?<a href="#whats-the-problem-with-replacing-nontype-with-constant_wrapper" class="self-link"></a></h2>
<p>In short, <code class="sourceCode cpp">constant_wrapper</code> has
its own <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code>,
with its own semantics which might, or might not, be compatible with an
arbitrary invocable used to instantiate it.</p>
<p>More specifically, <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code>
in <code class="sourceCode cpp">constant_wrapper</code> is defined in
<span class="citation" data-cites="P2781R8"><a href="https://wg21.link/p2781r8" role="doc-biblioref">[P2781R8]</a></span> as:</p>
<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="kw">template</span><span class="op">&lt;</span><span class="kw">constexpr</span><span class="op">-</span>param T, <span class="kw">constexpr</span><span class="op">-</span>param<span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">()(</span><span class="kw">this</span> T, Args<span class="op">...)</span> <span class="kw">noexcept</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span>Args<span class="op">...)</span> <span class="op">{</span> constant_wrapper<span class="op">&lt;</span>T<span class="op">::</span>value<span class="op">(</span>Args<span class="op">::</span>value<span class="op">...)&gt;()</span>; <span class="op">}</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span> <span class="cf">return</span> constant_wrapper<span class="op">&lt;</span>T<span class="op">::</span>value<span class="op">(</span>Args<span class="op">::</span>value<span class="op">...)&gt;{}</span>; <span class="op">}</span></span></code></pre></div>
<p>Please note that the return type is an instance of
<code class="sourceCode cpp">constant_wrapper</code>, which will fail
compilation if the return type returned from the invocation <code class="sourceCode cpp">T<span class="op">::</span>value<span class="op">(</span>Args<span class="op">::</span>value<span class="op">...)</span></code>
is <em>not</em> a structural type. Also, the call parameters are all
expected to have <code class="sourceCode cpp">value</code> static data
member, which is extracted inside the call. There is nothing wrong with
this, because the design goal of
<code class="sourceCode cpp">constant_wrapper</code> is to provide C++
users with a <em>more useful</em> compile-time constant (compared to
<code class="sourceCode cpp">integral_constant</code>). However it also
means that an invocable returning an <em>arbitrary</em> (including
non-structural) type <em>cannot</em> be used with <code class="sourceCode cpp">constant_wrapper<span class="op">::</span><span class="kw">operator</span><span class="op">()</span></code>.
This is by design, and (in my humble opinion) it’s <em>good</em>.</p>
<p>When trying to use
<code class="sourceCode cpp">constant_wrapper</code> in place of
<code class="sourceCode cpp">nontype</code>, the workaround for this
limitation is obvious: do not try to invoke the
<code class="sourceCode cpp">constant_wrapper</code>, just unwrap its
template parameter using <code class="sourceCode cpp">value</code>
static data member. This is what I did and it worked.</p>
<h2 data-number="3.5" id="it-worked-so-whats-the-problem"><span class="header-section-number">3.5</span> It worked, so what’s the
problem ?<a href="#it-worked-so-whats-the-problem" class="self-link"></a></h2>
<p>Currently no other function wrapper has this functionality. However,
the C++26 status quo is that
<code class="sourceCode cpp">constant_wrapper</code>, instantiated with
a value of a compatible type, is also an invocable, and it can be used
to construct any function wrapper (with matching template parameters).
The behaviour and semantics of such function wrapper will be different
compared to a <code class="sourceCode cpp">function_ref</code>
constructed with <code class="sourceCode cpp">constant_wrapper</code>,
because of the semantics of <code class="sourceCode cpp">constant_wrapper<span class="op">::</span><span class="kw">operator</span><span class="op">()</span></code>.
This difference will be most stark if the invocable used to instantiate
<code class="sourceCode cpp">constant_wrapper</code> is a functor user
type with overloaded function call operators, or with a templated
function call operator (as a niebloid might be). In short, it is not
safe to <em>just</em> substitute
<code class="sourceCode cpp">nontype</code> with a
<code class="sourceCode cpp">constant_wrapper</code>.</p>
<p>This means that:</p>
<ul>
<li>if <code class="sourceCode cpp">nontype</code> was replaced by
<code class="sourceCode cpp">constant_wrapper</code> as a construction
parameter to <code class="sourceCode cpp">function_ref</code>
<em>and</em></li>
<li>a user performed a (seemingly) simple refactoring by swapping a
standard function wrapper with another standard function wrapper
(e.g. to benefit from the low cost of
<code class="sourceCode cpp">function_ref</code> or to use the data
storage in other wrappers) where the constructor happens to rely on
<code class="sourceCode cpp">constant_wrapper</code></li>
</ul>
<p>… any of the following might happen:</p>
<ul>
<li>the program will continue to work as designed</li>
<li>the program will fail to compile</li>
<li>the program will continue to compile and “work”, but with subtly
changed behaviour</li>
</ul>
<p>In order to prevent the last two happening, we would have to do some
of the following:</p>
<ul>
<li>revisit <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code>
in <code class="sourceCode cpp">constant_wrapper</code> i.e. <span class="citation" data-cites="P2781R8"><a href="https://wg21.link/p2781r8" role="doc-biblioref">[P2781R8]</a></span></li>
<li>revisit <code class="sourceCode cpp">nontype</code> parameter in
<code class="sourceCode cpp">function_ref</code> i.e. <span class="citation" data-cites="P2472R3"><a href="https://wg21.link/p2472r3" role="doc-biblioref">[P2472R3]</a></span> and <span class="citation" data-cites="P0792R14"><a href="https://wg21.link/p0792r14" role="doc-biblioref">[P0792R14]</a></span></li>
<li>add similar overloads to other functional wrappers (see first poll
taken)</li>
<li>define specialization of <code class="sourceCode cpp">invoke</code>
and <code class="sourceCode cpp">invoke_r</code> for
<code class="sourceCode cpp">constant_wrapper</code> to use the
extracted <code class="sourceCode cpp">value</code> rather than call
<code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code>
directly</li>
</ul>
<h2 data-number="3.6" id="example-user-code-breakage"><span class="header-section-number">3.6</span> Example user code breakage<a href="#example-user-code-breakage" class="self-link"></a></h2>
<p>In the following code excerpt,
<code class="sourceCode cpp">foo_t</code> is a niebloid providing two
different overloads of <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code>,
selected by means of a
<code class="sourceCode cpp"><span class="kw">requires</span></code>
clause.</p>
<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">static</span> <span class="kw">constexpr</span> <span class="kw">struct</span> foo_t <span class="kw">final</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" 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">auto</span> <span class="op">&amp;&amp;...</span>args<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">int</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span><span class="op">(</span>std<span class="op">::</span>integral<span class="op">&lt;</span>std<span class="op">::</span>remove_cvref_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>args<span class="op">)&gt;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">(</span><span class="dv">0</span> <span class="op">+</span> <span class="op">...</span> <span class="op">+</span> args<span class="op">)</span>;</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-9"><a href="#cb2-9" 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">auto</span> <span class="op">&amp;&amp;...</span>args<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> <span class="dt">int</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span><span class="op">(</span>std<span class="op">::</span>integral<span class="op">&lt;</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>                     <span class="kw">decltype</span><span class="op">(</span>std<span class="op">::</span>remove_cvref_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>args<span class="op">)&gt;::</span>value<span class="op">)&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>                 <span class="op">...)</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">sizeof</span><span class="op">...(</span>args<span class="op">)</span>;</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> foo <span class="op">=</span> <span class="op">{}</span>;</span></code></pre></div>
<p>The second overload matches types providing a
<code class="sourceCode cpp">value</code> static data member, just like
<code class="sourceCode cpp">constant_wrapper</code> or a
<code class="sourceCode cpp">baz_t</code> type presented below:</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">static</span> <span class="kw">constexpr</span> <span class="kw">struct</span> baz_t <span class="kw">final</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">int</span> value <span class="op">=</span> <span class="dv">42</span>;</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> baz <span class="op">=</span> <span class="op">{}</span>;</span></code></pre></div>
<p>The <code class="sourceCode cpp">foo</code> object is used to
instantiate a <code class="sourceCode cpp">cw<span class="op">&lt;</span>foo<span class="op">&gt;</span></code>,
from which a <code class="sourceCode cpp">move_only_function<span class="op">&lt;</span><span class="dt">int</span><span class="op">(</span>baz_t<span class="op">)&gt;</span> fn</code>
is constructed. This works because (by design) <code class="sourceCode cpp">constant_wraper<span class="op">::</span><span class="kw">operator</span><span class="op">()</span></code>
will accept any parameter type with a
<code class="sourceCode cpp">value</code> static data member, including
<code class="sourceCode cpp">baz_t</code> presented above.</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">auto</span> main<span class="op">()</span> <span class="op">-&gt;</span> <span class="dt">int</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    move_only_function<span class="op">&lt;</span><span class="dt">int</span><span class="op">(</span>baz_t<span class="op">)&gt;</span> fn<span class="op">(</span>cw<span class="op">&lt;</span>foo<span class="op">&gt;)</span>;</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="ot">assert</span><span class="op">(</span>fn<span class="op">(</span>baz<span class="op">)</span> <span class="op">==</span> <span class="dv">42</span><span class="op">)</span>;</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The
<code class="sourceCode cpp"><span class="ot">assert</span></code> will
succeed if the top overloaded <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code>
in <code class="sourceCode cpp">foo_t</code> is selected. This is
guaranteed by <code class="sourceCode cpp">constant_wrapper<span class="op">::</span><span class="kw">operator</span><span class="op">()</span></code>,
which unwraps <code class="sourceCode cpp">value</code> from
<code class="sourceCode cpp">baz_t</code>, <em>before</em> submitting
the result to <code class="sourceCode cpp">foo<span class="op">(</span><span class="dt">int</span><span class="op">)</span></code>.</p>
<p>If the user were to switch their code from
<code class="sourceCode cpp">move_only_function</code> to
<code class="sourceCode cpp">function_ref</code>, taking
<code class="sourceCode cpp">constant_wrapper</code> as a constructor
parameter (in place of the current
<code class="sourceCode cpp">nontype</code>), then the constructor will
unwrap <code class="sourceCode cpp">value</code> (that is,
<code class="sourceCode cpp">foo</code> object) from <code class="sourceCode cpp">cw<span class="op">&lt;</span>foo<span class="op">&gt;</span></code>
and invoke <code class="sourceCode cpp">foo<span class="op">(</span>baz_t<span class="op">)</span></code>
(rather than call <code class="sourceCode cpp">constant_wrapper<span class="op">::</span><span class="kw">operator</span><span class="op">()</span></code>).
As a result, the second overload of <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code>
in <code class="sourceCode cpp">foo_t</code> will be selected, and the
assert will fail:</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">auto</span> main<span class="op">()</span> <span class="op">-&gt;</span> <span class="dt">int</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    function_ref<span class="op">&lt;</span><span class="dt">int</span><span class="op">(</span>baz_t<span class="op">)&gt;</span> fn<span class="op">(</span>cw<span class="op">&lt;</span>foo<span class="op">&gt;)</span>;</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="ot">assert</span><span class="op">(</span>fn<span class="op">(</span>baz<span class="op">)</span> <span class="op">==</span> <span class="dv">42</span><span class="op">)</span>; <span class="co">// assertion failure</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This demonstration is available on github <span class="citation" data-cites="github"><a href="https://github.com/Bronek/nontype_functional/pull/1" role="doc-biblioref">[Bronek/nontype_functional/pull/1]</a></span>.</p>
<h2 data-number="3.7" id="what-about-change-in-invoke-and-invoke_r"><span class="header-section-number">3.7</span> What about change in
<code class="sourceCode cpp">invoke</code> and
<code class="sourceCode cpp">invoke_r</code> ?<a href="#what-about-change-in-invoke-and-invoke_r" class="self-link"></a></h2>
<p>The last option suggested above, which nobody is proposing and which
(in my opinion) is <em>not</em> sensible, would “fix” the problem,
preventing breakage when the user code is switched from one standard
function wrapper to another (when the constructor call relies on on
<code class="sourceCode cpp">constant_wrapper</code> parameter), at the
cost of imbuing the <code class="sourceCode cpp">constant_wrapper</code>
with <em>dual</em> invocation semantics:</p>
<ul>
<li>direct call defined in <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code>,
as stated in <span class="citation" data-cites="P2781R8"><a href="https://wg21.link/p2781r8" role="doc-biblioref">[P2781R8]</a></span> <em>and</em></li>
<li>call into the value template parameter, via
<code class="sourceCode cpp">value</code> static data member, with
<code class="sourceCode cpp">invoke</code> and
<code class="sourceCode cpp">invoke_r</code></li>
</ul>
<p>These dual semantics mean that we have moved the problem from one
place to another. A user would not expect that a change in their code
from <code class="sourceCode cpp">invoke</code> (or
<code class="sourceCode cpp">invoke_r</code>) to function call syntax,
might make the program fail to compile or worse, change its
behaviour.</p>
<p>This is just making things worse.</p>
<h1 data-number="4" id="summary"><span class="header-section-number">4</span> Summary<a href="#summary" class="self-link"></a></h1>
<p>LEWG did the right thing in Sofia by not replacing
<code class="sourceCode cpp">nontype</code> constructor parameters in
<code class="sourceCode cpp">function_ref</code> with
<code class="sourceCode cpp">constant_wrapper</code>. Had this been
done, we would have to either revisit several other design decision
taken previously or risk users’ code breaking (sometimes subtly) when
they move between different standard function wrappers. Even if we
changed the other function wrappers to do what
<code class="sourceCode cpp">function_ref</code> does (a design choice
rejected by LEWG) then the inconsistency would remain, it would just
move elsewhere.</p>
<h1 data-number="5" id="future"><span class="header-section-number">5</span> Future<a href="#future" class="self-link"></a></h1>
<p>I suggest we should pursue the following:</p>
<ul>
<li>Rename <code class="sourceCode cpp">nontype</code> to better reflect
its current use in <code class="sourceCode cpp">function_ref</code>
constructor. This <em>has</em> to be done in C++26 (possibly via NB
comment) and is discussed in <span class="citation" data-cites="P3774R0"><a href="https://isocpp.org/files/papers/P3774R0.html" role="doc-biblioref">[P3774R0]</a></span>.</li>
<li>Extend such newly named type with function call semantics that does
not break user expectations, while preserving its lack of state. This is
also discussed in <span class="citation" data-cites="P3774R0"><a href="https://isocpp.org/files/papers/P3774R0.html" role="doc-biblioref">[P3774R0]</a></span>.</li>
<li>Consider optimizing other function wrappers for such a stateless
constructor parameter, possibly as QoI.</li>
</ul>
<h1 data-number="6" id="acknowledgments"><span class="header-section-number">6</span> Acknowledgments<a href="#acknowledgments" class="self-link"></a></h1>
<p>I am grateful to Jan Schultke, Tomasz Kamiński and Gašper Ažman for
their kind comments and suggestions. Also big thank you to Zhihao Yuan
and Zach Laine for their reference implementations of function wrappers
and <code class="sourceCode cpp">constant_wrapper</code>, used when
writing this paper.</p>
<h1 data-number="7" id="bibliography"><span class="header-section-number">7</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="1" role="doc-bibliography">
<div id="ref-github" class="csl-entry" role="doc-biblioentry">
[Bronek/nontype_functional/pull/1] Bronek Kozicki. Breakage
demonstration. <a href="https://github.com/Bronek/nontype_functional/pull/1"><div class="csl-block">https://github.com/Bronek/nontype_functional/pull/1</div></a>
</div>
<div id="ref-P0792R14" class="csl-entry" role="doc-biblioentry">
[P0792R14] Vittorio Romeo, Zhihao Yuan, Jarrad Waterloo. 2023-02-09.
function_ref: a non-owning reference to a Callable. <a href="https://wg21.link/p0792r14"><div class="csl-block">https://wg21.link/p0792r14</div></a>
</div>
<div id="ref-P2472R3" class="csl-entry" role="doc-biblioentry">
[P2472R3] Jarrad J. Waterloo, Zhihao Yuan. 2022-05-13. make function_ref
more functional. <a href="https://wg21.link/p2472r3"><div class="csl-block">https://wg21.link/p2472r3</div></a>
</div>
<div id="ref-P2781R8" class="csl-entry" role="doc-biblioentry">
[P2781R8] Zach Laine, Matthias Kretz, Hana Dusíková. 2025-03-16.
std::constexpr_wrapper. <a href="https://wg21.link/p2781r8"><div class="csl-block">https://wg21.link/p2781r8</div></a>
</div>
<div id="ref-P3740R1" class="csl-entry" role="doc-biblioentry">
[P3740R1] Jan Schultke. Last chance to fix std::nontype. <a href="https://isocpp.org/files/papers/P3740R1.html"><div class="csl-block">https://isocpp.org/files/papers/P3740R1.html</div></a>
</div>
<div id="ref-P3774R0" class="csl-entry" role="doc-biblioentry">
[P3774R0] Jan Schultke. Rename std::nontype, and make it broadly useful.
<a href="https://isocpp.org/files/papers/P3774R0.html"><div class="csl-block">https://isocpp.org/files/papers/P3774R0.html</div></a>
</div>
<div id="ref-implementation" class="csl-entry" role="doc-biblioentry">
[zhihaoy/nontype_functional/pull/13] Bronek Kozicki. Replace nontype
with constant_wrapper as a construction parameter. <a href="https://github.com/zhihaoy/nontype_functional/pull/13"><div class="csl-block">https://github.com/zhihaoy/nontype_functional/pull/13</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
