<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2023-11-05" />
  <title>Replacement function</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">Replacement function</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2826R1</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2023-11-05</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="#status" id="toc-status"><span class="toc-section-number">2</span> Status<span></span></a></li>
<li><a href="#proposal" id="toc-proposal"><span class="toc-section-number">3</span> Proposal<span></span></a>
<ul>
<li><a href="#example-1-simple-free-function-aliases" id="toc-example-1-simple-free-function-aliases"><span class="toc-section-number">3.1</span> Example 1: simple free function
aliases<span></span></a></li>
<li><a href="#example-2-simple-member-function-aliases" id="toc-example-2-simple-member-function-aliases"><span class="toc-section-number">3.2</span> Example 2: simple member function
aliases<span></span></a></li>
<li><a href="#example-3-computed-target" id="toc-example-3-computed-target"><span class="toc-section-number">3.3</span> Example 3: computed
target<span></span></a></li>
<li><a href="#example-4-deduce-to-baseclass" id="toc-example-4-deduce-to-baseclass"><span class="toc-section-number">3.4</span> Example 4:
deduce-to-baseclass<span></span></a></li>
<li><a href="#discussion" id="toc-discussion"><span class="toc-section-number">3.5</span> Discussion<span></span></a></li>
<li><a href="#what-if-the-constant-expression-evaluates-to-null" id="toc-what-if-the-constant-expression-evaluates-to-null"><span class="toc-section-number">3.6</span> What if the constant expression
evaluates to null?<span></span></a></li>
</ul></li>
<li><a href="#why-this-syntax" id="toc-why-this-syntax"><span class="toc-section-number">4</span> Why this
syntax<span></span></a></li>
<li><a href="#nice-to-have-properties" id="toc-nice-to-have-properties"><span class="toc-section-number">5</span> Nice-to-have
properties<span></span></a></li>
<li><a href="#related-work" id="toc-related-work"><span class="toc-section-number">6</span> Related Work<span></span></a></li>
<li><a href="#use-cases" id="toc-use-cases"><span class="toc-section-number">7</span> Use-cases<span></span></a>
<ul>
<li><a href="#deduce-to-type" id="toc-deduce-to-type"><span class="toc-section-number">7.1</span>
deduce-to-type<span></span></a></li>
<li><a href="#expression-equivalent-for-stdstrong_order" id="toc-expression-equivalent-for-stdstrong_order"><span class="toc-section-number">7.2</span> expression-equivalent for
<code class="sourceCode default">std::strong_order</code><span></span></a></li>
<li><a href="#interactions-with-__builtin_calltarget" id="toc-interactions-with-__builtin_calltarget"><span class="toc-section-number">7.3</span> interactions with
<code class="sourceCode default">__builtin_calltarget()</code><span></span></a></li>
<li><a href="#programmable-ufcs" id="toc-programmable-ufcs"><span class="toc-section-number">7.4</span> programmable
UFCS<span></span></a></li>
<li><a href="#the-rename-overload-set-rename-function-refactoring-becomes-possible-in-large-codebases" id="toc-the-rename-overload-set-rename-function-refactoring-becomes-possible-in-large-codebases"><span class="toc-section-number">7.5</span> The “Rename Overload Set” /
“Rename Function” refactoring becomes possible in large
codebases<span></span></a></li>
<li><a href="#the-rename-function-refactoring-becomes-abi-stable" id="toc-the-rename-function-refactoring-becomes-abi-stable"><span class="toc-section-number">7.6</span> The “rename function” refactoring
becomes ABI stable<span></span></a></li>
</ul></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">8</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 way to redirect a function call to a
different function without a forwarding layer.</p>
<p>Example:</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="dt">int</span> g<span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="dv">42</span>; <span class="op">}</span></span>
<span id="cb1-2"><a href="#cb1-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="op">{</span> <span class="cf">return</span> <span class="dv">43</span>; <span class="op">}</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> g<span class="op">(</span><span class="dt">unsigned</span><span class="op">)</span> <span class="op">=</span> <span class="op">&amp;</span>f; <span class="co">// handle unsigned int with f(long)</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>    g<span class="op">(</span><span class="dv">1</span><span class="op">)</span>; <span class="co">// 42</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    g<span class="op">(</span><span class="dv">1</span><span class="bu">u</span><span class="op">)</span>; <span class="co">// 43</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>One might think that declaring</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="dt">int</span> g<span class="op">(</span><span class="dt">unsigned</span> x<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> f<span class="op">(</span>x<span class="op">)</span>; <span class="op">}</span></span></code></pre></div>
<p>is equivalent; this is far from the case in general, which is exactly
why we need this capability. See the motivation section for the full
list of issues this capability solves.</p>
<p>First, however, this paper introduces what it <em>does</em>.</p>
<h1 data-number="2" id="status"><span class="header-section-number">2</span> Status<a href="#status" class="self-link"></a></h1>
<p>This paper is in early stages of exploration. The R1 will be
presented to EWGI in Kona, 2023.</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 kind of function definition of the form</p>
<p><em>function-body</em>: … <code class="sourceCode default">=</code>
<em>constant-expression</em>
<code class="sourceCode default">;</code></p>
<p>where the <em>constant-expression</em> evaluates to a
pointer-to-function or pointer-to-member-function. We will call this
function the <strong>target</strong>.</p>
<p>The associated function declaration has to be declared with a return
type of <code class="sourceCode default">auto</code>, and cannot have
been declared previously.</p>
<p>A call expression that resolves to a function thus declared instead
resolves to the target. This may render the program ill-formed.</p>
<h2 data-number="3.1" id="example-1-simple-free-function-aliases"><span class="header-section-number">3.1</span> Example 1: simple free function
aliases<a href="#example-1-simple-free-function-aliases" class="self-link"></a></h2>
<p>We could implement overload sets from the C library without
indirection:</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="co">// &lt;cmath&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span>   exp<span class="op">(</span><span class="dt">float</span><span class="op">)</span>       <span class="op">=</span> <span class="op">&amp;</span>expf; <span class="co">// no duplication </span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="dt">double</span> exp<span class="op">(</span><span class="dt">double</span><span class="op">)</span>      <span class="op">{</span> <span class="co">/* normal definition */</span> <span class="op">}</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span>   exp<span class="op">(</span><span class="dt">long</span> <span class="dt">double</span><span class="op">)</span> <span class="op">=</span> <span class="op">&amp;</span>expl; <span class="co">// no duplication</span></span></code></pre></div>
<p>This capability would make wrapping C APIs much easier, since we
could just make overload sets out of individually-named functions.</p>
<h2 data-number="3.2" id="example-2-simple-member-function-aliases"><span class="header-section-number">3.2</span> Example 2: simple member
function aliases<a href="#example-2-simple-member-function-aliases" class="self-link"></a></h2>
<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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Container <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> cbegin<span class="op">()</span> <span class="kw">const</span> <span class="op">-&gt;</span> const_iterator;</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> begin<span class="op">()</span> <span class="op">-&gt;</span> iterator;</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> begin<span class="op">()</span> <span class="kw">const</span> <span class="op">=</span> <span class="op">&amp;</span>cbegin; <span class="co">// saves on template instantiations</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<h2 data-number="3.3" id="example-3-computed-target"><span class="header-section-number">3.3</span> Example 3: computed target<a href="#example-3-computed-target" class="self-link"></a></h2>
<p><code class="sourceCode default">fmt::format</code> goes through
great lengths to validate format string compatibility at compile time,
but <em>really</em> does not want to generate code for every different
kind of string.</p>
<p>This is extremely simple to do with this extension - just funnel all
instantiations to a <code class="sourceCode default">string_view</code>
overload.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> FmtString, <span class="kw">typename</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> compatible<span class="op">&lt;</span>FmtString, Args<span class="op">...&gt;</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> format<span class="op">(</span>FmtString <span class="kw">const</span><span class="op">&amp;</span>, Args <span class="kw">const</span><span class="op">&amp;...</span> args<span class="op">)</span> </span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="op">=</span> <span class="kw">static_cast</span><span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">(*)(</span>std<span class="op">::</span>string_view, Args <span class="kw">const</span><span class="op">&amp;...)&gt;(&amp;</span>format<span class="op">)</span>;</span></code></pre></div>
<p>Contrast with the best we can realistically do presently:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> FmtString, <span class="kw">typename</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> compatible<span class="op">&lt;</span>FmtString, Args<span class="op">...&gt;</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> format<span class="op">(</span>FmtString <span class="kw">const</span><span class="op">&amp;</span> fmt, Args <span class="kw">const</span><span class="op">&amp;...</span> args<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>string <span class="op">{</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> format<span class="op">(</span>std<span class="op">::</span>string_view<span class="op">(</span>fmt<span class="op">)</span>, args<span class="op">...)</span>;</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The second example results in a separate function for each format
string (which is, say, one per log statement). The first provably never
instantiates different function bodies for different format strings.</p>
<h2 data-number="3.4" id="example-4-deduce-to-baseclass"><span class="header-section-number">3.4</span> Example 4:
deduce-to-baseclass<a href="#example-4-deduce-to-baseclass" class="self-link"></a></h2>
<p>Imagine we inherited from
<code class="sourceCode default">std::optional</code>, and we wanted to
forward <code class="sourceCode default">operator*</code>, but have it
be treated the same as <code class="sourceCode default">value()</code>;
note this is <em>far</em> easier to done with the help of
<code class="sourceCode default">__builtin_calltarget</code> <span class="citation" data-cites="P2825R0">[<a href="#ref-P2825R0" role="doc-biblioref">P2825R0</a>]</span>, so we’ll use it here (it’s
just “give me the function pointer to the top-most call
expression”):</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> my_optional <span class="op">:</span> std<span class="op">::</span>optional<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> Self<span class="op">&gt;</span></span>
<span id="cb7-4"><a href="#cb7-4" 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> Self<span class="op">&amp;&amp;</span> self<span class="op">)</span> <span class="op">=</span> <span class="fu">__builtin_calltarget</span><span class="op">(</span>std<span class="op">::</span>declval<span class="op">&lt;</span>Self<span class="op">&gt;().</span>value<span class="op">())</span>;</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Without <code class="sourceCode default">__bultin_calltarget</code>,
the computation becomes a <em>lot</em> uglier, because we need to
conjure the function pointer type for each cv-ref qualification, so I’m
not even going to include it here.</p>
<h2 data-number="3.5" id="discussion"><span class="header-section-number">3.5</span> Discussion<a href="#discussion" class="self-link"></a></h2>
<p>There are two parts such a function definition: the declarator, and
the body.</p>
<p>The function signature as declared in the declarator participates in
overload resolution. (the constant expression is not part of the
immediate context).</p>
<p>If overload resolution picks this signature, then, <em>poof</em>,
instead of substituting this signature into the call-expression, the
replacement function is substituted. If this renders the program
ill-formed, so be it.</p>
<h2 data-number="3.6" id="what-if-the-constant-expression-evaluates-to-null"><span class="header-section-number">3.6</span> What if the constant expression
evaluates to null?<a href="#what-if-the-constant-expression-evaluates-to-null" class="self-link"></a></h2>
<p>That renders calling that overload ill-formed (and thus effectively
means the same as a programmable
<code class="sourceCode default">= delete</code>).</p>
<p><code class="sourceCode default">virtual</code>, in which case you
can now spell conditionally-implemented overrides. Yay. (Note: whether a
class is abstract or not is decided when the vtable entry is tried to be
synthesized and fails).</p>
<p>For virtual functions, though, the signature needs to match in the
same way as signatures of overrides have to match the virtual interface
declaration, otherwise we have a problem with ABI.</p>
<p>Example:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span> enable_implementations<span class="op">&gt;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> A <span class="op">{</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">long</span> g<span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="dv">42</span>; <span class="op">}</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">long</span> h<span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="op">=</span> enable_implementations <span class="op">?</span> <span class="op">&amp;</span>g <span class="op">:</span> <span class="kw">nullptr</span>;</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">virtual</span> <span class="dt">long</span> f<span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="op">=</span> enable_implementations <span class="op">?</span> <span class="op">&amp;</span>g <span class="op">:</span> <span class="kw">nullptr</span>;</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Concrete <span class="op">:</span> A<span class="op">&lt;</span><span class="kw">true</span><span class="op">&gt;</span> <span class="op">{}</span>;</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Abstract <span class="op">:</span> A<span class="op">&lt;</span><span class="kw">false</span><span class="op">&gt;</span> <span class="op">{}</span>;</span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Concrete2 <span class="op">:</span> Abstract <span class="op">{</span> <span class="dt">long</span> f<span class="op">(</span><span class="dt">int</span><span class="op">)</span> <span class="kw">override</span> <span class="op">{</span> <span class="cf">return</span> <span class="dv">3</span>; <span class="op">}</span> <span class="op">}</span>;</span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> impl<span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>  Concrete x;  <span class="co">// ok</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>  x<span class="op">.</span>h<span class="op">(</span><span class="dv">2</span><span class="op">)</span>;      <span class="co">// ok, 42</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>  Concrete2 z; <span class="co">// ok</span></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>  z<span class="op">.</span>f<span class="op">(</span><span class="dv">2</span><span class="op">)</span>;      <span class="co">// ok, 3</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>  z<span class="op">.</span>h<span class="op">(</span><span class="dv">2</span><span class="op">)</span>;      <span class="co">// Error, h is explicitly deleted</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a>  Abstract y;  <span class="co">// Error, f(int) is abstract</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<h1 data-number="4" id="why-this-syntax"><span class="header-section-number">4</span> Why this syntax<a href="#why-this-syntax" class="self-link"></a></h1>
<ul>
<li>syntax noted actually already exist, just look for =delete</li>
<li>it works for <code class="sourceCode default">0</code> as
“not-provided” and <code class="sourceCode default">= delete</code> as
“no body”, consistently</li>
</ul>
<h1 data-number="5" id="nice-to-have-properties"><span class="header-section-number">5</span> Nice-to-have properties<a href="#nice-to-have-properties" class="self-link"></a></h1>
<ul>
<li>removal of library-defined dispatch from callstacks</li>
<li>optimizers have to work way less hard</li>
<li>major symbol reduction</li>
<li>no issues with expressions - we don’t modify expressions (compare:
parametric expressions)</li>
<li>No extra work for overload resolution - this feature has no bearing
on overload resolution, as the
<code class="sourceCode default"><em>constant-expression</em></code> is
evaluated at declaration time.</li>
</ul>
<h1 data-number="6" id="related-work"><span class="header-section-number">6</span> Related Work<a href="#related-work" class="self-link"></a></h1>
<p>Roughly related were Parametric Expressions <span class="citation" data-cites="P1221R1">[<a href="#ref-P1221R1" role="doc-biblioref">P1221R1</a>]</span>, but they didn’t interact with
overload sets very well.</p>
<p>This paper is strictly orthogonal, as it doesn’t give you a way to
rewire the arguments, just substitute the function that’s actually
invoked.</p>
<h1 data-number="7" id="use-cases"><span class="header-section-number">7</span> Use-cases<a href="#use-cases" class="self-link"></a></h1>
<p>There are many cases in c++ where we want to add a function to an
overload set without wrapping it.</p>
<p>A myriad of use-cases are in the standard itself, just search for
<em>expression_equivalent</em> and you will find many.</p>
<p>The main thing we want to do in all those cases is:</p>
<ul>
<li>step 1: detect a call expression pattern</li>
<li>step 2: dispatch to the appropriate function for that case</li>
</ul>
<p>The problem is that the detection of the pattern and the appropriate
function to call often don’t fit into the standard overload resolution
mechanism of C++, which necessitates a wrapper, such as a customization
point object, or some kind of dispatch function.</p>
<p>This dispatch function, however it’s employed, has no way to
distinguish prvalues from other rvalues and therefore cannot possibly
emulate the copy-elision aspects of <em>expression-equivalent</em>. It
is also a major source of template bloat. The proposed mechanism also
solves a number of currently unsolved problems in the language (see the
<a href="#use-cases">use-cases section</a>).</p>
<h2 data-number="7.1" id="deduce-to-type"><span class="header-section-number">7.1</span> deduce-to-type<a href="#deduce-to-type" class="self-link"></a></h2>
<p>The problem of template-bloat when all we wanted to do was deduce the
type qualifiers has plagued C++ since move-semantics were introduced,
but gets much, worse with the introduction of (Deducing This) <span class="citation" data-cites="P0847R7">[<a href="#ref-P0847R7" role="doc-biblioref">P0847R7</a>]</span> into the language.</p>
<p>This topic is explored in Barry Revzin’s <span class="citation" data-cites="P2481R1">[<a href="#ref-P2481R1" role="doc-biblioref">P2481R1</a>]</span>.</p>
<p>This paper provides a way to spell this though a specific facility
for this functionality might be desirable as a part of a different
paper.</p>
<p>Observe:</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">struct</span> A <span class="op">{}</span>;</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> B <span class="op">:</span> A <span class="op">{}</span>;</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> _f_impl<span class="op">(</span>T<span class="op">&amp;&amp;</span> x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">// only ever gets instantiated for A&amp;, A&amp;&amp;, A const&amp;, and A const&amp;&amp;</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a><span class="co">// </span><span class="al">TODO</span><span class="co"> define cvref-derived-from</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> D, <span class="kw">typename</span> B<span class="op">&gt;</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> derived_from_xcv <span class="op">=</span> std<span class="op">::</span>derived_from<span class="op">&lt;</span>std<span class="op">::</span>remove_cvref_t<span class="op">&lt;</span>D<span class="op">&gt;</span>, B<span class="op">&gt;</span>;</span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span>derived_from<span class="op">&lt;</span>A<span class="op">&gt;</span> T<span class="op">&gt;</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> f<span class="op">(</span>T<span class="op">&amp;&amp;)</span> <span class="op">=</span> <span class="op">&amp;</span>_f_impl<span class="op">&lt;</span>copy_cvref_t<span class="op">&lt;</span>T, A<span class="op">&gt;&gt;</span>;</span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> use_free<span class="op">()</span> <span class="op">{</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a>  B b;</span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a>  f<span class="op">(</span>b<span class="op">)</span>;                <span class="co">// OK, calls _f_impl(A&amp;)</span></span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a>  f<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>b<span class="op">))</span>;     <span class="co">// OK, calls _f_impl(A&amp;&amp;)</span></span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a>  f<span class="op">(</span>std<span class="op">::</span>as_const<span class="op">(</span>b<span class="op">))</span>; <span class="co">// OK, calls _f_impl(A const&amp;)</span></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Or, for an explicit-object member function:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> C <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> f<span class="op">(</span><span class="kw">this</span> std<span class="op">::</span>same_as<span class="op">&lt;</span>C<span class="op">&gt;</span> <span class="kw">auto</span><span class="op">&amp;&amp;</span> x<span class="op">)</span> <span class="op">{}</span> <span class="co">// implementation</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> f<span class="op">(</span><span class="kw">this</span> T<span class="op">&amp;&amp;</span> x<span class="op">)</span> <span class="op">=</span> <span class="kw">static_cast</span><span class="op">&lt;</span><span class="dt">void</span> <span class="op">(*)(</span>copy_cvref_t<span class="op">&lt;</span>T, C<span class="op">&gt;&amp;&amp;)&gt;(</span>f<span class="op">)</span>;</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// or, with __builtin_calltarget (P2825) - helps if you just want to write the equivalent expression</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> f<span class="op">(</span><span class="kw">this</span> T<span class="op">&amp;&amp;</span> x<span class="op">)</span> <span class="op">=</span> <span class="fu">__builtin_calltarget</span><span class="op">(</span>std<span class="op">::</span>declval<span class="op">&lt;</span>copy_cvref_t<span class="op">&lt;</span>T, C<span class="op">&gt;&amp;&amp;&gt;().</span>f<span class="op">())</span>;</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> D <span class="op">:</span> C <span class="op">{}</span>;</span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> use_member<span class="op">()</span> <span class="op">{</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>  D d;</span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a>  d<span class="op">.</span>f<span class="op">()</span>;                <span class="co">// OK, calls C::f(C&amp;)</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>move<span class="op">(</span>d<span class="op">).</span>f<span class="op">()</span>;     <span class="co">// OK, calls C::f(C&amp;&amp;)</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>as_const<span class="op">(</span>d<span class="op">).</span>f<span class="op">()</span>; <span class="co">// OK, calls C::f(C const&amp;)</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 data-number="7.1.1" id="dont-lambdas-make-this-shorter"><span class="header-section-number">7.1.1</span> Don’t lambdas make this
shorter?<a href="#dont-lambdas-make-this-shorter" class="self-link"></a></h3>
<p>Observe that we could also have just defined the inline lambda as the
<em>constant-expression</em>:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> A <span class="op">{}</span>;</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> B <span class="op">:</span> A <span class="op">{}</span>;</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="co">// saves on typing?</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span>derived_from<span class="op">&lt;</span>A<span class="op">&gt;</span> T<span class="op">&gt;</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> f<span class="op">(</span>T<span class="op">&amp;&amp;)</span> <span class="op">=</span> <span class="op">+[](</span>copy_cvref_t<span class="op">&lt;</span>T, A<span class="op">&gt;&amp;&amp;)</span> <span class="op">{}</span>;</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> use_free<span class="op">()</span> <span class="op">{</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>  B b;</span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>  f<span class="op">(</span>b<span class="op">)</span>;                <span class="co">// OK, calls f-lambda(A&amp;)</span></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>  f<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>b<span class="op">))</span>;     <span class="co">// OK, calls f-lambda(A&amp;&amp;)</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>  f<span class="op">(</span>std<span class="op">::</span>as_const<span class="op">(</span>b<span class="op">))</span>; <span class="co">// OK, calls f-lambda(A const&amp;)</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>While at first glance this saves on template instantiations, it’s not
really true (but it might save on executable size if the compiler
employs COMDAT folding).</p>
<p>The reason is that the lambdas still depend on
<code class="sourceCode default">T</code>, since one can use it in the
lambda body.</p>
<p>This is very useful if we need to manufacture overload sets of
<em>functions with identical signatures</em>, such as needed for
type-erasure.</p>
<p>Continued example:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> qsort_compare<span class="op">(</span>T <span class="kw">const</span><span class="op">*</span>, T <span class="kw">const</span><span class="op">*)</span> <span class="op">=</span> <span class="op">+[](</span><span class="dt">void</span> <span class="kw">const</span><span class="op">*</span> x, <span class="dt">void</span> <span class="kw">const</span><span class="op">*</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="kw">static_cast</span><span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;(</span><span class="kw">static_cast</span><span class="op">&lt;</span>T <span class="kw">const</span><span class="op">*&gt;(</span>x<span class="op">)</span> <span class="op">&lt;=&gt;</span> <span class="kw">static_cast</span><span class="op">&lt;</span>T <span class="kw">const</span><span class="op">*&gt;(</span>y<span class="op">))</span>;</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">//                                  ^^                           ^^</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a><span class="co">// special-case c-strings</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> qsort_compare<span class="op">(</span><span class="dt">char</span> <span class="kw">const</span><span class="op">*</span> <span class="kw">const</span><span class="op">*</span>, <span class="dt">char</span> <span class="kw">const</span><span class="op">*</span> <span class="kw">const</span><span class="op">*)</span> <span class="op">=</span> <span class="op">+[](</span><span class="dt">void</span> <span class="kw">const</span><span class="op">*</span> x, <span class="dt">void</span> <span class="kw">const</span><span class="op">*</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <span class="kw">const</span> x_unerased <span class="op">=</span> <span class="kw">static_cast</span><span class="op">&lt;</span><span class="dt">char</span> <span class="kw">const</span><span class="op">*</span> <span class="kw">const</span><span class="op">*&gt;(</span>x<span class="op">)</span>;</span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <span class="kw">const</span> y_unerased <span class="op">=</span> <span class="kw">static_cast</span><span class="op">&lt;</span><span class="dt">char</span> <span class="kw">const</span><span class="op">*</span> <span class="kw">const</span><span class="op">*&gt;(</span>y<span class="op">)</span>;</span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> strcmp<span class="op">(*</span>x_unerased, <span class="op">*</span>y_unerased<span class="op">)</span>;</span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> use_qsort_compare<span class="op">()</span> <span class="op">{</span></span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> xs<span class="op">{</span><span class="dv">1</span>, <span class="dv">4</span>, <span class="dv">3</span>, <span class="dv">5</span>, <span class="dv">2</span><span class="op">}</span>;</span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a>  <span class="op">::</span>qsort<span class="op">(</span>xs<span class="op">.</span>data<span class="op">()</span>, xs<span class="op">.</span>size<span class="op">()</span>, <span class="kw">sizeof</span><span class="op">(</span><span class="dt">int</span><span class="op">)</span>,</span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a>          __bultin_calltarget<span class="op">(</span>qsort_compare<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>, std<span class="op">::</span>declval<span class="op">&lt;</span><span class="dt">int</span><span class="op">*&gt;()))</span>;</span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">char</span> <span class="kw">const</span><span class="op">*&gt;</span> ys<span class="op">{</span><span class="st">&quot;abcd&quot;</span>, <span class="st">&quot;abdc&quot;</span>, <span class="st">&quot;supercalifragilisticexpielidocious&quot;</span><span class="op">}</span>;</span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true" tabindex="-1"></a>  <span class="op">::</span>qsort<span class="op">(</span>ys<span class="op">.</span>data<span class="op">()</span>, ys<span class="op">.</span>size<span class="op">()</span>, <span class="kw">sizeof</span><span class="op">(</span><span class="dt">char</span> <span class="kw">const</span><span class="op">*)</span>,</span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true" tabindex="-1"></a>          __bultin_calltarget<span class="op">(</span>qsort_compare<span class="op">(</span><span class="st">&quot;&quot;</span>, <span class="st">&quot;&quot;</span><span class="op">)))</span>;</span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>So, while lambdas don’t turn out to be a useful
“template-bloat-reduction” strategy, they <em>do</em> turn out to be a
very useful strategy for type-erasure.</p>
<h2 data-number="7.2" id="expression-equivalent-for-stdstrong_order"><span class="header-section-number">7.2</span> expression-equivalent for
<code class="sourceCode default">std::strong_order</code><a href="#expression-equivalent-for-stdstrong_order" class="self-link"></a></h2>
<p><code class="sourceCode default">std::strong_order</code> needs to
effectively be implemented with an <a href="https://github.com/llvm/llvm-project/blob/4a4b8570f7c16346094c59fab1bd8debf9b177e1/libcxx/include/__compare/strong_order.h#L42"><code class="sourceCode default">if constexpr</code>
cascade</a> (link to libc++’s implementation).</p>
<p>This function template would probably be much easier to optimize for
a compiler if it were factored as follows:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">typename</span> U<span class="op">&gt;</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">consteval</span> <span class="kw">auto</span> __select_implementation<span class="op">&lt;</span>T, U<span class="op">&gt;()</span> <span class="op">{</span> <span class="co">/* figure out the correct function to call and return the pointer to it */</span> <span class="op">}</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">typename</span> U<span class="op">&gt;</span></span>
<span id="cb13-5"><a href="#cb13-5" 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>T<span class="op">&amp;&amp;</span>, U<span class="op">&amp;&amp;)</span> <span class="op">=</span> __select_implementation<span class="op">&lt;</span>T, U<span class="op">&gt;()</span>;</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> strong_order;</span></code></pre></div>
<p>Implementing it like that allows one to dispatch to functions that
don’t even take references for built-in types, eliding not just a
debug/inlining scope, but also the cleanup of references.</p>
<p>It allows one to dispatch to ABI-optimal versions of the
parameter-passing strategy. It lets us make function objects truly
invisible to debuggers.</p>
<h2 data-number="7.3" id="interactions-with-__builtin_calltarget"><span class="header-section-number">7.3</span> interactions with
<code class="sourceCode default">__builtin_calltarget()</code><a href="#interactions-with-__builtin_calltarget" class="self-link"></a></h2>
<p>While <span class="citation" data-cites="P2826R0">[<a href="#ref-P2826R0" role="doc-biblioref">P2826R0</a>]</span> makes this
paper much easier to utilize, in the presence of this paper, it becomes
truly invaluable. Computing the calltarget while having to know the
exact function pointer type of the called function is very difficult,
and needless, since the compiler is very good at resolving function
calls.</p>
<h2 data-number="7.4" id="programmable-ufcs"><span class="header-section-number">7.4</span> programmable UFCS<a href="#programmable-ufcs" class="self-link"></a></h2>
<p>If we get a new revision of <span class="citation" data-cites="P1214R0">[<a href="#ref-P1214R0" role="doc-biblioref">P1214R0</a>]</span>,
(<code class="sourceCode default">std::invoke</code>-in-the-language),
one could substitute a free function call with a
pointer-to-member-function, or vice versa, thus enabling both call
syntaxes as desired.</p>
<h2 data-number="7.5" id="the-rename-overload-set-rename-function-refactoring-becomes-possible-in-large-codebases"><span class="header-section-number">7.5</span> The “Rename Overload Set” /
“Rename Function” refactoring becomes possible in large codebases<a href="#the-rename-overload-set-rename-function-refactoring-becomes-possible-in-large-codebases" class="self-link"></a></h2>
<p>In C++, “rename function” or “rename overload set” are not
refactorings that are physically possible for large codebases without at
least temporarily risking overload resolution breakage.</p>
<p>However, with this paper, one can disentangle overload sets by
leaving removed overloads where they are, and redirecting them to the
new implementations, until they are ready to be removed.</p>
<p>(<em>Reminder:</em> conversions to reference can lose fidelity, so
trampolines in general do not work).</p>
<p>One can also just define</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>auto new_name(auto&amp;&amp;...args) </span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>    requires { __builtin_calltarget(old_name(FWD(args)...))(FWD(args)...) }</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    = __builtin_calltarget(old_name(FWD(args)...));</span></code></pre></div>
<p>and have a new name for an old overload set (as resolved at the
declaration of <code class="sourceCode default">new_name</code>).</p>
<h2 data-number="7.6" id="the-rename-function-refactoring-becomes-abi-stable"><span class="header-section-number">7.6</span> The “rename function”
refactoring becomes ABI stable<a href="#the-rename-function-refactoring-becomes-abi-stable" class="self-link"></a></h2>
<ul>
<li>we can finally move overload sets around and not break ABI in some
cases since we basically gain function aliases.</li>
</ul>
<h1 data-number="8" id="bibliography"><span class="header-section-number">8</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-P0847R7" class="csl-entry" role="doc-biblioentry">
[P0847R7] Barry Revzin, Gašper Ažman, Sy Brand, Ben Deane. 2021-07-14.
Deducing this. <a href="https://wg21.link/p0847r7"><div class="csl-block">https://wg21.link/p0847r7</div></a>
</div>
<div id="ref-P1214R0" class="csl-entry" role="doc-biblioentry">
[P1214R0] JeanHeyd Meneide. 2018-10-06. Pointer to Member Functions and
Member Objects are just Callables! <a href="https://wg21.link/p1214r0"><div class="csl-block">https://wg21.link/p1214r0</div></a>
</div>
<div id="ref-P1221R1" class="csl-entry" role="doc-biblioentry">
[P1221R1] Jason Rice. 2018-10-03. Parametric Expressions. <a href="https://wg21.link/p1221r1"><div class="csl-block">https://wg21.link/p1221r1</div></a>
</div>
<div id="ref-P2481R1" class="csl-entry" role="doc-biblioentry">
[P2481R1] Barry Revzin. 2022-07-15. Forwarding reference to specific
type/template. <a href="https://wg21.link/p2481r1"><div class="csl-block">https://wg21.link/p2481r1</div></a>
</div>
<div id="ref-P2825R0" class="csl-entry" role="doc-biblioentry">
[P2825R0] Gašper Ažman. 2023-03-15.
calltarget(unevaluated-call-expression). <a href="https://wg21.link/p2825r0"><div class="csl-block">https://wg21.link/p2825r0</div></a>
</div>
<div id="ref-P2826R0" class="csl-entry" role="doc-biblioentry">
[P2826R0] Gašper Ažman. 2023-03-15. Replacement functions. <a href="https://wg21.link/p2826r0"><div class="csl-block">https://wg21.link/p2826r0</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
