<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2024-04-16" />
  <title>declcall(unevaluated-postfix-expression)</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">declcall(unevaluated-postfix-expression)</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2825R1</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-04-16</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      EWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Gašper Ažman<br>&lt;<a href="mailto:gasper.azman@gmail.com" class="email">gasper.azman@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#introduction" id="toc-introduction"><span class="toc-section-number">1</span> Introduction<span></span></a></li>
<li><a href="#motivation-and-prior-art" id="toc-motivation-and-prior-art"><span class="toc-section-number">2</span> Motivation and Prior
Art<span></span></a>
<ul>
<li><a href="#related-work" id="toc-related-work"><span class="toc-section-number">2.1</span> Related Work<span></span></a></li>
</ul></li>
<li><a href="#proposal" id="toc-proposal"><span class="toc-section-number">3</span> Proposal<span></span></a>
<ul>
<li><a href="#interesting-cases-in-the-above-example" id="toc-interesting-cases-in-the-above-example"><span class="toc-section-number">3.1</span> Interesting cases in the above
example<span></span></a></li>
<li><a href="#alternatives-to-syntax" id="toc-alternatives-to-syntax"><span class="toc-section-number">3.2</span> Alternatives to
syntax<span></span></a></li>
<li><a href="#naming" id="toc-naming"><span class="toc-section-number">3.3</span> Naming<span></span></a></li>
</ul></li>
<li><a href="#usecases" id="toc-usecases"><span class="toc-section-number">4</span> Usecases<span></span></a>
<ul>
<li><a href="#what-does-this-give-us-that-we-dont-have-yet" id="toc-what-does-this-give-us-that-we-dont-have-yet"><span class="toc-section-number">4.1</span> What does this give us that we
don’t have yet<span></span></a></li>
<li><a href="#thats-not-good-enough-to-do-all-that-work.-what-else" id="toc-thats-not-good-enough-to-do-all-that-work.-what-else"><span class="toc-section-number">4.2</span> That’s not good enough to do all
that work. What else?<span></span></a></li>
</ul></li>
<li><a href="#needed-guidance" id="toc-needed-guidance"><span class="toc-section-number">5</span> Needed
Guidance<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">6</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="introduction"><span class="header-section-number">1</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>This paper introduces a new compile-time expression into the
language, for the moment with the syntax
<code class="sourceCode default">declcall(<em>expression</em>)</code>.</p>
<p>The <code class="sourceCode default">declcall</code> expression is a
constant expression of the type pointer-to-function (PF) or
pointer-to-member-function (PMF). Its value is the pointer to the
function that would have been invoked if the <em>expression</em> were
evaluated. The <em>expression</em> itself is an unevaluated operand.</p>
<p>In effect, <code class="sourceCode default">declcall</code> is a hook
into the overload resolution machinery.</p>
<h1 data-number="2" id="motivation-and-prior-art"><span class="header-section-number">2</span> Motivation and Prior Art<a href="#motivation-and-prior-art" class="self-link"></a></h1>
<p>The language already has a number of sort-of overload resolution
facilities:</p>
<ul>
<li><code class="sourceCode default">static_cast</code></li>
<li>assignment to a variable of a given function pointer type</li>
<li>function calls (implicit) - the only one that actually works</li>
</ul>
<p>All of these are woefully unsuitable for type-erasure that library
authors (such as <span class="citation" data-cites="P2300R6">[<a href="#ref-P2300R6" role="doc-biblioref">P2300R6</a>]</span>) would
actually <em>like</em> to work with. Sure, we can always indirect
through a lambda:</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">typename</span> R, <span class="kw">typename</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">struct</span> my_erased_wrapper <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> fptr <span class="op">=</span> R<span class="op">(*)(</span>Args_<span class="op">...)</span>;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  fptr erased <span class="op">=</span> <span class="op">+[](</span>my_erased_wrapper<span class="op">*</span> self, <span class="kw">auto</span><span class="op">&amp;&amp;...</span> args_<span class="op">)</span> <span class="op">-&gt;</span> R <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> self<span class="op">-&gt;</span>fptr<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">&gt;(</span>args_<span class="op">)...)</span>;</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>This has several drawbacks:</p>
<ul>
<li>it introduces a whole new lambda scope
<ul>
<li>annoying for optimizers because extra inlining</li>
<li>annoying for debugging because of an extra stack frame</li>
</ul></li>
<li>a requirement to divine forward noexceptness by the user,</li>
<li>a requirement that arguments are <em>convertible</em> (but not
necessarily the same) as the ones the user specified in their infinite
wisdom,</li>
<li>a requirement that the return type is convertible (but not
necessarily the same) as the one the user specified in their infinite
wisdom,</li>
<li>the forward-through-a-reference inhibits copy-elision of
arguments</li>
<li>inability to flatten subsetting type-erased wrappers (we can’t
divine an exact match in the presence of overloads) (think “subsetting
vtables”)</li>
</ul>
<p>Oh, if only we had a facility to ask the compiler what function we’d
be calling and then <em>just have the pointer to it</em>.</p>
<p>This is what this paper is trying to provide.</p>
<h2 data-number="2.1" id="related-work"><span class="header-section-number">2.1</span> Related Work<a href="#related-work" class="self-link"></a></h2>
<h3 data-number="2.1.1" id="reflection"><span class="header-section-number">2.1.1</span> Reflection<a href="#reflection" class="self-link"></a></h3>
<p>The reflection proposal does not include anything like this. It knows
how to reflect on constants, but a general-purpose feature like this is
beyond its reach. Source: hallway discussion with Daveed
Vandevoorde.</p>
<p>We probably need to do the specification work of this paper to
understand the corner cases of even trying to do this with
reflection.</p>
<p>Reflection (<span class="citation" data-cites="P2320R0">[<a href="#ref-P2320R0" role="doc-biblioref">P2320R0</a>]</span>,<span class="citation" data-cites="P1240R1">[<a href="#ref-P1240R1" role="doc-biblioref">P1240R1</a>]</span>,<span class="citation" data-cites="P2237R0">[<a href="#ref-P2237R0" role="doc-biblioref">P2237R0</a>]</span>,<span class="citation" data-cites="P2087R0">[<a href="#ref-P2087R0" role="doc-biblioref">P2087R0</a>]</span>,<span class="citation" data-cites="N4856">[<a href="#ref-N4856" role="doc-biblioref">N4856</a>]</span>) might miss C++26, and is far
wider in scope as another
<code class="sourceCode default">decltype</code>-ish proposal that’s
easily implementable today, and
<code class="sourceCode default">std::execution</code> could use
immediately.</p>
<p>Regardless of how we chose to provide this facility, it is dearly
needed, and should be provided by the standard library or a
built-in.</p>
<p>See the <a href="#alternatives-to-syntax">Alternatives to Syntax</a>
chapter for details.</p>
<h3 data-number="2.1.2" id="library-fundamentals-ts-v3"><span class="header-section-number">2.1.2</span> Library fundamentals TS v3<a href="#library-fundamentals-ts-v3" class="self-link"></a></h3>
<p>The <a href="https://cplusplus.github.io/fundamentals-ts/v3.html#meta.trans.other">Library
Fundamentals TS version 3</a> defines <code class="sourceCode default">invocation_type&lt;F(Args...)&gt;</code> and
<code class="sourceCode default">raw_invocation_type&lt;F(Args...)&gt;</code>
with the hope of getting the function pointer type of a given call
expression.</p>
<p>However, this is not good enough to actually be able to resolve that
call in all cases.</p>
<p>Observe:</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">struct</span> S <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="dt">void</span> f<span class="op">(</span>S<span class="op">)</span> <span class="op">{}</span> <span class="co">// #1</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> f<span class="op">(</span><span class="kw">this</span> S<span class="op">)</span> <span class="op">{}</span>   <span class="co">// #2</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> h<span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_cast</span><span class="op">&lt;</span><span class="dt">void</span><span class="op">(*)(</span>S<span class="op">)&gt;(</span>S<span class="op">::</span>f<span class="op">)</span> <span class="co">// error, ambiguous</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>  S<span class="op">{}.</span>f<span class="op">(</span>S<span class="op">{})</span>; <span class="co">// calls #1</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  S<span class="op">{}.</span>f<span class="op">()</span>; <span class="co">// calls #2</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// no ambiguity for declcall</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>S<span class="op">{}.</span>f<span class="op">(</span>S<span class="op">{}))</span>; <span class="co">// &amp;#1</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>S<span class="op">{}.</span>f<span class="op">())</span>;    <span class="co">// &amp;#2</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>A library solution can’t give us this, no matter how much we try,
unless we can reflect on unevaluated operands (which Reflection
does).</p>
<h1 data-number="3" id="proposal"><span class="header-section-number">3</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>We propose a new (technically) non-overloadable operator (because
<code class="sourceCode default">sizeof</code> is one, and this behaves
similarly):</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>declcall<span class="op">(</span><em>expression</em><span class="op">)</span>;</span></code></pre></div>
<p>Example:</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="dt">int</span> f<span class="op">(</span><span class="dt">int</span><span class="op">)</span>;  <span class="co">// 1</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> f<span class="op">(</span><span class="dt">long</span><span class="op">)</span>; <span class="co">// 2</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> fptr_to_1 <span class="op">=</span> declcall<span class="op">(</span>f<span class="op">(</span><span class="dv">2</span><span class="op">))</span>;</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> fptr_to_2 <span class="op">=</span> declcall<span class="op">(</span>f<span class="op">(</span><span class="dv">2</span><span class="bu">l</span><span class="op">))</span>;</span></code></pre></div>
<p>The program is ill-formed if the named
<code class="sourceCode default"><em>postfix-expression</em></code> is
not a call to an addressable function (such as a constructor,
destructor, built-in, etc.).</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">struct</span> S <span class="op">{}</span>;</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>declcall<span class="op">(</span>S<span class="op">())</span>; <span class="co">// Error, constructors are not addressable</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>declcall<span class="op">(</span><span class="fu">__builtin_unreachable</span><span class="op">())</span>; <span class="co">// Error, not addressable</span></span></code></pre></div>
<p>The expression is not a constant expression if the
<code class="sourceCode default"><em>expression</em></code> does not
resolve for unevaluated operands. Examples of this function pointer
values and surrogate functions.</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="dt">int</span> f<span class="op">(</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> fptr_t <span class="op">=</span> <span class="dt">int</span> <span class="op">(*)(</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> fptr_t fptr <span class="op">=</span> declcall<span class="op">(</span>f<span class="op">(</span><span class="dv">2</span><span class="op">))</span>;</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>declcall<span class="op">(</span>fptr<span class="op">(</span><span class="dv">2</span><span class="op">))</span>; <span class="co">// Error, fptr_to_1 is a pointer value</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> T <span class="op">{</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">operator</span> fptr_t<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> fptr; <span class="op">}</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>declcall<span class="op">(</span>T<span class="op">{}(</span><span class="dv">2</span><span class="op">))</span>; <span class="co">// Error, T{} would need to be evaluated</span></span></code></pre></div>
<p>If the
<code class="sourceCode default">declcall(<em>expression</em>)</code> is
evaluated and not a constant expression, the program is ill-formed (but
SFINAE-friendly).</p>
<p>However, if it is unevaluated, it’s not an error.</p>
<p>Example:</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="dt">int</span> f<span class="op">(</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> fptr_t <span class="op">=</span> <span class="dt">int</span> <span class="op">(*)(</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> fptr_t fptr <span class="op">=</span> declcall<span class="op">(</span>f<span class="op">(</span><span class="dv">2</span><span class="op">))</span>;</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="kw">static_cast</span><span class="op">&lt;</span>declcall<span class="op">(</span>fptr<span class="op">(</span><span class="dv">2</span><span class="op">))&gt;(</span>fptr<span class="op">)</span>; <span class="co">// OK, fptr, though redundant</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> T <span class="op">{</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">operator</span> fptr_t<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> fptr; <span class="op">}</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a><span class="kw">static_cast</span><span class="op">&lt;</span>declcall<span class="op">(</span>T<span class="op">{}(</span><span class="dv">2</span><span class="op">))&gt;(</span>T<span class="op">{})</span>; <span class="co">// OK, fptr</span></span></code></pre></div>
<p>This pattern covers all cases that need evaluated base operands,
while making it explicit that the operand is evaluated due to the
<code class="sourceCode default">static_cast</code>.</p>
<p>Examples:</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="dt">void</span> g<span class="op">(</span><span class="dt">long</span> x<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> x<span class="op">+</span><span class="dv">1</span>; <span class="op">}</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">()</span> <span class="op">{}</span>                                                <span class="co">// #1</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="op">{}</span>                                             <span class="co">// #2</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> S <span class="op">{</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">+(</span>S, S<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">-&gt;</span> S <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span> <span class="co">// #3</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <span class="kw">operator</span><span class="op">-(</span>S<span class="op">)</span> <span class="op">-&gt;</span> S <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span>                    <span class="co">// #4</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <span class="kw">operator</span><span class="op">-(</span>S, S<span class="op">)</span> <span class="op">-&gt;</span> S <span class="op">{</span> <span class="cf">return</span> <span class="op">{}</span>; <span class="op">}</span>                 <span class="co">// #5</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> f<span class="op">()</span> <span class="op">{}</span>                                              <span class="co">// #6</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> f<span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="op">{}</span>                                           <span class="co">// #7</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>  S<span class="op">()</span> <span class="kw">noexcept</span> <span class="op">{}</span>                                          <span class="co">// #8</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">~</span>S<span class="op">()</span> <span class="kw">noexcept</span> <span class="op">{}</span>                                         <span class="co">// #9</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <span class="kw">operator</span><span class="op">-&gt;(</span><span class="kw">this</span> <span class="kw">auto</span><span class="op">&amp;&amp;</span> self<span class="op">)</span> <span class="kw">const</span> <span class="op">-&gt;</span> S<span class="op">*</span>;           <span class="co">// #10</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <span class="kw">operator</span><span class="op">[](</span><span class="kw">this</span> <span class="kw">auto</span><span class="op">&amp;&amp;</span> self, <span class="dt">int</span> i<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">int</span>;         <span class="co">// #11</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">auto</span> f<span class="op">(</span>S<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">int</span>;                                 <span class="co">// #12</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> fptr <span class="op">=</span> <span class="dt">void</span><span class="op">(*)(</span><span class="dt">long</span><span class="op">)</span>;</span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <span class="kw">operator</span> fptr <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">&amp;</span>g; <span class="op">}</span>                  <span class="co">// #13</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&lt;=&gt;(</span>S <span class="kw">const</span><span class="op">&amp;)</span> <span class="op">=</span> <span class="cf">default</span>;                    <span class="co">// #14</span></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>S f<span class="op">(</span><span class="dt">int</span>, <span class="dt">long</span><span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> S<span class="op">{}</span>; <span class="op">}</span>                             <span class="co">// #15</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> U <span class="op">:</span> S <span class="op">{}</span></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> h<span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true" tabindex="-1"></a>  S s;</span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true" tabindex="-1"></a>  U u;</span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>f<span class="op">())</span>;                     <span class="co">// ok, &amp;#1             (A)</span></span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>f<span class="op">(</span><span class="dv">1</span><span class="op">))</span>;                    <span class="co">// ok, &amp;#2             (B)</span></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>f<span class="op">(</span>std<span class="op">::</span>declval<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;()))</span>;  <span class="co">// ok, &amp;#2             (C)</span></span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>f<span class="op">(</span><span class="dv">1</span><span class="bu">s</span><span class="op">))</span>;                   <span class="co">// ok, &amp;#2 (!)         (D)</span></span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>s <span class="op">+</span> s<span class="op">)</span>;                   <span class="co">// ok, &amp;#3             (E)</span></span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(-</span>s<span class="op">)</span>;                      <span class="co">// ok, &amp;#4             (F)</span></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(-</span>u<span class="op">)</span>;                      <span class="co">// ok, &amp;#4 (!)         (G)</span></span>
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>s <span class="op">-</span> s<span class="op">)</span>;                   <span class="co">// ok, &amp;#5             (H)</span></span>
<span id="cb8-33"><a href="#cb8-33" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>s<span class="op">.</span>f<span class="op">())</span>;                   <span class="co">// ok, &amp;#6             (I)</span></span>
<span id="cb8-34"><a href="#cb8-34" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>u<span class="op">.</span>f<span class="op">())</span>;                   <span class="co">// ok, &amp;#6 (!)         (J)</span></span>
<span id="cb8-35"><a href="#cb8-35" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>s<span class="op">.</span>f<span class="op">(</span><span class="dv">2</span><span class="op">))</span>;                  <span class="co">// ok, &amp;#7             (K)</span></span>
<span id="cb8-36"><a href="#cb8-36" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>s<span class="op">)</span>;                       <span class="co">// error, constructor  (L)</span></span>
<span id="cb8-37"><a href="#cb8-37" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>s<span class="op">.</span>S<span class="op">::~</span>S<span class="op">())</span>;               <span class="co">// error, destructor   (M)</span></span>
<span id="cb8-38"><a href="#cb8-38" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>s<span class="op">-&gt;</span>f<span class="op">())</span>;                  <span class="co">// ok, &amp;#6 (not &amp;#10)  (N)</span></span>
<span id="cb8-39"><a href="#cb8-39" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>s<span class="op">.</span>S<span class="op">::</span><span class="kw">operator</span><span class="op">-&gt;())</span>;       <span class="co">// ok, &amp;#10            (O)</span></span>
<span id="cb8-40"><a href="#cb8-40" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>s<span class="op">[</span><span class="dv">1</span><span class="op">])</span>;                    <span class="co">// ok, &amp;#11            (P)</span></span>
<span id="cb8-41"><a href="#cb8-41" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>S<span class="op">::</span>f<span class="op">(</span>S<span class="op">{}))</span>;               <span class="co">// ok, &amp;#12            (Q)</span></span>
<span id="cb8-42"><a href="#cb8-42" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>s<span class="op">.</span>f<span class="op">(</span>S<span class="op">{}))</span>;                <span class="co">// ok, &amp;#12            (R)</span></span>
<span id="cb8-43"><a href="#cb8-43" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>s<span class="op">(</span><span class="dv">1</span><span class="bu">l</span><span class="op">))</span>;                   <span class="co">// error, #13          (S)</span></span>
<span id="cb8-44"><a href="#cb8-44" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static_cast</span><span class="op">&lt;</span>declcall<span class="op">(</span>s<span class="op">(</span><span class="dv">1</span><span class="bu">l</span><span class="op">)&gt;(</span>s<span class="op">))</span>;   <span class="co">// ok, &amp;13             (S)</span></span>
<span id="cb8-45"><a href="#cb8-45" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>f<span class="op">(</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">))</span>;                 <span class="co">// ok, &amp;#15            (T)</span></span>
<span id="cb8-46"><a href="#cb8-46" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span><span class="kw">new</span> <span class="op">(</span><span class="kw">nullptr</span><span class="op">)</span> S<span class="op">())</span>;       <span class="co">// error, not function (U)</span></span>
<span id="cb8-47"><a href="#cb8-47" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span><span class="kw">delete</span> <span class="op">&amp;</span>s<span class="op">)</span>;               <span class="co">// error, not function (V)</span></span>
<span id="cb8-48"><a href="#cb8-48" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span><span class="dv">1</span> <span class="op">+</span> <span class="dv">1</span><span class="op">)</span>;                   <span class="co">// error, built-in     (W)</span></span>
<span id="cb8-49"><a href="#cb8-49" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">([]{</span></span>
<span id="cb8-50"><a href="#cb8-50" aria-hidden="true" tabindex="-1"></a>       <span class="cf">return</span> declcall<span class="op">(</span>f<span class="op">())</span>;</span>
<span id="cb8-51"><a href="#cb8-51" aria-hidden="true" tabindex="-1"></a>    <span class="op">}()())</span>;                          <span class="co">// error (unevaluated) (X)</span></span>
<span id="cb8-52"><a href="#cb8-52" aria-hidden="true" tabindex="-1"></a>  declcall<span class="op">(</span>S<span class="op">{}</span> <span class="op">&lt;</span> S<span class="op">{})</span>;               <span class="co">// error, synthesized  (Y)</span></span>
<span id="cb8-53"><a href="#cb8-53" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="3.1" id="interesting-cases-in-the-above-example"><span class="header-section-number">3.1</span> Interesting cases in the above
example<a href="#interesting-cases-in-the-above-example" class="self-link"></a></h2>
<ul>
<li>resolving different members of a free-function overload set (A, B,
C, D, T)
<ul>
<li>the (D) case is important - the
<code class="sourceCode default">short</code> argument still resolves to
the <code class="sourceCode default">int</code> overload!</li>
</ul></li>
<li>constructors and destructors (L, M, U, V) - see the <strong>possible
extensions</strong> chapter.</li>
<li>resolving different member of a member-function overload set (I, J,
K, N, Q, R)
<ul>
<li>the (J) example is important - the call on
<code class="sourceCode default">u</code> still resolves to a member
function of <code class="sourceCode default">S</code>.</li>
</ul></li>
<li>resolving built-in non-functions (W): we could make this work in a
future extension (see that chapter).</li>
<li>resolving <code class="sourceCode default">operator-&gt;</code> (N
and O). <span class="marginalizedparent"><a class="marginalized">(expr.post.general)</a></span>
specifies that
<code class="sourceCode default"><em>postfix-expression</em></code>s
group left-to-right, which means the top-most postfix-expression is the
call to <code class="sourceCode default">f()</code>, and not the
<code class="sourceCode default">-&gt;</code>. To get to
<code class="sourceCode default">S::operator-&gt;</code>, we have to ask
for it explicitly.</li>
<li>surrogate function call (S) - again, the top-most call-expression is
the function call to <code class="sourceCode default">g</code>, so the
type of <code class="sourceCode default">g</code> is returned, but it’s
not a constant expression. We can get it by evaluating the operand with
<code class="sourceCode default">static_cast</code>.</li>
<li>nested calls: (X) the top-level call is a call to a function-pointer
to #2, so that is what is returned, but since obtaining the value of the
function pointer requires evaluation, this is ill-formed. Getting the
type is fine.</li>
<li>Synthesized operators (Y) - these are not functions that we can take
pointers to, so unless we “force-manufacture” one, we can’t make this
work.</li>
</ul>
<h2 data-number="3.2" id="alternatives-to-syntax"><span class="header-section-number">3.2</span> Alternatives to syntax<a href="#alternatives-to-syntax" class="self-link"></a></h2>
<p>We could wait for reflection in which case
<code class="sourceCode default">declcall</code> is implementable when
we have expression reflections.</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">namespace</span> std<span class="op">::</span>meta <span class="op">{</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>info r<span class="op">&gt;</span> <span class="kw">constexpr</span> <span class="kw">auto</span> declcall <span class="op">=</span> <span class="op">[]{</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>is_nonstatic_member<span class="op">(</span>r<span class="op">))</span> <span class="op">{</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> pointer_to_member<span class="op">&lt;[:</span>pm_type_of<span class="op">(</span>r<span class="op">):]&gt;(</span>r<span class="op">)</span>;</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> entity_ref<span class="op">&lt;[:</span>type_of<span class="op">:]&gt;(</span>r<span class="op">)</span>;</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="co">/* insert additional cases as we define them. */</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}()</span>;</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> f<span class="op">(</span><span class="dt">int</span><span class="op">)</span>; <span class="co">//1 </span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> f<span class="op">(</span><span class="dt">long</span><span class="op">)</span>; <span class="co">//2</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> fptr_1 <span class="op">=</span> <span class="op">[:</span> declcall<span class="op">&lt;^</span>f<span class="op">(</span><span class="dv">1</span><span class="op">)&gt;</span> <span class="op">:]</span>; <span class="co">// 1</span></span></code></pre></div>
<p>It’s unlikely to be quite as efficient as just hooking directly into
the resolver, but it does have the nice property that it doesn’t take up
a whole keyword.</p>
<p>It <em>also</em> currently only works for constant expressions, so
it’s not general-purpose. For general arguments, one would need to pass
reflections of arguments, and if those aren’t constant expressions, this
gets really complicated.
<code class="sourceCode default">declcall</code> is far simpler.</p>
<p>Many thanks to Daveed Vandevoorde for helping out with this
example.</p>
<h2 data-number="3.3" id="naming"><span class="header-section-number">3.3</span> Naming<a href="#naming" class="self-link"></a></h2>
<p>I think <code class="sourceCode default">declcall</code> is a
reasonable name - it hints that it’s an unevaluated operand, and it’s
how I implemented it in clang.</p>
<p><a href="https://codesearch.isocpp.org/cgi-bin/cgi_ppsearch?q=declcall&amp;search=Search">codesearch
for declcall</a> comes up with zero hits.</p>
<p>For all intents and purposes, this facility grammatically behaves in
the same way as <code class="sourceCode default">sizeof</code>, except
that we should require the parentheses around the operand.</p>
<p>We could call it something other unlikely to conflict, but I like
<code class="sourceCode default">declcall</code></p>
<ul>
<li><code class="sourceCode default">declcall</code></li>
<li><code class="sourceCode default">declinvoke</code></li>
<li><code class="sourceCode default">calltarget</code></li>
<li><code class="sourceCode default">expression_targetof</code></li>
<li><code class="sourceCode default">calltargetof</code></li>
<li><code class="sourceCode default">decltargetof</code></li>
<li><code class="sourceCode default">resolvetarget</code></li>
</ul>
<h1 data-number="4" id="usecases"><span class="header-section-number">4</span> Usecases<a href="#usecases" class="self-link"></a></h1>
<p>Broadly, anywhere where we want to type-erase a call-expression.
Broad uses in any type-erasure library, smart pointers, ABI-stable
interfaces, compilation barriers, task-queues, runtime lifts for
double-dispatch, and the list goes on and on and on and …</p>
<h2 data-number="4.1" id="what-does-this-give-us-that-we-dont-have-yet"><span class="header-section-number">4.1</span> What does this give us that we
don’t have yet<a href="#what-does-this-give-us-that-we-dont-have-yet" class="self-link"></a></h2>
<h3 data-number="4.1.1" id="resolving-overload-sets-for-callbacks-without-lambdas"><span class="header-section-number">4.1.1</span> Resolving overload sets for
callbacks without lambdas<a href="#resolving-overload-sets-for-callbacks-without-lambdas" class="self-link"></a></h3>
<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="co">// generic context</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>sort<span class="op">(</span>v<span class="op">.</span>begin<span class="op">()</span>, v<span class="op">.</span>end<span class="op">()</span>, <span class="op">[](</span><span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> x, <span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> my_comparator<span class="op">(</span>x, y<span class="op">)</span>; <span class="co">// some overload set</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="op">})</span>;</span></code></pre></div>
<p>becomes</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="co">// look ma, no lambda, no inlining, and less code generation!</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>sort<span class="op">(</span>v<span class="op">.</span>begin<span class="op">()</span>, v<span class="op">.</span>end<span class="op">()</span>, declcall<span class="op">(</span>my_comparator<span class="op">(</span>v<span class="op">.</span>front<span class="op">()</span>, v<span class="op">.</span>front<span class="op">()))</span>;</span></code></pre></div>
<p>Note also, that in the case of a
<code class="sourceCode default">vector&lt;int&gt;</code>, the ABI for
the comparator is likely to take those by value, which means we get a
better calling convention.</p>
<p><code class="sourceCode default">static_cast&lt;bool(*)(int, int)&gt;(my_comparator)</code>
is not good enough here - the resolved comparator could take
<code class="sourceCode default">long</code>s, for instance.</p>
<h3 data-number="4.1.2" id="copy-elision-in-callbacks"><span class="header-section-number">4.1.2</span> Copy-elision in callbacks<a href="#copy-elision-in-callbacks" class="self-link"></a></h3>
<p>We cannot correctly forward immovable type construction through
forwarding function.</p>
<p>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="dt">int</span> f<span class="op">(</span>nonmovable<span class="op">)</span> <span class="op">{</span> <span class="co">/* ... */</span> <span class="op">}</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// doesn&#39;t work</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</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> obj<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> f<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>obj<span class="op">)&gt;(</span>obj<span class="op">))</span>; <span class="co">// 1</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>    <span class="co">// would work if we also had replacement function / expression aliases</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</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> obj<span class="op">)</span> <span class="kw">const</span> </span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>       <span class="op">=</span> declcall<span class="op">(</span>f<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>obj<span class="op">&gt;(</span>obj<span class="op">)))</span>;      <span class="co">// 2</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> some_customization_point_object;</span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> continue_with_result<span class="op">(</span><span class="kw">auto</span> callback<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>    callback<span class="op">(</span>nonmovable<span class="op">{</span>read_something<span class="op">()})</span>;</span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> handler<span class="op">()</span> <span class="op">{</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a>    continue_with_result<span class="op">(</span>declcall<span class="op">(</span>f<span class="op">(</span>nonmovable<span class="op">{})))</span>; <span class="co">// works</span></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a>    <span class="co">// (1) doesn&#39;t work, (2) works</span></span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a>    continue_with_result<span class="op">(</span>some_customization_point_object<span class="op">)</span>;</span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="4.2" id="thats-not-good-enough-to-do-all-that-work.-what-else"><span class="header-section-number">4.2</span> That’s not good enough to do
all that work. What else?<a href="#thats-not-good-enough-to-do-all-that-work.-what-else" class="self-link"></a></h2>
<p>Together with <span class="citation" data-cites="P2826R0">[<a href="#ref-P2826R0" role="doc-biblioref">P2826R0</a>]</span>, the two
papers constitute the ability to implement
<em>expression-equivalent</em> in many important cases (not all, that’s
probably impossible).</p>
<p><span class="citation" data-cites="P2826R0">[<a href="#ref-P2826R0" role="doc-biblioref">P2826R0</a>]</span> proposes a way for a function
signature to participate in overload resolution and, if it wins, be
replaced by some other function.</p>
<p>This facility is the key to <em>finding</em> that other function. The
ability to preserve prvalue-ness is crucial to implementing quite a lot
of the standard library customization points as mandated by the
standard, without compiler help.</p>
<h1 data-number="5" id="needed-guidance"><span class="header-section-number">5</span> Needed Guidance<a href="#needed-guidance" class="self-link"></a></h1>
<ul>
<li>Do we want to punt the syntax to reflection, or is this basic enough
to warrant this feature? (Knowing that reflection will need more work
from the user to get the pointer value).</li>
<li>Do we care that it only works on unevaluated operands? (With the
<code class="sourceCode default">static_cast</code> fallback in run-time
cases)</li>
</ul>
<h1 data-number="6" id="bibliography"><span class="header-section-number">6</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" role="doc-bibliography">
<div id="ref-N4856" class="csl-entry" role="doc-biblioentry">
[N4856] David Sankel. 2020-03-02. C++ Extensions for Reflection. <a href="https://wg21.link/n4856"><div class="csl-block">https://wg21.link/n4856</div></a>
</div>
<div id="ref-P1240R1" class="csl-entry" role="doc-biblioentry">
[P1240R1] Daveed Vandevoorde, Wyatt Childers, Andrew Sutton, Faisal
Vali, Daveed Vandevoorde. 2019-10-08. Scalable Reflection in C++. <a href="https://wg21.link/p1240r1"><div class="csl-block">https://wg21.link/p1240r1</div></a>
</div>
<div id="ref-P2087R0" class="csl-entry" role="doc-biblioentry">
[P2087R0] Mihail Naydenov. 2020-01-12. Reflection Naming: fix reflexpr.
<a href="https://wg21.link/p2087r0"><div class="csl-block">https://wg21.link/p2087r0</div></a>
</div>
<div id="ref-P2237R0" class="csl-entry" role="doc-biblioentry">
[P2237R0] Andrew Sutton. 2020-10-15. Metaprogramming. <a href="https://wg21.link/p2237r0"><div class="csl-block">https://wg21.link/p2237r0</div></a>
</div>
<div id="ref-P2300R6" class="csl-entry" role="doc-biblioentry">
[P2300R6] Michał Dominiak, Georgy Evtushenko, Lewis Baker, Lucian Radu
Teodorescu, Lee Howes, Kirk Shoop, Michael Garland, Eric Niebler, Bryce
Adelstein Lelbach. 2023-01-19. `std::execution`. <a href="https://wg21.link/p2300r6"><div class="csl-block">https://wg21.link/p2300r6</div></a>
</div>
<div id="ref-P2320R0" class="csl-entry" role="doc-biblioentry">
[P2320R0] Andrew Sutton, Wyatt Childers, Daveed Vandevoorde. 2021-02-15.
The Syntax of Static Reflection. <a href="https://wg21.link/p2320r0"><div class="csl-block">https://wg21.link/p2320r0</div></a>
</div>
<div id="ref-P2826R0" class="csl-entry" role="doc-biblioentry">
[P2826R0] Gašper Ažman. Replacement functions. <a href="https://wg21.link/P2826R0"><div class="csl-block">https://wg21.link/P2826R0</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
