<!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="2022-07-16" />
  <title>Language Support for Customisable Functions</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">Language Support for
Customisable Functions</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2547R1</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2022-07-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>
      Evolution<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Lewis Baker (Woven-Planet)<br>&lt;<a href="mailto:lewissbaker@gmail.com" class="email">lewissbaker@gmail.com</a>&gt;<br>
      Corentin Jabot<br>&lt;<a href="mailto:corentinjabot@gmail.com" class="email">corentinjabot@gmail.com</a>&gt;<br>
      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="#abstract" id="toc-abstract"><span class="toc-section-number">1</span> Abstract<span></span></a></li>
<li><a href="#status-of-this-proposal" id="toc-status-of-this-proposal"><span class="toc-section-number">2</span> Status of this
proposal<span></span></a>
<ul>
<li><a href="#revision-1" id="toc-revision-1"><span class="toc-section-number">2.1</span> Revision 1<span></span></a></li>
</ul></li>
<li><a href="#short-description-of-the-proposed-facilities" id="toc-short-description-of-the-proposed-facilities"><span class="toc-section-number">3</span> Short description of the proposed
facilities<span></span></a></li>
<li><a href="#terminology" id="toc-terminology"><span class="toc-section-number">4</span> Terminology<span></span></a></li>
<li><a href="#examples" id="toc-examples"><span class="toc-section-number">5</span> Examples<span></span></a>
<ul>
<li><a href="#declaring-a-customisable-function" id="toc-declaring-a-customisable-function"><span class="toc-section-number">5.1</span> Declaring a customisable
function<span></span></a></li>
<li><a href="#declaring-a-customisable-function-contains-that-has-a-default-implementation" id="toc-declaring-a-customisable-function-contains-that-has-a-default-implementation"><span class="toc-section-number">5.2</span> Declaring a customisable function
<code class="sourceCode default">contains</code> that has a default
implementation<span></span></a></li>
<li><a href="#defining-a-customisation-as-hidden-friend" id="toc-defining-a-customisation-as-hidden-friend"><span class="toc-section-number">5.3</span> Defining a customisation as hidden
friend<span></span></a></li>
<li><a href="#defining-a-customisation-at-namespace-scope" id="toc-defining-a-customisation-at-namespace-scope"><span class="toc-section-number">5.4</span> Defining a customisation at
namespace scope<span></span></a></li>
<li><a href="#calling-a-customisable-function" id="toc-calling-a-customisable-function"><span class="toc-section-number">5.5</span> Calling a customisable
function<span></span></a></li>
<li><a href="#customizable-function-templates" id="toc-customizable-function-templates"><span class="toc-section-number">5.6</span> Customizable function
templates<span></span></a></li>
<li><a href="#generic-customisations" id="toc-generic-customisations"><span class="toc-section-number">5.7</span> Generic
customisations<span></span></a></li>
</ul></li>
<li><a href="#background" id="toc-background"><span class="toc-section-number">6</span> Background<span></span></a></li>
<li><a href="#motivation" id="toc-motivation"><span class="toc-section-number">7</span> Motivation<span></span></a>
<ul>
<li><a href="#the-problem-with-member-functions" id="toc-the-problem-with-member-functions"><span class="toc-section-number">7.1</span> The problem with
member-functions<span></span></a>
<ul>
<li><a href="#member-functions-all-live-in-a-single-global-namespace" id="toc-member-functions-all-live-in-a-single-global-namespace"><span class="toc-section-number">7.1.1</span> Member functions all live in a
single global “namespace”<span></span></a></li>
<li><a href="#we-cannot-customise-different-member-names-generically" id="toc-we-cannot-customise-different-member-names-generically"><span class="toc-section-number">7.1.2</span> We cannot customise different
member names generically<span></span></a></li>
<li><a href="#customisation-point-member-functions-cannot-be-passed-to-higher-order-functions" id="toc-customisation-point-member-functions-cannot-be-passed-to-higher-order-functions"><span class="toc-section-number">7.1.3</span> Customisation-point member
functions cannot be passed to higher-order
functions<span></span></a></li>
<li><a href="#implementing-a-concept-requires-modification-of-the-type" id="toc-implementing-a-concept-requires-modification-of-the-type"><span class="toc-section-number">7.1.4</span> Implementing a concept requires
modification of the type<span></span></a></li>
</ul></li>
<li><a href="#problems-with-raw-argument-dependent-lookup-adl" id="toc-problems-with-raw-argument-dependent-lookup-adl"><span class="toc-section-number">7.2</span> Problems with raw
argument-dependent lookup (ADL)<span></span></a>
<ul>
<li><a href="#adl-function-names-all-share-a-single-global-namespace" id="toc-adl-function-names-all-share-a-single-global-namespace"><span class="toc-section-number">7.2.1</span> ADL function names all share a
single global namespace<span></span></a></li>
<li><a href="#inability-to-customise-different-adl-names-generically" id="toc-inability-to-customise-different-adl-names-generically"><span class="toc-section-number">7.2.2</span> Inability to customise different
ADL names generically<span></span></a></li>
<li><a href="#inability-to-pass-a-customisation-point-as-an-argument-ta-higher-order-function" id="toc-inability-to-pass-a-customisation-point-as-an-argument-ta-higher-order-function"><span class="toc-section-number">7.2.3</span> Inability to pass a
customisation-point as an argument ta higher-order
function<span></span></a></li>
<li><a href="#need-for-two-step-usingcall-to-call-functions-with-default-implementations-e.g.-swap" id="toc-need-for-two-step-usingcall-to-call-functions-with-default-implementations-e.g.-swap"><span class="toc-section-number">7.2.4</span> Need for two-step using/call to
call functions with default implementations
(e.g. <code class="sourceCode default">swap()</code>)<span></span></a></li>
<li><a href="#adl-is-location-dependent" id="toc-adl-is-location-dependent"><span class="toc-section-number">7.2.5</span> ADL is
location-dependent<span></span></a></li>
</ul></li>
<li><a href="#the-problem-with-cpos-defined-in-ranges" id="toc-the-problem-with-cpos-defined-in-ranges"><span class="toc-section-number">7.3</span> The problem with CPOs defined in
ranges<span></span></a>
<ul>
<li><a href="#still-relies-on-adl-for-customisation---single-global-namespace." id="toc-still-relies-on-adl-for-customisation---single-global-namespace."><span class="toc-section-number">7.3.1</span> Still relies on ADL for
customisation -&gt; Single global namespace.<span></span></a></li>
<li><a href="#unable-to-generically-customise-and-forward-implementations-in-wrapper-types." id="toc-unable-to-generically-customise-and-forward-implementations-in-wrapper-types."><span class="toc-section-number">7.3.2</span> Unable to generically customise
and forward implementations in wrapper types.<span></span></a></li>
<li><a href="#lots-of-boiler-plate-needed-to-define-a-cpo" id="toc-lots-of-boiler-plate-needed-to-define-a-cpo"><span class="toc-section-number">7.3.3</span> Lots of boiler-plate needed to
define a CPO<span></span></a></li>
<li><a href="#the-extra-layer-of-indirection-through-the-operator-overload-inhibits-copy-elision" id="toc-the-extra-layer-of-indirection-through-the-operator-overload-inhibits-copy-elision"><span class="toc-section-number">7.3.4</span> The extra layer of indirection
through the <code class="sourceCode default">operator()</code> overload
inhibits copy-elision<span></span></a></li>
</ul></li>
<li><a href="#the-problem-with-tag_invoke-cpos" id="toc-the-problem-with-tag_invoke-cpos"><span class="toc-section-number">7.4</span> The problem with
<code class="sourceCode default">tag_invoke</code> CPOs<span></span></a>
<ul>
<li><a href="#still-lots-of-boiler-plate-to-define-a-new-cpo" id="toc-still-lots-of-boiler-plate-to-define-a-new-cpo"><span class="toc-section-number">7.4.1</span> Still lots of boiler-plate to
define a new CPO<span></span></a></li>
<li><a href="#syntax-for-customisations-is-more-cumbersome" id="toc-syntax-for-customisations-is-more-cumbersome"><span class="toc-section-number">7.4.2</span> Syntax for customisations is
more cumbersome<span></span></a></li>
<li><a href="#potential-for-very-large-overload-set" id="toc-potential-for-very-large-overload-set"><span class="toc-section-number">7.4.3</span> Potential for very large
overload-set<span></span></a></li>
<li><a href="#forwarding-layers-inhibit-copy-elision" id="toc-forwarding-layers-inhibit-copy-elision"><span class="toc-section-number">7.4.4</span> Forwarding layers inhibit
copy-elision<span></span></a></li>
<li><a href="#compile-errors-are-difficult-to-diagnose" id="toc-compile-errors-are-difficult-to-diagnose"><span class="toc-section-number">7.4.5</span> Compile Errors are difficult to
diagnose<span></span></a></li>
</ul></li>
</ul></li>
<li><a href="#use-cases" id="toc-use-cases"><span class="toc-section-number">8</span> Use-cases<span></span></a>
<ul>
<li><a href="#basis-operations" id="toc-basis-operations"><span class="toc-section-number">8.1</span> Basis
operations<span></span></a></li>
<li><a href="#customisable-algorithms" id="toc-customisable-algorithms"><span class="toc-section-number">8.2</span> Customisable
algorithms<span></span></a></li>
<li><a href="#wrapper-types" id="toc-wrapper-types"><span class="toc-section-number">8.3</span> Wrapper
types<span></span></a></li>
</ul></li>
<li><a href="#design" id="toc-design"><span class="toc-section-number">9</span> Design<span></span></a>
<ul>
<li><a href="#declaring-customisable-functions" id="toc-declaring-customisable-functions"><span class="toc-section-number">9.1</span> Declaring customisable
functions<span></span></a></li>
<li><a href="#customisable-function-objects" id="toc-customisable-function-objects"><span class="toc-section-number">9.2</span> Customisable function
objects<span></span></a></li>
<li><a href="#declaring-customizations-and-default-implementations" id="toc-declaring-customizations-and-default-implementations"><span class="toc-section-number">9.3</span> Declaring Customizations and
Default Implementations<span></span></a>
<ul>
<li><a href="#declaring-default-implementations" id="toc-declaring-default-implementations"><span class="toc-section-number">9.3.1</span> Declaring default
implementations<span></span></a></li>
<li><a href="#multiple-default-overloads-can-be-defined." id="toc-multiple-default-overloads-can-be-defined."><span class="toc-section-number">9.3.2</span> Multiple default overloads can
be defined.<span></span></a></li>
<li><a href="#declaring-default-implementations-in-other-namespaces" id="toc-declaring-default-implementations-in-other-namespaces"><span class="toc-section-number">9.3.3</span> Declaring default
implementations in other namespaces<span></span></a></li>
<li><a href="#why-do-we-need-defaults-to-be-looked-up-as-fallback" id="toc-why-do-we-need-defaults-to-be-looked-up-as-fallback"><span class="toc-section-number">9.3.4</span> Why do we need defaults to be
looked up as fallback?<span></span></a></li>
<li><a href="#calling-an-override-with-argument-conversion-is-preferred-over-calling-a-default" id="toc-calling-an-override-with-argument-conversion-is-preferred-over-calling-a-default"><span class="toc-section-number">9.3.5</span> Calling an override with
argument conversion is preferred over calling a
default<span></span></a></li>
</ul></li>
<li><a href="#declaring-multiple-forms-of-a-customisable-function" id="toc-declaring-multiple-forms-of-a-customisable-function"><span class="toc-section-number">9.4</span> Declaring multiple forms of a
customisable function<span></span></a></li>
<li><a href="#customising-customisable-functions" id="toc-customising-customisable-functions"><span class="toc-section-number">9.5</span> Customising customisable
functions<span></span></a></li>
<li><a href="#customisable-functions-with-explicit-template-arguments" id="toc-customisable-functions-with-explicit-template-arguments"><span class="toc-section-number">9.6</span> Customisable functions with
explicit template arguments<span></span></a></li>
<li><a href="#generic-forwarding" id="toc-generic-forwarding"><span class="toc-section-number">9.7</span> Generic
forwarding<span></span></a></li>
<li><a href="#overload-resolution-for-customisable-function-calls" id="toc-overload-resolution-for-customisable-function-calls"><span class="toc-section-number">9.8</span> Overload resolution for
customisable function calls<span></span></a>
<ul>
<li><a href="#validating-customisations" id="toc-validating-customisations"><span class="toc-section-number">9.8.1</span> Validating
customisations<span></span></a></li>
<li><a href="#noexcept-specifications" id="toc-noexcept-specifications"><span class="toc-section-number">9.8.2</span> Noexcept
specifications<span></span></a></li>
<li><a href="#constraining-parameter-types" id="toc-constraining-parameter-types"><span class="toc-section-number">9.8.3</span> Constraining
parameter-types<span></span></a></li>
<li><a href="#constraining-return-types" id="toc-constraining-return-types"><span class="toc-section-number">9.8.4</span> Constraining return
types<span></span></a></li>
</ul></li>
</ul></li>
<li><a href="#additional-design-discussions" id="toc-additional-design-discussions"><span class="toc-section-number">10</span> Additional Design
Discussions<span></span></a>
<ul>
<li><a href="#syntax" id="toc-syntax"><span class="toc-section-number">10.1</span> Syntax<span></span></a></li>
<li><a href="#default-arguments" id="toc-default-arguments"><span class="toc-section-number">10.2</span> Default
arguments<span></span></a></li>
<li><a href="#attributes" id="toc-attributes"><span class="toc-section-number">10.3</span> Attributes<span></span></a></li>
<li><a href="#controlling-the-set-of-associated-namespaces" id="toc-controlling-the-set-of-associated-namespaces"><span class="toc-section-number">10.4</span> Controlling the set of associated
namespaces<span></span></a></li>
<li><a href="#comparison-to-rust-traits" id="toc-comparison-to-rust-traits"><span class="toc-section-number">10.5</span> Comparison to Rust
Traits<span></span></a></li>
<li><a href="#redefining-existing-customisation-points-in-terms-of-this-solution" id="toc-redefining-existing-customisation-points-in-terms-of-this-solution"><span class="toc-section-number">10.6</span> Redefining existing customisation
points in terms of this solution<span></span></a></li>
</ul></li>
<li><a href="#implementation" id="toc-implementation"><span class="toc-section-number">11</span>
Implementation<span></span></a></li>
<li><a href="#acknowledgements" id="toc-acknowledgements"><span class="toc-section-number">12</span>
Acknowledgements<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">13</span> References<span></span></a></li>
</ul>
</div>
<!-- The formatting is one sentence per line to make diffs intelligible -->
<h1 data-number="1" id="abstract"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p>This paper proposes a language mechanism for defining customisable
namespace-scope functions as a solution to the problems posed by <span class="citation" data-cites="P2279R0">[<a href="#ref-P2279R0" role="doc-biblioref">P2279R0</a>]</span> “We need a language mechanism
for customisation points”.</p>
<h1 data-number="2" id="status-of-this-proposal"><span class="header-section-number">2</span> Status of this proposal<a href="#status-of-this-proposal" class="self-link"></a></h1>
<p>This work is a preliminary initial design. We intend this proposal to
replace the use of <code class="sourceCode default">tag_invoke</code> in
<span class="citation" data-cites="P2300R5">[<a href="#ref-P2300R5" role="doc-biblioref">P2300R5</a>]</span> in the C++26 time frame. We
need directional guidance from EWG and LEWG to refine the design over
the next few months.</p>
<h2 data-number="2.1" id="revision-1"><span class="header-section-number">2.1</span> Revision 1<a href="#revision-1" class="self-link"></a></h2>
<ul>
<li>New syntax to introduce customisable functions, using a contextual
keyword, <code class="sourceCode default">customisable</code>, rather
than <code class="sourceCode default">virtual</code> and
<code class="sourceCode default">= 0</code>. This is to address initial
feedback that re-using <code class="sourceCode default">virtual</code>
for a feature unrelated to dynamic polymorphism was, at best,
confusing.</li>
<li>Default implementations can no longer be defined together with the
declaration of the customisable function prototype. The treatment of a
function parameters and template argument deduction between the two is
different enough that it was thought to be confusing to allow them to be
the same declaration.</li>
<li>Add support for the <code class="sourceCode default">final</code>
keyword to annotate a function that may not be overridden.</li>
<li>Change overload resolution of customisable functions so it always
considers the associated entities/namespaces of the CFO itself. This
allows generic overrides (that customise for a whole concept instead of
a particular type) to be defined in a place it is guaranteed to be
found. It also allows overloads for a template customisable function to
be found in namespaces of the explicit type template arguments to the
CFO.</li>
<li>Add more examples of template customisable functions and generic
customisations.</li>
<li>Improve terminology consistency - use “customisable functions” and
CFOs (customisable function objects) instead of CPOs
(customisation-point objects)</li>
</ul>
<h1 data-number="3" id="short-description-of-the-proposed-facilities"><span class="header-section-number">3</span> Short description of the proposed
facilities<a href="#short-description-of-the-proposed-facilities" class="self-link"></a></h1>
<p>This proposal seeks to improve over existing customisation-point
mechanisms in a number of ways:</p>
<ul>
<li>Allows customisation-point names to be namespace-scoped rather than
names being reserved globally.</li>
<li>Allows generic forwarding of customisable functions through
wrapper-types, including generic type-erasing wrappers (like
<code class="sourceCode default">unifex::any_object</code>) and adapters
that customise some operations and pass through others.</li>
<li>Concise syntax for defining customisable function-objects and adding
customisations for particular types.</li>
<li>Support for copy-elision of arguments passed by-value to
customisation-points.</li>
<li>Far better compile times compared to the
<code class="sourceCode default">tag_invoke</code> mechanism (avoids 3
layers of template instantiations and cuts down on SFINAE required to
separate implementation functions)</li>
<li>Far better error messages compared to the
<code class="sourceCode default">tag_invoke</code> mechanism
(<code class="sourceCode default">tag_invoke</code> does not distinguish
between different customisation-point functions and sometimes results in
reporting hundreds of unrelated overloads)</li>
</ul>
<p>This proposal improves on the semantics of the
<code class="sourceCode default">tag_invoke</code> proposal <span class="citation" data-cites="P1895R0">[<a href="#ref-P1895R0" role="doc-biblioref">P1895R0</a>]</span>, keeping namespace-scoped
customisation-points and generic customisation / forwarding, while
providing a terser and cleaner syntax accessible to less experienced
programmers.</p>
<p>The proposed syntax introduces use of:</p>
<ul>
<li>A new <em>virt-specifier</em>
<code class="sourceCode cpp">customisable</code> for namespace-scope
functions as a way of declaring that the function declaration is a
customisation-point.</li>
<li>The <em>virt-specifier</em>
<code class="sourceCode cpp"><span class="kw">override</span></code> for
customisations of a customisable function-object.</li>
<li>The
<code class="sourceCode cpp"><span class="cf">default</span></code>
keyword as an additional <em>virt-specifier</em> annotation for a
customisable function’s default implementation.</li>
<li>The <em>virt-specifier</em>
<code class="sourceCode cpp"><span class="kw">final</span></code> to
create a non-customisable function-object.</li>
<li>A syntax for declaring customisations of a specific customisable
function-object by using the fully-scoped name of the function-object as
the function-name.</li>
<li>The ability to deduce the customisable function object for the
purposes of generic forwarding and generically customising multiple
customisation-points.</li>
</ul>
<h1 data-number="4" id="terminology"><span class="header-section-number">4</span> Terminology<a href="#terminology" class="self-link"></a></h1>
<p>This paper introduces the following terms:</p>
<ul>
<li><p>A function declaration for a <em>customisable function</em> is a
<strong>customisable function prototype</strong>:</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">void</span> foo<span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;)</span> customisable;</span></code></pre></div></li>
<li><p>The set of <em>customisable function prototypes</em> naming the
same entity represent a <strong>customisable function</strong>.</p></li>
<li><p>A <em>customisable function</em> introduces a
<strong>customisable Function Object</strong> <strong>(CFO)</strong> in
the scope it is declared.</p></li>
<li><p>The set of functions or template functions with the
<code class="sourceCode default">override</code> keyword are
<strong>customisations</strong> of the corresponding customisable
function. They form the <strong>customisation overload
set</strong>.</p></li>
<li><p>The set of functions or template functions with the
<code class="sourceCode default">default</code> keyword are
<strong>default implementations</strong> of the corresponding
customisable function. They form the <strong>default overload
set</strong> for that customisable function object.</p></li>
<li><p>A declaration of a customisable function with explicit template
parameters in the function declarator is a <strong>customisable function
template</strong>. e.g. <code class="sourceCode default">cpp       template &lt;typename T, typename Object&gt;       T* any_cast&lt;T&gt;(Object&amp;&amp; object) customisable;</code></p></li>
<li><p>A declaration of namespace-scope function of the form</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">template</span> <span class="op">&lt;</span><span class="kw">auto</span> func, <span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">auto</span> func<span class="op">(</span>T<span class="op">&amp;&amp;</span> object<span class="op">)</span> <span class="kw">override</span>;</span></code></pre></div>
<p>declares a <strong>generic customisation</strong>.</p></li>
</ul>
<h1 data-number="5" id="examples"><span class="header-section-number">5</span> Examples<a href="#examples" class="self-link"></a></h1>
<h2 data-number="5.1" id="declaring-a-customisable-function"><span class="header-section-number">5.1</span> Declaring a customisable
function<a href="#declaring-a-customisable-function" class="self-link"></a></h2>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>sender S, receiver R<span class="op">&gt;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>  operation_state <span class="kw">auto</span> <span class="fu">connect</span><span class="op">(</span>S s, R r<span class="op">)</span> <span class="hl" style="background-color: #ffff88">customisable</span>;</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="5.2" id="declaring-a-customisable-function-contains-that-has-a-default-implementation"><span class="header-section-number">5.2</span> Declaring a customisable
function <code class="sourceCode default">contains</code> that has a
default implementation<a href="#declaring-a-customisable-function-contains-that-has-a-default-implementation" 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">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>input_range R, <span class="kw">typename</span> Value<span class="op">&gt;</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> equality_comparable_with<span class="op">&lt;</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, Value<span class="op">&gt;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> contains<span class="op">(</span>R range, Value v<span class="op">)</span> <span class="hl" style="background-color: #ffff88">customisable</span>;</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>input_range R, <span class="kw">typename</span> Value<span class="op">&gt;</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> equality_comparable_with<span class="op">&lt;</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, Value<span class="op">&gt;</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> contains<span class="op">(</span>R<span class="op">&amp;&amp;</span> range, <span class="kw">const</span> Value<span class="op">&amp;</span> v<span class="op">)</span> <span class="hl" style="background-color: #ffff88">default</span> <span class="op">{</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> x <span class="op">:</span> range<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>x <span class="op">==</span> v<span class="op">)</span> <span class="cf">return</span> <span class="kw">true</span>;</span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">false</span>;</span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="5.3" id="defining-a-customisation-as-hidden-friend"><span class="header-section-number">5.3</span> Defining a customisation as
hidden friend<a href="#defining-a-customisation-as-hidden-friend" class="self-link"></a></h2>
<p>As an example we define a customisation of the above customisable
function contains (as a hidden friend) for
<code class="sourceCode default">std::set</code> using the
<code class="sourceCode default">override</code> keyword. Note that the
name of the customised function is qualified.</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">namespace</span> std <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Key, <span class="kw">class</span> Compare, <span class="kw">class</span> Allocator<span class="op">&gt;</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> set <span class="op">{</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">private</span><span class="op">:</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> V<span class="op">&gt;</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span><span class="kw">const</span> set<span class="op">&amp;</span> s, <span class="kw">const</span> V<span class="op">&amp;</span> v<span class="op">)</span> <span class="op">{</span> s<span class="op">.</span>contains<span class="op">(</span>v<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="dt">bool</span> <span class="hl" style="background-color: #ffff88">ranges::contains</span><span class="op">(</span><span class="kw">const</span> set<span class="op">&amp;</span> s, <span class="kw">const</span> V<span class="op">&amp;</span> v<span class="op">)</span> <span class="hl" style="background-color: #ffff88">override</span> <span class="op">{</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> s<span class="op">.</span>contains<span class="op">(</span>v<span class="op">)</span>;</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="5.4" id="defining-a-customisation-at-namespace-scope"><span class="header-section-number">5.4</span> Defining a customisation at
namespace scope<a href="#defining-a-customisation-at-namespace-scope" class="self-link"></a></h2>
<p>Alternatively, we can define a customisation at namespace scope using
the <code class="sourceCode default">override</code> keyword. This can
be useful when implicit conversions should be considered.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Key, <span class="kw">class</span> Hash, <span class="kw">class</span> KeyEq, <span class="kw">class</span> Allocator<span class="op">&gt;</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> unordered_set <span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Defined outside class definition.</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Key, <span class="kw">class</span> Hash, <span class="kw">class</span> Eq, <span class="kw">class</span> Allocator, <span class="kw">class</span> Value<span class="op">&gt;</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span><span class="kw">const</span> unordered_set<span class="op">&lt;</span>Key,Hash,Eq, Allocator<span class="op">&gt;&amp;</span> s, <span class="kw">const</span> Value<span class="op">&amp;</span> v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>      s<span class="op">.</span>contains<span class="op">(</span>v<span class="op">)</span>;</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> <span class="hl" style="background-color: #ffff88">ranges::contains</span><span class="op">(</span><span class="kw">const</span> unordered_set<span class="op">&lt;</span>Key,Hash,Eq,Allocator<span class="op">&gt;&amp;</span> s,</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>                        <span class="kw">const</span> Value<span class="op">&amp;</span> v<span class="op">)</span> <span class="hl" style="background-color: #ffff88">override</span> <span class="op">{</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> s<span class="op">.</span>contains<span class="op">(</span>v<span class="op">)</span>;</span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="5.5" id="calling-a-customisable-function"><span class="header-section-number">5.5</span> Calling a customisable
function<a href="#calling-a-customisable-function" class="self-link"></a></h2>
<p>When calling a customisable function there is no need for the
<em>two-step <code class="sourceCode default">using</code></em>. They
are safe to call fully qualified.</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">void</span> example<span class="op">()</span> <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>set<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> s <span class="op">=</span> <span class="op">{</span> <span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span> <span class="op">}</span>;</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> x <span class="op">:</span> <span class="op">{</span> <span class="dv">2</span>, <span class="dv">5</span> <span class="op">})</span> <span class="op">{</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span><span class="hl" style="background-color: #ffff88">std::ranges::contains</span><span class="op">(</span>s, x<span class="op">))</span> <span class="co">// calls std::set customisation</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>      std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> x <span class="op">&lt;&lt;</span> <span class="st">&quot; Found!</span><span class="sc">\n</span><span class="st">&quot;</span>;</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Note that, as with C++20
<code class="sourceCode default">std::ranges</code> CPOs,
customisable-functions cannot be found by ADL when resolving unqualified
call expressions.</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> lookup_example<span class="op">()</span> <span class="op">{</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>set<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> s <span class="op">=</span> <span class="op">{</span> <span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span> <span class="op">}</span>;</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>  contains<span class="op">(</span>s, <span class="dv">2</span><span class="op">)</span>; <span class="co">// normal ADL lookup for function declarations.</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>                  <span class="co">// <span class="hl" style="background-color: #ffff88">will not find
std::ranges::contains</span>.</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> std<span class="op">::</span>ranges<span class="op">::</span>contains;</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>  contains<span class="op">(</span>s, <span class="dv">2</span><span class="op">)</span>; <span class="co">// name lookup for &#39;contains&#39; finds the std::ranges::contains</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>                  <span class="co">// &quot;customisable function&quot;, and then follows overload resolution</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>                  <span class="co">// rules of customisable functions instead</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>                  <span class="co">// of [basic.lookup.argdep].</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>A customisable function prototype creates a name that identifies an
empty object that can be passed around by value. This object represents
the overload set of all overloads of that customisable function, and so
can be passed to higher-order functions without having to wrap it in a
lambda.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> frobnicate<span class="op">(</span>T<span class="op">&amp;</span> x<span class="op">)</span> customisable;</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">struct</span> X <span class="op">{</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">void</span> frobnicate<span class="op">(</span>X<span class="op">&amp;</span> x<span class="op">)</span> <span class="kw">override</span> <span class="op">{</span> <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="op">}</span>;</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> example<span class="op">()</span> <span class="op">{</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector<span class="op">&lt;</span>X<span class="op">&gt;</span> xs <span class="op">=</span> <span class="op">...</span>;               <span class="co">// &#39;frobnicate&#39; is a callable-object that</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>ranges<span class="op">::</span>for_each<span class="op">(</span>xs, <span class="hl" style="background-color: #ffff88">frobnicate</span><span class="op">)</span>; <span class="co">// can be passed to a higher-order function.</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="5.6" id="customizable-function-templates"><span class="header-section-number">5.6</span> Customizable function
templates<a href="#customizable-function-templates" class="self-link"></a></h2>
<p>A customisable function template is declared as a customisable
function where the function declarator has an explicit template
parameter list.</p>
<p>Calling the customisable function requires explicitly passing the
template parameters and each specialisation of the customisable function
results in a different customisation point object type.</p>
<p><em>Note:</em> the ability to declare multiple variable templates of
the same name but different parameter kinds is novel.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// get for types</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="kw">typename</span> Obj<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> <span class="hl" style="background-color: #ffff88">get<T></span><span class="op">(</span>Obj<span class="op">&amp;&amp;</span> obj<span class="op">)</span> customisable;</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">// get for numeric indices</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="dt">size_t</span> N, <span class="kw">typename</span> Obj<span class="op">&gt;</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <span class="hl" style="background-color: #ffff88">get<N></span><span class="op">(</span>Obj<span class="op">&amp;&amp;</span> obj<span class="op">)</span> customisable;</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// non-template get() that deduces numeric indices</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">// callable without explicit template args</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="dt">size_t</span> N, <span class="kw">typename</span> Obj<span class="op">&gt;</span></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="op">(</span>Obj<span class="op">&amp;&amp;</span> obj<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>      get<span class="op">&lt;</span>N<span class="op">&gt;(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>Obj<span class="op">&gt;(</span>obj<span class="op">))</span>;</span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <span class="hl" style="background-color: #ffff88">get</span><span class="op">(</span>Obj<span class="op">&amp;&amp;</span> obj, std<span class="op">::</span>integral_constant<span class="op">&lt;</span><span class="dt">size_t</span>, N<span class="op">&gt;)</span> <span class="kw">final</span> <span class="op">{</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>       <span class="cf">return</span> get<span class="op">&lt;</span>N<span class="op">&gt;(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>Obj<span class="op">&gt;(</span>obj<span class="op">))</span>;</span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> my_tuple <span class="op">{</span></span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> x;</span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true" tabindex="-1"></a>  <span class="dt">float</span> y;</span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">int</span><span class="op">&amp;</span>   std<span class="op">::</span>get<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;(</span>my_tuple<span class="op">&amp;</span> self<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">override</span> <span class="op">{</span> <span class="cf">return</span> self<span class="op">.</span>x; <span class="op">}</span></span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">float</span><span class="op">&amp;</span> std<span class="op">::</span>get<span class="op">&lt;</span><span class="dt">float</span><span class="op">&gt;(</span>my_tuple<span class="op">&amp;</span> self<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">override</span> <span class="op">{</span> <span class="cf">return</span> self<span class="op">.</span>y; <span class="op">}</span></span>
<span id="cb10-28"><a href="#cb10-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-29"><a href="#cb10-29" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">int</span><span class="op">&amp;</span>   std<span class="op">::</span>get<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;(</span>my_tuple<span class="op">&amp;</span> self<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">override</span> <span class="op">{</span> <span class="cf">return</span> self<span class="op">.</span>x; <span class="op">}</span></span>
<span id="cb10-30"><a href="#cb10-30" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">float</span><span class="op">&amp;</span> std<span class="op">::</span>get<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;(</span>my_tuple<span class="op">&amp;</span> self<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">override</span> <span class="op">{</span> <span class="cf">return</span> self<span class="op">.</span>y; <span class="op">}</span></span>
<span id="cb10-31"><a href="#cb10-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>A customisable function template can also be customised generically
by providing a template parameter as the template argument to the
customisable function’s template argument:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, std<span class="op">::</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> array <span class="op">{</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>  T data<span class="op">[</span>N<span class="op">]</span>;</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Use a function-template parameter to deduce the CFO parameter</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>std<span class="op">::</span><span class="dt">size_t</span> Idx<span class="op">&gt;</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="op">(</span>Idx <span class="op">&lt;</span> N<span class="op">)</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> T<span class="op">&amp;</span> std<span class="op">::</span>get<span class="op">&lt;</span>Idx<span class="op">&gt;(</span>array<span class="op">&amp;</span> self<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">override</span> <span class="op">{</span> <span class="cf">return</span> self<span class="op">.</span>data<span class="op">[</span>Idx<span class="op">]</span>; <span class="op">}</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> First, <span class="kw">typename</span> Second<span class="op">&gt;</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> pair <span class="op">{</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>  First first;</span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>  Second second;</span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Use a class-template parameter to constrain the CFO parameter</span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> First<span class="op">&amp;</span> std<span class="op">::</span>get<span class="op">&lt;</span>First<span class="op">&gt;(</span>pair<span class="op">&amp;</span> self<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">override</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <span class="op">(!</span>std<span class="op">::</span>same_as<span class="op">&lt;</span>First, Second<span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> self<span class="op">.</span>first;</span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Usage of this customisable function template works as follows:</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">void</span> example<span class="op">()</span> <span class="op">{</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>  my_tuple t <span class="op">=</span> <span class="op">{</span><span class="dv">42</span>, <span class="fl">0.0</span><span class="bu">f</span><span class="op">}</span>;</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span><span class="op">&amp;</span> x1 <span class="op">=</span> std<span class="op">::</span>get<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;(</span>t<span class="op">)</span>;</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">float</span><span class="op">&amp;</span> y1 <span class="op">=</span> std<span class="op">::</span>get<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;(</span>t<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 class="dt">int</span><span class="op">&amp;</span> x2 <span class="op">=</span> std<span class="op">::</span>get<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;(</span>t<span class="op">)</span>;</span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">float</span><span class="op">&amp;</span> y2 <span class="op">=</span> std<span class="op">::</span>get<span class="op">&lt;</span><span class="dt">float</span><span class="op">&gt;(</span>t<span class="op">)</span>;</span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span><span class="op">&amp;</span> x3 <span class="op">=</span> std<span class="op">::</span>get<span class="op">(</span>t, std<span class="op">::</span>integral_constant<span class="op">&lt;</span>std<span class="op">::</span><span class="dt">size_t</span>, <span class="dv">0</span><span class="op">&gt;{})</span>;</span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>  <span class="dt">float</span><span class="op">&amp;</span> y3 <span class="op">=</span> std<span class="op">::</span>get<span class="op">(</span>t, std<span class="op">::</span>integral_constant<span class="op">&lt;</span>std<span class="op">::</span><span class="dt">size_t</span>, <span class="dv">1</span><span class="op">&gt;{})</span>;</span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><em>Note:</em> unlike variables and variable templates, CFOs are not
less-than-comparable, which means
<code class="sourceCode default">cfo-name&lt;token&gt;</code> can be
unambiguously parsed as a template name and not a comparison, similar to
function templates. This allows CFOs and CFO-templates to coexist in the
same namespace.</p>
<h2 data-number="5.7" id="generic-customisations"><span class="header-section-number">5.7</span> Generic customisations<a href="#generic-customisations" class="self-link"></a></h2>
<p>A type can customise a set of customisable-functions generically by
defining namespace-scope <strong>generic customisation</strong>.</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Inner<span class="op">&gt;</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> unstoppable_receiver_wrapper <span class="op">{</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>  Inner inner;</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Customise get_stop_token() to return never_stop_token.</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="kw">constexpr</span> never_stop_token std<span class="op">::</span>execution<span class="op">::</span>get_stop_token<span class="op">(</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>      <span class="kw">const</span> unstoppable_receiver_wrapper<span class="op">&amp;</span> self<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">{}</span>;</span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Generically customise all other queries to forward them to the wrapped receiver.</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="hl" style="background-color: #ffff88">auto func</span><span class="op">&gt;</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span><span class="kw">const</span> Inner<span class="op">&amp;</span> inner<span class="op">)</span> <span class="op">{</span> func<span class="op">(</span>inner<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="hl" style="background-color: #ffff88">func</span><span class="op">(</span><span class="kw">const</span> unstoppable_receiver_wrapper<span class="op">&amp;</span> self<span class="op">)</span></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>      <span class="kw">noexcept</span><span class="op">(</span><span class="kw">noexcept</span><span class="op">(</span>func<span class="op">(</span>self<span class="op">.</span>inner<span class="op">)))</span> <span class="hl" style="background-color: #ffff88">override</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a>      <span class="op">-&gt;</span> <span class="kw">decltype</span><span class="op">(</span>func<span class="op">(</span>self<span class="op">.</span>inner<span class="op">))</span> <span class="op">{</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="hl" style="background-color: #ffff88">func</span><span class="op">(</span>self<span class="op">.</span>inner<span class="op">)</span>;</span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ... etc. for forwarding set_value/set_error/set_done customisable functions</span></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>This can be made even more generic by accepting a first parameter
that accepts an arbitrary set of parameters and different
value-categories of the first argument:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Obj, <span class="kw">typename</span> Member<span class="op">&gt;</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> member_t <span class="op">=</span> <span class="kw">decltype</span><span class="op">((</span>std<span class="op">::</span>declval<span class="op">&lt;</span>Obj<span class="op">&gt;().*</span>std<span class="op">::</span>declval<span class="op">&lt;</span>Member std<span class="op">::</span>remove_cvref_t<span class="op">&lt;</span>Obj<span class="op">&gt;::*&gt;()))</span>;</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Inner<span class="op">&gt;</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> logging_wrapper <span class="op">{</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>  Inner inner;</span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Forward calls with the first argument as &#39;logging_wrapper&#39; to the inner object if callable</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// on the inner object after printing out the name of the CPO that is being called.</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="hl" style="background-color: #ffff88">auto func</span>, <span class="kw">typename</span> Self, <span class="kw">typename</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</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>Self<span class="op">&gt;</span>, logging_wrapper<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>             std<span class="op">::</span>invocable<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>func<span class="op">)</span>, member_t<span class="op">&lt;</span>Self, Inner<span class="op">&gt;</span>, Args<span class="op">...&gt;</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <span class="hl" style="background-color: #ffff88">func</span><span class="op">(</span>Self<span class="op">&amp;&amp;</span> self, Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(</span><span class="co">/* ... */</span><span class="op">)</span> <span class="hl" style="background-color: #ffff88">override</span> <span class="op">{</span></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;Calling {}</span><span class="sc">\n</span><span class="st">&quot;</span>, <span class="kw">typeid</span><span class="op">(</span>func<span class="op">).</span>name<span class="op">())</span>;</span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="hl" style="background-color: #ffff88">func</span><span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>Self<span class="op">&gt;(</span>self<span class="op">).</span>inner, std<span class="op">::</span>forward<span class="op">&lt;</span>Args<span class="op">&gt;(</span>args<span class="op">)...)</span>;</span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>A single <code class="sourceCode default">override</code> declaration
is able to provide an overload for an open set of customisable functions
by allowing the non-type template parameter
<code class="sourceCode default">func</code> to be deduced to an
instance of whichever customisable function the compiler is currently
performing overload resolution for.</p>
<h1 data-number="6" id="background"><span class="header-section-number">6</span> Background<a href="#background" class="self-link"></a></h1>
<p>One of the main purposes of defining customisation points is to
enable the ability to program generically. By defining a common set of
operations that many different types can customize with their own
type-specific behaviour we can write generic algorithms defined in terms
of that common set of operations, and have them work on many different
types. This is the cornerstone of generic programming.</p>
<p>The state of the art for defining customisable functions has evolved
over time.</p>
<p>Early customisation points such as
<code class="sourceCode default">std::swap()</code> make use of raw
argument-dependent-lookup (ADL) but require a two-step process to call
them
(<code class="sourceCode default">using std::swap; swap(a, b);</code>)
to ensure the customisation is found if one exists but with a fallback
to a default implementation. It is a common programmer error to forget
to do this two-step process and just call
<code class="sourceCode default">std::swap(a, b)</code> which results in
always calling the default implementation. Raw ADL calls can also give
different results depending on the context in which you call them, which
can lead to some hard to track down bugs.</p>
<p>The <code class="sourceCode default">std::ranges</code>
customisation-point objects added in C++20 improved on this by
encapsulating the two-step ADL call into a function object, making the
customisation point easier to call correctly, but also making it much
more complex to define a customisation point, as one needs to define two
nested namespaces, poison pill declarations,
<code class="sourceCode default">inline constexpr</code> objects, and a
class with a constrained
<code class="sourceCode default">operator()</code> overload.</p>
<p>The <code class="sourceCode default">tag_invoke</code> proposal <span class="citation" data-cites="P1895R0">[<a href="#ref-P1895R0" role="doc-biblioref">P1895R0</a>]</span> further refines the concept of
customisation-point objects to use a single ADL name
<code class="sourceCode default">tag_invoke</code> and instead
distinguish customisations of different CPOs by passing the CPO itself
as the first argument, using tag-dispatch to select the right overload.
This simplifies definitions of customisation-point objects, enables
generically customising many CPOs, and eliminates the issue of name
conflicts inherent in ADL-based approaches when different libraries use
the same function name for customisation points with different semantics
by allowing names to be namespace-scoped.</p>
<p>Adding a first-class language solution for defining customisation
points has been suggested before; Matt Calabrese’s paper <span class="citation" data-cites="P1292R0">[<a href="#ref-P1292R0" role="doc-biblioref">P1292R0</a>]</span> <em>“Customization Point
Functions”</em> suggests adding a language syntax for customisation
points similar to the syntax proposed here.</p>
<p>Barry Revzin’s paper <span class="citation" data-cites="P2279R0">[<a href="#ref-P2279R0" role="doc-biblioref">P2279R0</a>]</span> <em>“We
need a language mechanism for customization points”</em> discusses what
he sees as the essential properties of “proper customisation” in the
context of <code class="sourceCode default">tag_invoke</code> and also
seems to come to the conclusion that
<code class="sourceCode default">tag_invoke</code>, despite being an
improvement on previous solutions, still leaves much to be desired and
that we should pursue a language solution.</p>
<div class="line-block">“<code class="sourceCode default">tag_invoke</code>
is an improvement over customization point objects as a library solution
to the static polymorphism problem. But I don’t really think it’s better
enough, and we really need a language solution to this problem. …”</div>
<p>A discussion of <span class="citation" data-cites="P2279R0">[<a href="#ref-P2279R0" role="doc-biblioref">P2279R0</a>]</span> in a joint
library/language evolution session had strong consensus for exploring a
language solution to the problem of defining customisation points. This
is that paper.</p>
<p><strong>POLL:</strong> <em>We should promise more committee time to
exploring language mechanism for customization points (<span class="citation" data-cites="P2279R0">[<a href="#ref-P2279R0" role="doc-biblioref">P2279R0</a>]</span>), knowing that our time is
scarce and this will leave less time for other work.</em></p>
<table style="width:33%;">
<colgroup>
<col style="width: 6%" />
<col style="width: 6%" />
<col style="width: 5%" />
<col style="width: 6%" />
<col style="width: 6%" />
</colgroup>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>SF</strong>
</div></th>
<th><div style="text-align:center">
<strong>WF</strong>
</div></th>
<th><div style="text-align:center">
<strong>N</strong>
</div></th>
<th><div style="text-align:center">
<strong>WA</strong>
</div></th>
<th><div style="text-align:center">
<strong>SA</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>30</td>
<td>12</td>
<td>2</td>
<td>0</td>
<td>0</td>
</tr>
</tbody>
</table>
<p>The paper <span class="citation" data-cites="P2300R5">[<a href="#ref-P2300R5" role="doc-biblioref">P2300R5</a>]</span>
<em>“<code class="sourceCode default">std::execution</code>”</em>
proposes a design that heavily uses customisable functions which are
currently based on <code class="sourceCode default">tag_invoke</code> as
the customisation mechanism. If <span class="citation" data-cites="P2300R5">[<a href="#ref-P2300R5" role="doc-biblioref">P2300R5</a>]</span> is standardised with
customisation points defined in terms of
<code class="sourceCode default">tag_invoke()</code>, retrofitting them
to support the language-based solution for customisable functions
proposed in this paper will still carry all the downsides of
<code class="sourceCode default">tag_invoke</code> due to backwards
compatibility requirements.</p>
<p>The added complexity of CPOs and abstractions to support both
<code class="sourceCode default">tag_invoke</code> and a language
solution may negate much of the benefit of using a language feature.</p>
<p>The committee should consider whether it is preferable to first
standardise a language-based approach to customisable functions before
adding a large number of customisable functions to the standard library
based on <code class="sourceCode default">tag_invoke</code>.</p>
<h1 data-number="7" id="motivation"><span class="header-section-number">7</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>A primary motivation for writing this paper was based on experience
building libraries such as libunifex, which implement some earlier
versions of sender/receiver concepts from <span class="citation" data-cites="P2300R5">[<a href="#ref-P2300R5" role="doc-biblioref">P2300R5</a>]</span> and are heavily based on
<code class="sourceCode default">tag_invoke</code> customisation point
objects.</p>
<p>While the <code class="sourceCode default">tag_invoke</code>
mechanism for implementing customisation points is functional and
powerful, there are a few things that make it less than ideal as the
standard-blessed mechanism for customisable functions.</p>
<ul>
<li>It requires a lot of boiler-plate when defining a new customisation
point (see example below)</li>
<li>Customisations are harder to read due to the function-name being
found in the first argument position instead of in the function-name
position (which is always
<code class="sourceCode default">tag_invoke</code>).</li>
<li>The extra layer of forwarding prevents copy-elision of arguments
even if the customisation takes a parameter by-value.</li>
<li>Every customisation uses the name
<code class="sourceCode default">tag_invoke</code>, which can make for a
large overload-set that the compiler has to consider. Types that
customise a large number of CPOs have all of those customisations added
to the overload-set for every call to a CPO with that type as an
argument. This can impact compile times when used at scale, and heavily
impacts user-visible error messages.</li>
<li>The <code class="sourceCode default">tag_invoke</code> forwarding
mechanism requires a lot of template instantiations when instantiating
the call operator (<code class="sourceCode default">tag_invocable</code>
concept for constraint,
<code class="sourceCode default">tag_invoke_result_t</code> for return
type, <code class="sourceCode default">is_nothrow_tag_invocable_v</code>
to forward <code class="sourceCode default">noexcept</code> clause, the
<code class="sourceCode default">std::tag_invoke_t::operator()</code>
function template. This can potentially impact compile-time in code
where there are a large number of calls to CPOs.</li>
</ul>
<p>For example, defining a hypothetical
<code class="sourceCode default">std::ranges::contains</code>
customisable function with a default implementation requires a lot of
boiler-plate with
<code class="sourceCode default">tag_invoke</code>.</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong><code class="sourceCode default">tag_invoke</code> (<span class="citation" data-cites="P1895R0">[<a href="#ref-P1895R0" role="doc-biblioref">P1895R0</a>]</span>)</strong>
</div></th>
<th><div style="text-align:center">
<strong>This proposal</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> contains_t <span class="op">{</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>input_range R, <span class="kw">typename</span> Value<span class="op">&gt;</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>      tag_invocable<span class="op">&lt;</span>contains_t, R, <span class="kw">const</span> Value<span class="op">&amp;&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>      equality_comparable_with<span class="op">&lt;</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>        range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, Value<span class="op">&gt;</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <span class="kw">operator</span><span class="op">()(</span>R<span class="op">&amp;&amp;</span> range, <span class="kw">const</span> Value<span class="op">&amp;</span> v<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">noexcept</span><span class="op">(</span>is_nothrow_tag_invocable_v<span class="op">&lt;</span></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>               contains_t, R, <span class="kw">const</span> Value<span class="op">&amp;&gt;)</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> tag_invoke_result_t<span class="op">&lt;</span>contains_t, R,</span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a>                           <span class="kw">const</span> Value<span class="op">&amp;&gt;</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> std<span class="op">::</span>tag_invoke<span class="op">(</span>contains_t<span class="op">{}</span>, <span class="op">(</span>R<span class="op">&amp;&amp;)</span>range, value<span class="op">)</span>;</span>
<span id="cb15-16"><a href="#cb15-16" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-18"><a href="#cb15-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>input_range R, <span class="kw">typename</span> Value<span class="op">&gt;</span></span>
<span id="cb15-19"><a href="#cb15-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span></span>
<span id="cb15-20"><a href="#cb15-20" aria-hidden="true" tabindex="-1"></a>      <span class="op">!</span>tag_invocable<span class="op">&lt;</span>contains_t, R, <span class="kw">const</span> Value<span class="op">&amp;&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb15-21"><a href="#cb15-21" aria-hidden="true" tabindex="-1"></a>      equality_comparable_with<span class="op">&lt;</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, Value<span class="op">&gt;</span></span>
<span id="cb15-22"><a href="#cb15-22" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> <span class="kw">operator</span><span class="op">()(</span>R<span class="op">&amp;&amp;</span> range, <span class="kw">const</span> Value<span class="op">&amp;</span> v<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb15-23"><a href="#cb15-23" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb15-24"><a href="#cb15-24" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> x <span class="op">:</span> range<span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-25"><a href="#cb15-25" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>x <span class="op">==</span> v<span class="op">)</span> <span class="cf">return</span> <span class="kw">true</span>;</span>
<span id="cb15-26"><a href="#cb15-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb15-27"><a href="#cb15-27" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">false</span>;</span>
<span id="cb15-28"><a href="#cb15-28" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb15-29"><a href="#cb15-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb15-30"><a href="#cb15-30" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> contains_t contains<span class="op">{}</span>;</span>
<span id="cb15-31"><a href="#cb15-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="co">// namespace std::ranges</span></span></code></pre></div>

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

<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span>input_range R, <span class="kw">typename</span> Value<span class="op">&gt;</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> equality_comparable_with<span class="op">&lt;</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, Value<span class="op">&gt;</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> contains<span class="op">(</span>R<span class="op">&amp;&amp;</span> range, <span class="kw">const</span> Value<span class="op">&amp;</span> v<span class="op">)</span> customisable;</span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span>input_range R, <span class="kw">typename</span> Value<span class="op">&gt;</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> equality_comparable_with<span class="op">&lt;</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, Value<span class="op">&gt;</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> contains<span class="op">(</span>R<span class="op">&amp;&amp;</span> range, <span class="kw">const</span> Value<span class="op">&amp;</span> v<span class="op">)</span> <span class="cf">default</span> <span class="op">{</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> x <span class="op">:</span> range<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>x <span class="op">==</span> v<span class="op">)</span> <span class="cf">return</span> <span class="kw">true</span>;</span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="kw">false</span>;</span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="co">// namespace std::ranges</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>When reading code that customises a function, it is difficult for the
eye to scan over the declaration to see which function is being
customised. You need to look for the template argument to
<code class="sourceCode default">std::tag_t</code> in the first argument
of the customization instead of in the function-name position, where
most editors highlight the name.</p>
<p>Barry’s discussion paper <span class="citation" data-cites="P2279R0">[<a href="#ref-P2279R0" role="doc-biblioref">P2279R0</a>]</span> contains further critique of
<code class="sourceCode default">tag_invoke</code> and other
customisation point mechanisms along several axes:</p>
<ol type="1">
<li>The ability to see clearly, in code, what the interface is that can
(or needs to) be customised.</li>
<li>The ability to provide default implementations that can be
overridden, not just non-defaulted functions.</li>
<li>The ability to opt in <em>explicitly</em> to the interface.</li>
<li>The inability to <em>incorrectly</em> opt in to the interface (for
instance, if the interface has a function that takes an
<code class="sourceCode default">int</code>, you cannot opt in by
accidentally taking an
<code class="sourceCode default">unsigned int</code>).</li>
<li>The ability to easily invoke the customised implementation.
Alternatively, the inability to accidentally invoke the base
implementation.</li>
<li>The ability to easily verify that a type implements an
interface.</li>
<li>The ability to present an atomic group of functionality that needs
to be customised together (and diagnosed early).</li>
<li>The ability to opt in types that you do not own to an interface
non-intrusively.</li>
<li>The ability to provide associated types as part of the customisation
of an interface.</li>
<li>The ability to customise multiple CPOs generically (e.g. for
forwarding to a wrapped object)</li>
</ol>
<p>The proposal in this paper addresses most of these axes, improving on
<span class="citation" data-cites="P1292R0">[<a href="#ref-P1292R0" role="doc-biblioref">P1292R0</a>]</span> customisation point functions
by adding better support for diagnosis of incorrect customisations and
adding the ability to generically customise multiple
customisation-points and forward them to calls on wrapped objects.</p>
<p>This proposal is not attempting to solve the “atomic group of
functionality” or the “associated types” aspects that <span class="citation" data-cites="P2279R0">[<a href="#ref-P2279R0" role="doc-biblioref">P2279R0</a>]</span> discusses. Although in
combination with C++20 concepts it does a reasonable job of matching the
simplicity of Rust Traits (see Comparison to Rust Traits).
<!-- TODO add link to Rust Traits to section --> The authors do not
believe that this proposal would prevent the ability to define such an
atomic group of functionality as a future extension to the language, or
even as a library feature.</p>
<p>While <span class="citation" data-cites="P2279R0">[<a href="#ref-P2279R0" role="doc-biblioref">P2279R0</a>]</span> does a
great job of surveying the existing techniques used for customisation
points, we want to further elaborate on some limitations of those
techniques not discussed in that paper.</p>
<h2 data-number="7.1" id="the-problem-with-member-functions"><span class="header-section-number">7.1</span> The problem with
member-functions<a href="#the-problem-with-member-functions" class="self-link"></a></h2>
<!-- TODO: Niebler: If you plan to take this to EWG, then you'll need to change how you talk about this since member functions are not namespace scope entities. -->
<h3 data-number="7.1.1" id="member-functions-all-live-in-a-single-global-namespace"><span class="header-section-number">7.1.1</span> Member functions all live in
a single global “namespace”<a href="#member-functions-all-live-in-a-single-global-namespace" class="self-link"></a></h3>
<ul>
<li>(from the perspective of generic programming)</li>
</ul>
<p>If a generic concept defined by one library wants to use the
<code class="sourceCode default">.foo()</code> member function name as a
customisation point, it will potentially conflict with <em>another</em>
library that also uses the
<code class="sourceCode default">.foo()</code> member function name as a
customisation point with different implied semantics.</p>
<p>This can lead to types accidentally satisfying a given concept
syntactically even if the semantics of the implementations don’t match
because they are implementing a different concept.</p>
<p>It can also make it impossible to implement a type that satisfies two
concepts if both of those concepts use conflicting customisation point
names. e.g. the somewhat contrived example:</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> GUI <span class="op">{</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> size <span class="op">{</span> <span class="dt">int</span> width; <span class="dt">int</span> height; <span class="op">}</span>;</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-4"><a href="#cb17-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="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> widget <span class="op">=</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> w<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>      <span class="op">{</span> w<span class="op">.</span>size<span class="op">()</span> <span class="op">}</span> <span class="op">-&gt;</span> std<span class="op">::</span>same_as<span class="op">&lt;</span>GUI<span class="op">::</span>size<span class="op">&gt;</span>;</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> CONTAINER <span class="op">{</span></span>
<span id="cb17-12"><a href="#cb17-12" 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="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> sized_container <span class="op">=</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> c<span class="op">)</span> <span class="op">{</span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>      <span class="op">{</span> c<span class="op">.</span>size<span class="op">()</span> <span class="op">}</span> <span class="op">-&gt;</span> std<span class="op">::</span>same_as<span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">::</span>size_type<span class="op">&gt;</span>;</span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>A <code class="sourceCode default">composite_widget</code> type that
wants to be a <code class="sourceCode default">sized_container</code> of
widgets but also a widget itself would not be able to simultaneously
satisfy both the concepts as it can only define one
<code class="sourceCode default">size()</code> member function.</p>
<h3 data-number="7.1.2" id="we-cannot-customise-different-member-names-generically"><span class="header-section-number">7.1.2</span> We cannot customise different
member names generically<a href="#we-cannot-customise-different-member-names-generically" class="self-link"></a></h3>
<p>If one wants to build a wrapper type that customises only one
customisation point and <em>forwards the rest</em>, or that type-erases
objects that support a given concept, one needs to implement a new class
for each set of member names they want to forward.</p>
<p>e.g. For each concept we need to define a new wrapper type instead of
being able to define a wrapping pattern generically.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span>foo_concept Foo<span class="op">&gt;</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> synchronised_foo <span class="op">{</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>  Foo inner;</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>mutex mut;</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> foo<span class="op">()</span> <span class="op">{</span> std<span class="op">::</span>unique_lock lk<span class="op">{</span>mut<span class="op">}</span>; inner<span class="op">.</span>foo<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span>bar_concept Bar<span class="op">&gt;</span></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> synchronised_bar <span class="op">{</span></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>  Bar inner;</span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>mutex mut;</span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> bar<span class="op">()</span> <span class="op">{</span> std<span class="op">::</span>unique_lock lk<span class="op">{</span>mut<span class="op">}</span>; inner<span class="op">.</span>bar<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> baz<span class="op">()</span> <span class="op">{</span> std<span class="op">::</span>unique_lock lk<span class="op">{</span>mut<span class="op">}</span>; inner<span class="op">.</span>baz<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<h3 data-number="7.1.3" id="customisation-point-member-functions-cannot-be-passed-to-higher-order-functions"><span class="header-section-number">7.1.3</span> Customisation-point member
functions cannot be passed to higher-order functions<a href="#customisation-point-member-functions-cannot-be-passed-to-higher-order-functions" class="self-link"></a></h3>
<p>Generally, we need to wrap up the call to an object in a generic
lambda so we can pass it as an object representing an overload set.</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> <span class="kw">auto</span> foo <span class="op">=</span> <span class="op">[](</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> x<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="kw">static_cast</span><span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>x<span class="op">)&gt;(</span>x<span class="op">).</span>foo<span class="op">()</span>;</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<h3 data-number="7.1.4" id="implementing-a-concept-requires-modification-of-the-type"><span class="header-section-number">7.1.4</span> Implementing a concept
requires modification of the type<a href="#implementing-a-concept-requires-modification-of-the-type" class="self-link"></a></h3>
<p>We cannot define new customisations of functions for types we cannot
modify if they must be defined as member functions.</p>
<p>A common workaround for this is to use the CRTP pattern (or, since
C++23, <span class="citation" data-cites="P0847R7">[<a href="#ref-P0847R7" role="doc-biblioref">P0847R7</a>]</span>
<em>“Deducing this”</em>) to have each type inherit from some base class
that provides default implementations for common operations, but this is
effectively providing a way to modify types that inherit from it, and
not purely unrelated types.</p>
<p>e.g. We can define two types that implement a concept and that both
inherit from <code class="sourceCode default">foo_base</code>:</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> foo_base <span class="op">{</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> thing1<span class="op">(</span><span class="kw">this</span> <span class="kw">auto</span><span class="op">&amp;</span> self<span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;default thing1</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">)</span>;</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> foo_a <span class="op">:</span> foo_base <span class="op">{}</span>;</span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> foo_b <span class="op">:</span> foo_base <span class="op">{</span></span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> thing1<span class="op">()</span> <span class="op">{</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;foo_b thing1</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>We can then later extend
<code class="sourceCode default">foo_base</code> to add additional
members with default implementations in a non-breaking fashion.</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> foo_base <span class="op">{</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> thing1<span class="op">(</span><span class="kw">this</span> <span class="kw">auto</span><span class="op">&amp;</span> self<span class="op">)</span> <span class="op">{</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;default thing1</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">)</span>;</span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> thing2<span class="op">(</span><span class="kw">this</span> <span class="kw">auto</span><span class="op">&amp;</span> self, <span class="dt">int</span> n<span class="op">)</span> <span class="op">{</span></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;default thing2</span><span class="sc">\n</span><span class="st">&quot;</span><span class="op">)</span>;</span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(</span>n<span class="op">--</span> <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> self<span class="op">.</span>thing1<span class="op">()</span>;</span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>It may not be possible to retrofit or enforce that all types that
satisfy a concept use the CRTP base, however.</p>
<h2 data-number="7.2" id="problems-with-raw-argument-dependent-lookup-adl"><span class="header-section-number">7.2</span> Problems with raw
argument-dependent lookup (ADL)<a href="#problems-with-raw-argument-dependent-lookup-adl" class="self-link"></a></h2>
<p>This is the technique used by facilities like
<code class="sourceCode default">std::swap()</code>.</p>
<p>A default implementation is defined in some namespace and then
customisations are placed in an associated namespace of the arguments to
the type. e.g.</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb22-2"><a href="#cb22-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="op">&gt;</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> swap<span class="op">(</span>T<span class="op">&amp;</span> a, T<span class="op">&amp;</span> b<span class="op">)</span> <span class="op">{</span></span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>    T tmp <span class="op">=</span> move<span class="op">(</span>a<span class="op">)</span>;</span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>    a <span class="op">=</span> move<span class="op">(</span>b<span class="op">)</span>;</span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>    b <span class="op">=</span> move<span class="op">(</span>tmp<span class="op">)</span>;</span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> customising_lib <span class="op">{</span></span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> X <span class="op">{</span></span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="dt">void</span> swap<span class="op">(</span>X<span class="op">&amp;</span> a, X<span class="op">&amp;</span> b<span class="op">)</span> <span class="op">{</span> <span class="co">/* More efficient implementation */</span> <span class="op">}</span></span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> consumer <span class="op">{</span></span>
<span id="cb22-17"><a href="#cb22-17" 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="cb22-18"><a href="#cb22-18" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> reverse<span class="op">(</span>std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;&amp;</span> v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb22-19"><a href="#cb22-19" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">&lt;</span> v<span class="op">.</span>size<span class="op">()</span> <span class="op">/</span> <span class="dv">2</span>; <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb22-20"><a href="#cb22-20" aria-hidden="true" tabindex="-1"></a>      <span class="kw">using</span> std<span class="op">::</span>swap;                 <span class="co">// Step 1. Make default available.</span></span>
<span id="cb22-21"><a href="#cb22-21" aria-hidden="true" tabindex="-1"></a>      swap<span class="op">(</span>v<span class="op">[</span>i<span class="op">]</span>, v<span class="op">[</span>v<span class="op">.</span>size<span class="op">()</span> <span class="op">-</span> i <span class="op">-</span> <span class="dv">1</span><span class="op">])</span>; <span class="co">// Step 2. Call unqualified.</span></span>
<span id="cb22-22"><a href="#cb22-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb22-23"><a href="#cb22-23" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb22-24"><a href="#cb22-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 data-number="7.2.1" id="adl-function-names-all-share-a-single-global-namespace"><span class="header-section-number">7.2.1</span> ADL function names all share
a single global namespace<a href="#adl-function-names-all-share-a-single-global-namespace" class="self-link"></a></h3>
<p>Similar to the limitation of member functions, which have a single
global namespace that all member function names conceptually live
within, there is also a single global namespace that all functions
intended to be called using ADL conceptually live within.</p>
<p>If two libraries decide to use the same ADL name as a customisation
point then it is possible that the usages of those libraries may
conflict. This can lead to either an inability for a type to implement
concepts from both libraries or the potential for a type to implement
the concept from one library and accidentally match the concept from
another library.</p>
<h3 data-number="7.2.2" id="inability-to-customise-different-adl-names-generically"><span class="header-section-number">7.2.2</span> Inability to customise
different ADL names generically<a href="#inability-to-customise-different-adl-names-generically" class="self-link"></a></h3>
<p>Similarly to the limitation of member functions, customisation points
defined in terms of raw ADL need to know the name of the ADL function in
order to customise it.</p>
<p>This means we cannot build wrapper types that generically customise
and forward multiple customisation point calls to a child object. We
need to explicitly customise and forward each ADL name. This prohibits
the implementation of any generic decorator pattern.</p>
<h3 data-number="7.2.3" id="inability-to-pass-a-customisation-point-as-an-argument-ta-higher-order-function"><span class="header-section-number">7.2.3</span> Inability to pass a
customisation-point as an argument ta higher-order function<a href="#inability-to-pass-a-customisation-point-as-an-argument-ta-higher-order-function" class="self-link"></a></h3>
<p>We cannot just pass an ADL function name to a higher-order function
as a parameter. A name that names a function must resolve to a specific
overload when used outside of a call-expression, so that the name can
resolve to a function pointer.</p>
<p>The issues here are covered in more detail in <span class="citation" data-cites="P1170R0">[<a href="#ref-P1170R0" role="doc-biblioref">P1170R0</a>]</span> <em>Overload sets as function
parameters</em>. One of the motivating examples from that paper is
reproduced here for convenience.</p>
<p>e.g. While we can write:</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> N <span class="op">{</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> X <span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>  X getX<span class="op">()</span>;</span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>foo<span class="op">(</span>N<span class="op">::</span>getX<span class="op">())</span>; <span class="co">// which calls some function &#39;foo&#39;</span></span></code></pre></div>
<p>we can’t necessarily write:</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> F<span class="op">&gt;</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> algorithm<span class="op">(</span>F f, N<span class="op">::</span>X x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>  f<span class="op">(</span>x<span class="op">)</span>;</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>algorithm<span class="op">(</span>foo, N<span class="op">::</span>getX<span class="op">())</span>;</span></code></pre></div>
<p>As <code class="sourceCode default">foo</code> could be a function
template, name an overload-set or be a function that was only found by
ADL, or any of several other situations, this code may or may not be
valid code.</p>
<p>If <code class="sourceCode default">foo</code> was intended to be a
customisation point, it would almost always be an overload set.</p>
<p>One common workaround to this is to wrap the call in a lambda.
e.g.</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> <span class="kw">auto</span> foo <span class="op">=</span> <span class="op">[](</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> x<span class="op">)</span> <span class="op">-&gt;</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="kw">static_cast</span><span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>x<span class="op">)&gt;(</span>x<span class="op">).</span>foo<span class="op">()</span>;</span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>However, this is a lot of boiler-plate to have to remember to write
at every call site where you want to pass
<code class="sourceCode default">foo</code> as an overload-set.</p>
<h3 data-number="7.2.4" id="need-for-two-step-usingcall-to-call-functions-with-default-implementations-e.g.-swap"><span class="header-section-number">7.2.4</span> Need for two-step using/call
to call functions with default implementations
(e.g. <code class="sourceCode default">swap()</code>)<a href="#need-for-two-step-usingcall-to-call-functions-with-default-implementations-e.g.-swap" class="self-link"></a></h3>
<p>The need to perform the two-step using/call is unfortunate due to the
extra line of code you need to write, especially since you <em>must</em>
<em>not</em> forget to write it.</p>
<p>This also complicates deducing what the return type of a call to the
customisation point is. e.g. to determine the iterator type returned by
<code class="sourceCode default">begin()</code> - we can’t add the
<code class="sourceCode default">using std::begin;</code> default
implementation to a <code class="sourceCode default">decltype()</code>
expression.</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="co">// This won&#39;t find the default implementation.</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Rng<span class="op">&gt;</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> range_iterator_t <span class="op">=</span> <span class="kw">decltype</span><span class="op">(</span><span class="co">/* what to write here? */</span><span class="op">)</span>;</span></code></pre></div>
<p>Instead, one must wrap the two-step call mechanism in a namespace
that has brought in the default implementation. e.g.</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> _begin <span class="op">{</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> std<span class="op">::</span>begin; <span class="co">// Also shadows &#39;begin&#39; defined in parent namespace.</span></span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Rng<span class="op">&gt;</span></span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> range_iterator_t <span class="op">=</span> <span class="kw">decltype</span><span class="op">(</span>begin<span class="op">(</span>std<span class="op">::</span>declval<span class="op">&lt;</span>Rng<span class="op">&amp;&gt;()))</span>;</span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb27-7"><a href="#cb27-7" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> range_iterator_t;</span></code></pre></div>
<p>A bigger problem, however, is that callers might accidentally call
the default function explicitly. i.e. instead of writing</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a>using std::swap;</span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>swap(a, b);</span></code></pre></div>
<p>a programmer might write</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>swap<span class="op">(</span>a, b<span class="op">)</span>;</span></code></pre></div>
<p>In this case, the compiler will no longer perform ADL when resolving
overloads of this call and so it will generally not find any
customisations of <code class="sourceCode default">swap()</code> for the
types passed to it; instead, it will always calls the default
implementation. For many types, the default implementation of
<code class="sourceCode default">swap()</code> will still silently
compile just fine - it may just run a lot slower than if it called the
custom implementation.</p>
<h3 data-number="7.2.5" id="adl-is-location-dependent"><span class="header-section-number">7.2.5</span> ADL is location-dependent<a href="#adl-is-location-dependent" class="self-link"></a></h3>
<p>… and therefore nondeterministic and difficult to debug when
wrong.</p>
<p>When a raw ADL customisation-point that is intended to be called
unqualified is defined so that ADL finds the right customisation, but
where there is no default implementation, the two-step using+call
process is generally not required when calling the
customisation-point.</p>
<p>However, this means that the call-site will consider any overloads
declared in parent namespaces which can make the overload that a call
dispatches to context-sensitive.</p>
<p>For example: Two call expressions to the same ADL name from different
contexts resolve to different overloads despite the arguments to those
expressions having the same type.</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> ns1 <span class="op">{</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> X <span class="op">{}</span>;</span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> foo<span class="op">(</span>X <span class="kw">const</span><span class="op">&amp;)</span> <span class="op">{</span> <span class="cf">return</span> <span class="dv">1</span>; <span class="op">}</span></span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> ns2 <span class="op">{</span></span>
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> foo<span class="op">(</span>ns1<span class="op">::</span>X<span class="op">&amp;</span> x<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> <span class="dv">2</span>;<span class="op">}</span></span>
<span id="cb30-9"><a href="#cb30-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb30-10"><a href="#cb30-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-11"><a href="#cb30-11" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> ns3 <span class="op">{</span></span>
<span id="cb30-12"><a href="#cb30-12" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> bar<span class="op">()</span> <span class="op">{</span></span>
<span id="cb30-13"><a href="#cb30-13" aria-hidden="true" tabindex="-1"></a>    ns1<span class="op">::</span>X x;</span>
<span id="cb30-14"><a href="#cb30-14" aria-hidden="true" tabindex="-1"></a>    foo<span class="op">(</span>x<span class="op">)</span>; <span class="co">// calls ns1::foo(ns1::X const&amp;)</span></span>
<span id="cb30-15"><a href="#cb30-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb30-16"><a href="#cb30-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb30-17"><a href="#cb30-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-18"><a href="#cb30-18" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> ns2 <span class="op">{</span></span>
<span id="cb30-19"><a href="#cb30-19" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> baz<span class="op">()</span> <span class="op">{</span></span>
<span id="cb30-20"><a href="#cb30-20" aria-hidden="true" tabindex="-1"></a>    ns1<span class="op">::</span>X x;</span>
<span id="cb30-21"><a href="#cb30-21" aria-hidden="true" tabindex="-1"></a>    foo<span class="op">(</span>x<span class="op">)</span>; <span class="co">// calls ns2::foo(ns1::X&amp;)</span></span>
<span id="cb30-22"><a href="#cb30-22" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb30-23"><a href="#cb30-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This problem does not usually come up when using the two-step
<code class="sourceCode default">using</code>, however, as the
<code class="sourceCode default">using</code> declaration shadows the
declarations from parent namespaces.</p>
<h2 data-number="7.3" id="the-problem-with-cpos-defined-in-ranges"><span class="header-section-number">7.3</span> The problem with CPOs defined
in ranges<a href="#the-problem-with-cpos-defined-in-ranges" class="self-link"></a></h2>
<p>The <code class="sourceCode default">std::ranges</code> library
defines a number of customisation point objects which build on ADL, but
that make the customization points easier to use correctly by
encapsulating the two-step using approach in the call operator of the
CPO.</p>
<p>For example: A rough approximation of the
<code class="sourceCode default">std::ranges::swap()</code> CPO
defined</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">namespace</span> __swap <span class="op">{</span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> swap<span class="op">()</span>; <span class="co">// poison-pill so we don&#39;t find std::swap</span></span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-5"><a href="#cb31-5" 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="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">concept</span> __has_swap <span class="op">=</span> <span class="kw">requires</span><span class="op">(</span>T<span class="op">&amp;&amp;</span> t, U<span class="op">&amp;&amp;</span> u<span class="op">)</span> <span class="op">{</span></span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>      swap<span class="op">(</span><span class="kw">static_cast</span><span class="op">&lt;</span>T<span class="op">&amp;&amp;&gt;(</span>t<span class="op">)</span>, <span class="kw">static_cast</span><span class="op">&lt;</span>U<span class="op">&amp;&amp;&gt;(</span>u<span class="op">))</span>;</span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb31-9"><a href="#cb31-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-10"><a href="#cb31-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> __fn <span class="op">{</span></span>
<span id="cb31-11"><a href="#cb31-11" 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="cb31-12"><a href="#cb31-12" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> __has_swap<span class="op">&lt;</span>T, U<span class="op">&gt;</span></span>
<span id="cb31-13"><a href="#cb31-13" aria-hidden="true" tabindex="-1"></a>      <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span>T<span class="op">&amp;&amp;</span> t, U<span class="op">&amp;&amp;</span> u<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb31-14"><a href="#cb31-14" aria-hidden="true" tabindex="-1"></a>          <span class="kw">noexcept</span><span class="op">(</span><span class="kw">noexcept</span><span class="op">(</span>swap<span class="op">(</span><span class="kw">static_cast</span><span class="op">&lt;</span>T<span class="op">&amp;&amp;&gt;(</span>t<span class="op">)</span>, <span class="kw">static_cast</span><span class="op">&lt;</span>U<span class="op">&amp;&amp;&gt;(</span>u<span class="op">)))</span> <span class="op">{</span></span>
<span id="cb31-15"><a href="#cb31-15" aria-hidden="true" tabindex="-1"></a>        swap<span class="op">(</span><span class="kw">static_cast</span><span class="op">&lt;</span>T<span class="op">&amp;&amp;&gt;(</span>t<span class="op">)</span>, <span class="kw">static_cast</span><span class="op">&lt;</span>U<span class="op">&amp;&amp;&gt;(</span>u<span class="op">))</span>;</span>
<span id="cb31-16"><a href="#cb31-16" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb31-17"><a href="#cb31-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-18"><a href="#cb31-18" 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="cb31-19"><a href="#cb31-19" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <span class="op">(!</span>__has_swap<span class="op">&lt;</span>T<span class="op">&gt;)</span> <span class="op">&amp;&amp;</span> movable<span class="op">&lt;</span>T<span class="op">&gt;</span></span>
<span id="cb31-20"><a href="#cb31-20" aria-hidden="true" tabindex="-1"></a>      <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span>T<span class="op">&amp;</span> a, T<span class="op">&amp;</span> b<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb31-21"><a href="#cb31-21" aria-hidden="true" tabindex="-1"></a>          <span class="kw">noexcept</span><span class="op">(</span>std<span class="op">::</span>is_nothrow_move_constructible_v<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb31-22"><a href="#cb31-22" aria-hidden="true" tabindex="-1"></a>                   std<span class="op">::</span>is_nothrow_move_assignable_v<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb31-23"><a href="#cb31-23" aria-hidden="true" tabindex="-1"></a>                   std<span class="op">::</span>is_nothrow_destructible_v<span class="op">&lt;</span>T<span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb31-24"><a href="#cb31-24" aria-hidden="true" tabindex="-1"></a>        T tmp<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>a<span class="op">))</span>;</span>
<span id="cb31-25"><a href="#cb31-25" aria-hidden="true" tabindex="-1"></a>        a <span class="op">=</span> std<span class="op">::</span>move<span class="op">(</span>b<span class="op">)</span>;</span>
<span id="cb31-26"><a href="#cb31-26" aria-hidden="true" tabindex="-1"></a>        b <span class="op">=</span> std<span class="op">::</span>move<span class="op">(</span>tmp<span class="op">)</span>;</span>
<span id="cb31-27"><a href="#cb31-27" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb31-28"><a href="#cb31-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-29"><a href="#cb31-29" aria-hidden="true" tabindex="-1"></a>      <span class="co">// etc. for other default implementations (e.g. for swapping arrays)</span></span>
<span id="cb31-30"><a href="#cb31-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb31-31"><a href="#cb31-31" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb31-32"><a href="#cb31-32" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Function object needs to be in a separate namespace</span></span>
<span id="cb31-33"><a href="#cb31-33" aria-hidden="true" tabindex="-1"></a>  <span class="co">// And imported using &#39;using namespace&#39; to avoid conflicts with</span></span>
<span id="cb31-34"><a href="#cb31-34" aria-hidden="true" tabindex="-1"></a>  <span class="co">// hidden-friend customisations defined for types in std::ranges.</span></span>
<span id="cb31-35"><a href="#cb31-35" aria-hidden="true" tabindex="-1"></a>  <span class="kw">inline</span> <span class="kw">namespace</span> __swap_cpo <span class="op">{</span></span>
<span id="cb31-36"><a href="#cb31-36" aria-hidden="true" tabindex="-1"></a>      <span class="kw">inline</span> <span class="kw">constexpr</span> __swap<span class="op">::</span>__fn swap<span class="op">{}</span>;</span>
<span id="cb31-37"><a href="#cb31-37" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb31-38"><a href="#cb31-38" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Defining customisation-points as objects has a number of
benefits:</p>
<ul>
<li>Callers no longer need to use the two-step using+call to call it
correctly. Simplifies usage and makes the API safer to use.</li>
<li>The function is an object, so can be passed as an argument to a
higher-order function as if it were the overload set (although current
<code class="sourceCode default">std::ranges</code> specifications
prohibit this).</li>
<li>Still lets customisations be found by ADL - customisations of
<code class="sourceCode default">std::ranges::swap</code> are defined as
function overloads with the name
<code class="sourceCode default">swap</code>.</li>
</ul>
<p>However, there are still some problems with this approach.</p>
<h3 data-number="7.3.1" id="still-relies-on-adl-for-customisation---single-global-namespace."><span class="header-section-number">7.3.1</span> Still relies on ADL for
customisation -&gt; Single global namespace.<a href="#still-relies-on-adl-for-customisation---single-global-namespace." class="self-link"></a></h3>
<p>This approach still generally relies on the same approach as raw ADL
which has a single-global namespace for customisation-point names and so
is susceptible to conflicts between libraries.</p>
<h3 data-number="7.3.2" id="unable-to-generically-customise-and-forward-implementations-in-wrapper-types."><span class="header-section-number">7.3.2</span> Unable to generically
customise and forward implementations in wrapper types.<a href="#unable-to-generically-customise-and-forward-implementations-in-wrapper-types." class="self-link"></a></h3>
<p>Wrapper types that want to forward customisations to wrapped objects
still need to know the names of all CPOs to be forwarded as they need to
explicitly define customisations using those names.</p>
<p>It is not possible to define a generic customisation that can forward
calls to many different customisation-points.</p>
<h3 data-number="7.3.3" id="lots-of-boiler-plate-needed-to-define-a-cpo"><span class="header-section-number">7.3.3</span> Lots of boiler-plate needed
to define a CPO<a href="#lots-of-boiler-plate-needed-to-define-a-cpo" class="self-link"></a></h3>
<p>Defining a CPO in this way requires writing a lot of boiler-plate.
This can often obscure the intent of the CPO.</p>
<p>E.g. the <code class="sourceCode default">std::ranges::swap()</code>
CPO above requires:</p>
<ul>
<li>defining two private namespaces</li>
<li>adding a poison pill declaration</li>
<li>defining a function object type</li>
<li>defining multiple <code class="sourceCode default">operator()</code>
overloads</li>
<li>manually constraining
<code class="sourceCode default">operator()</code> overloads to prefer a
customisation over a default.</li>
<li>inline constexpr instance of callable object</li>
</ul>
<p>Many of the reasons for defining this way are subtle and require a
high-level of understanding of ADL and various corner-cases of the
language.</p>
<h3 data-number="7.3.4" id="the-extra-layer-of-indirection-through-the-operator-overload-inhibits-copy-elision"><span class="header-section-number">7.3.4</span> The extra layer of
indirection through the
<code class="sourceCode default">operator()</code> overload inhibits
copy-elision<a href="#the-extra-layer-of-indirection-through-the-operator-overload-inhibits-copy-elision" class="self-link"></a></h3>
<p>Even if the caller of a CPO invokes the function with a prvalue and
this resolves to calling a customisation that takes the parameter
by-value, the fact that the call goes through an intermediate call to
<code class="sourceCode default">operator()</code>, which typically
takes its arguments by universal-reference and “perfectly forwards”
those arguments to the customisation, means that copy-elision of the
argument will be inhibited.</p>
<p>The additional indirection and the required
SFINAE+<code class="sourceCode default">noexcept</code> forwarding “You
must say it three times” also results in <em>poor</em> compiler
diagnostics that bury the true culprit deep in the template
instantiation stack.</p>
<p>For example:</p>
<div class="sourceCode" id="cb32"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> _foo <span class="op">{</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> foo<span class="op">()</span>;</span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> _fn <span class="op">{</span></span>
<span id="cb32-4"><a href="#cb32-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> V<span class="op">&gt;</span></span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">(</span>T<span class="op">&amp;</span> obj, V<span class="op">&amp;&amp;</span> value<span class="op">)</span> <span class="op">{</span></span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a>        foo<span class="op">(</span>obj, <span class="op">(</span>V<span class="op">&amp;&amp;)</span>value<span class="op">)</span>;</span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="kw">operator</span><span class="op">()(</span>T<span class="op">&amp;</span> obj, V<span class="op">&amp;&amp;</span> value<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb32-9"><a href="#cb32-9" aria-hidden="true" tabindex="-1"></a>      foo<span class="op">(</span>obj, <span class="op">(</span>V<span class="op">&amp;&amp;)</span>value<span class="op">)</span>;</span>
<span id="cb32-10"><a href="#cb32-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb32-11"><a href="#cb32-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb32-12"><a href="#cb32-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb32-13"><a href="#cb32-13" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">namespace</span> _foo_cpo <span class="op">{</span></span>
<span id="cb32-14"><a href="#cb32-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">inline</span> <span class="kw">constexpr</span> _foo<span class="op">::</span>_fn foo<span class="op">{}</span>;</span>
<span id="cb32-15"><a href="#cb32-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb32-16"><a href="#cb32-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-17"><a href="#cb32-17" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> my_type <span class="op">{</span></span>
<span id="cb32-18"><a href="#cb32-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">void</span> foo<span class="op">(</span>my_type<span class="op">&amp;</span> self, std<span class="op">::</span>string value<span class="op">)</span>;</span>
<span id="cb32-19"><a href="#cb32-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb32-20"><a href="#cb32-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-21"><a href="#cb32-21" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> example<span class="op">()</span> <span class="op">{</span></span>
<span id="cb32-22"><a href="#cb32-22" aria-hidden="true" tabindex="-1"></a>  my_type t;</span>
<span id="cb32-23"><a href="#cb32-23" aria-hidden="true" tabindex="-1"></a>  foo<span class="op">(</span>t, std<span class="op">::</span>string<span class="op">{</span><span class="st">&quot;hello&quot;</span><span class="op">})</span>; <span class="co">// will result in an extra call to</span></span>
<span id="cb32-24"><a href="#cb32-24" aria-hidden="true" tabindex="-1"></a>                                <span class="co">// std::string&#39;s move constructor.</span></span>
<span id="cb32-25"><a href="#cb32-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Whereas, if we were using raw ADL,
<code class="sourceCode default">foo()</code> would have resolved
directly to a call to the customisation and copy-elision would have been
performed.</p>
<p>Related to this extra level of indirection are some (minor)
additional costs: - stepping-through a call to a CPO when debugging
means having to step through the intermediate
<code class="sourceCode default">operator()</code>. - Debug builds that
do not inline this code have to execute the intermediate function,
slowing debug execution performance (some game developers have cited
debug performance as an issue) - There are compile-time costs to
instantiating the intermediate
<code class="sourceCode default">operator()</code> function
template.</p>
<p>Note the standard distinguishes CPOs (like
<code class="sourceCode default">ranges::begin</code>) from
<em>niebloids</em>. A <strong>niebloid</strong> is a non-customizable
function that is never found by ADL. Both niebloids and CPOs are
implemented as objects, but a niebloid has no user-defined
customization.</p>
<h2 data-number="7.4" id="the-problem-with-tag_invoke-cpos"><span class="header-section-number">7.4</span> The problem with
<code class="sourceCode default">tag_invoke</code> CPOs<a href="#the-problem-with-tag_invoke-cpos" class="self-link"></a></h2>
<p>The paper <span class="citation" data-cites="P1895R0">[<a href="#ref-P1895R0" role="doc-biblioref">P1895R0</a>]</span> first
introduced the <code class="sourceCode default">tag_invoke</code>
technique for defining customisation points, which tries to solve some
of the limitations of customisation-point objects.</p>
<p>In particular it tries to address the following issues:</p>
<ul>
<li>removing need for a single global namespace for customisation point
names by customising based on a tag-type, which can be namespace
scoped</li>
<li>allowing defining customisations to generically customise multiple
CPOs e.g. for forwarding on to an wrapped object</li>
</ul>
<p>Defining a CPO using
<code class="sourceCode default">tag_invoke</code> is much like defining
a <code class="sourceCode default">std::ranges</code>
customisation-point object, where instead of dispatching to a named ADL
call, we instead dispatch to a call to
<code class="sourceCode default">tag_invoke()</code>, with the CPO
object itself as the first parameter.</p>
<p>For example:</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> N <span class="op">{</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> contains_t <span class="op">{</span></span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span>range R, <span class="kw">typename</span> V<span class="op">&gt;</span></span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> std<span class="op">::</span>tag_invocable<span class="op">&lt;</span>contains_t, R<span class="op">&amp;&amp;</span>, <span class="kw">const</span> V<span class="op">&amp;&gt;</span></span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">bool</span> <span class="kw">operator</span><span class="op">()(</span>R<span class="op">&amp;&amp;</span> rng, <span class="kw">const</span> V<span class="op">&amp;</span> value<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a>        <span class="kw">noexcept</span><span class="op">(</span>std<span class="op">::</span>is_nothrow_tag_invocable_v<span class="op">&lt;</span>contains_t, R<span class="op">&amp;&amp;</span>, <span class="kw">const</span> V<span class="op">&amp;&gt;)</span> <span class="op">{</span></span>
<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> std<span class="op">::</span>tag_invoke<span class="op">(</span>contains_t<span class="op">{}</span>, <span class="op">(</span>R<span class="op">&amp;&amp;)</span>rng, value<span class="op">)</span>;</span>
<span id="cb33-8"><a href="#cb33-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb33-9"><a href="#cb33-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-10"><a href="#cb33-10" aria-hidden="true" tabindex="-1"></a>    <span class="co">// A default implementation if no custom implementation is defined.</span></span>
<span id="cb33-11"><a href="#cb33-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span>range R, <span class="kw">typename</span> V<span class="op">&gt;</span></span>
<span id="cb33-12"><a href="#cb33-12" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="op">(!</span>std<span class="op">::</span>tag_invocable<span class="op">&lt;</span>foo_t, <span class="kw">const</span> T<span class="op">&amp;</span>, <span class="kw">const</span> U<span class="op">&amp;&gt;)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb33-13"><a href="#cb33-13" aria-hidden="true" tabindex="-1"></a>               std<span class="op">::</span>equality_comparable<span class="op">&lt;</span></span>
<span id="cb33-14"><a href="#cb33-14" aria-hidden="true" tabindex="-1"></a>                 std<span class="op">::</span>ranges<span class="op">::</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, V<span class="op">&gt;</span></span>
<span id="cb33-15"><a href="#cb33-15" aria-hidden="true" tabindex="-1"></a>    <span class="dt">bool</span> <span class="kw">operator</span><span class="op">()(</span>R<span class="op">&amp;&amp;</span> rng, <span class="kw">const</span> V<span class="op">&amp;</span> value<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb33-16"><a href="#cb33-16" aria-hidden="true" tabindex="-1"></a>      <span class="cf">for</span> <span class="op">(</span><span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> x <span class="op">:</span> rng<span class="op">)</span> <span class="op">{</span></span>
<span id="cb33-17"><a href="#cb33-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>x <span class="op">==</span> value<span class="op">)</span> <span class="cf">return</span> <span class="kw">true</span>;</span>
<span id="cb33-18"><a href="#cb33-18" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb33-19"><a href="#cb33-19" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="kw">false</span>;</span>
<span id="cb33-20"><a href="#cb33-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb33-21"><a href="#cb33-21" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb33-22"><a href="#cb33-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-23"><a href="#cb33-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">inline</span> <span class="kw">constexpr</span> foo_t foo<span class="op">{}</span>;</span>
<span id="cb33-24"><a href="#cb33-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Note that there is no longer a need to define the CPO and the
instance of the function object in a nested namespace; as well as no
need to define a poison-pill overload of the customisation-point. The
<code class="sourceCode default">std::tag_invoke</code> CPO handles
these aspects centrally.</p>
<p>A type can customise this CPO by defining an overload of
<code class="sourceCode default">tag_invoke</code>. e.g.</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> integer_set <span class="op">{</span></span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span><span class="dt">uint32_t</span> size_;</span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>unique_ptr<span class="op">&lt;</span>std<span class="op">::</span><span class="dt">uint32_t</span><span class="op">[]&gt;</span> bits_;</span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ... iterator, begin(), end() etc. omitted for brevity.</span></span>
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> U<span class="op">&gt;</span></span>
<span id="cb34-7"><a href="#cb34-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">bool</span> tag_invoke<span class="op">(</span>std<span class="op">::</span>tag_t<span class="op">&lt;</span>N<span class="op">::</span>contains<span class="op">&gt;</span>,</span>
<span id="cb34-8"><a href="#cb34-8" aria-hidden="true" tabindex="-1"></a>                         <span class="kw">const</span> bit_set<span class="op">&amp;</span> self, std<span class="op">::</span><span class="dt">uint32_t</span> value<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb34-9"><a href="#cb34-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>value <span class="op">&gt;=</span> size<span class="op">)</span> <span class="cf">return</span> <span class="kw">false</span>;</span>
<span id="cb34-10"><a href="#cb34-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">(</span>bits<span class="op">[</span>value <span class="op">/</span> <span class="dv">32</span><span class="op">]</span> <span class="op">&gt;&gt;</span> <span class="op">(</span>value <span class="op">&amp;</span> <span class="dv">31</span><span class="op">))</span> <span class="op">!=</span> <span class="dv">0</span>;</span>
<span id="cb34-11"><a href="#cb34-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb34-12"><a href="#cb34-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Also, with <code class="sourceCode default">tag_invoke</code>, a
generic wrapper can customise and forward calls to many CPOs
generically. e.g.</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Inner<span class="op">&gt;</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> wrapper <span class="op">{</span></span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a>  Inner inner;</span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> CPO, <span class="kw">typename</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb35-6"><a href="#cb35-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> std<span class="op">::</span>invocable<span class="op">&lt;</span>CPO, Inner, Args<span class="op">...&gt;</span></span>
<span id="cb35-7"><a href="#cb35-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> tag_invoke<span class="op">(</span>CPO cpo, wrapper<span class="op">&amp;&amp;</span> self, Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span></span>
<span id="cb35-8"><a href="#cb35-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">noexcept</span><span class="op">(</span>std<span class="op">::</span>is_nothrow_invocable_v<span class="op">&lt;</span>CPO, Inner, Args<span class="op">...&gt;)</span> <span class="op">{</span></span>
<span id="cb35-9"><a href="#cb35-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> cpo<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>self<span class="op">).</span>inner, std<span class="op">::</span>forward<span class="op">&lt;</span>Args<span class="op">&gt;(</span>args<span class="op">)...)</span>;</span>
<span id="cb35-10"><a href="#cb35-10" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb35-11"><a href="#cb35-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>This can be used for building generic type-erasing wrappers, or types
that generically forward through queries to wrapped types (e.g. this is
used often when writing <span class="citation" data-cites="P2300R4">[<a href="#ref-P2300R4" role="doc-biblioref">P2300R4</a>]</span> receiver
types).</p>
<p>There are still some problems / limitations with
<code class="sourceCode default">tag_invoke</code>, however.</p>
<h3 data-number="7.4.1" id="still-lots-of-boiler-plate-to-define-a-new-cpo"><span class="header-section-number">7.4.1</span> Still lots of boiler-plate to
define a new CPO<a href="#still-lots-of-boiler-plate-to-define-a-new-cpo" class="self-link"></a></h3>
<p>While the amount of boiler-plate has been reduced compared to
<code class="sourceCode default">std::ranges</code>-style CPOs, there is
still a need to define a <code class="sourceCode default">struct</code>
with <code class="sourceCode default">operator()</code> overloads that
detect whether customisations are defined and conditionally forward to
the customisation or to the default implementation.</p>
<h3 data-number="7.4.2" id="syntax-for-customisations-is-more-cumbersome"><span class="header-section-number">7.4.2</span> Syntax for customisations is
more cumbersome<a href="#syntax-for-customisations-is-more-cumbersome" class="self-link"></a></h3>
<p>Defining customisations requires defining a
<code class="sourceCode default">tag_invoke()</code> overload rather
than defining a overload of a function named after the operation you are
customising.</p>
<h3 data-number="7.4.3" id="potential-for-very-large-overload-set"><span class="header-section-number">7.4.3</span> Potential for very large
overload-set<a href="#potential-for-very-large-overload-set" class="self-link"></a></h3>
<p>As every customisation of
<code class="sourceCode default">tag_invoke</code>-based CPOs
necessarily defines a
<code class="sourceCode default">tag_invoke()</code> overload, this
means that all <code class="sourceCode default">tag_invoke()</code>
overloads defined for all associated types of all arguments to a CPO
will be considered when resolving the appropriate overload to a call to
a CPO.</p>
<p>This can potentially lead to increased compile-times for types that
add a lot of <code class="sourceCode default">tag_invoke</code>-based
customisations; if that is not bad enough, diagnostic size just
explodes.</p>
<p>Overload set sizes can be reduced somewhat by careful use of
hidden-friend definitions and ADL isolation techniques <span class="citation" data-cites="Odwyer2019">[<a href="#ref-Odwyer2019" role="doc-biblioref">O’Dwyer2019</a>]</span> for class templates.
However, types that need to customise a large number of CPOs will still
have an overload-resolution cost proportional to the number of CPOs that
they customise.</p>
<p>Specifically, <strong>the overload set size grows with the
<em>product</em> of <em>cpo-count</em> and <em>argument count</em>
</strong>, and that is <em>if</em> one studiously follows hidden-friend
cleanliness; if one does not, the size also grows with the number of all
specializations in all associated namespaces.</p>
<p>Note that raw ADL does not usually have the same problem as different
names are typically used for each customisation point and so overload
resolution only needs to consider functions with the same name as the
function currently being called and can ignore overloads for other
customisation points, thus removing an entire growth factor.</p>
<h3 data-number="7.4.4" id="forwarding-layers-inhibit-copy-elision"><span class="header-section-number">7.4.4</span> Forwarding layers inhibit
copy-elision<a href="#forwarding-layers-inhibit-copy-elision" class="self-link"></a></h3>
<p>The <code class="sourceCode default">tag_invoke</code> approach
inherits the downsides of CPOs regarding inhibiting copy-elision of
arguments as it also introduces a layer of forwarding through the
<code class="sourceCode default">operator()</code> function.</p>
<p>Also, as implementations generally dispatch to
<code class="sourceCode default">tag_invoke()</code> through the
<code class="sourceCode default">std::tag_invoke()</code> CPO rather
than doing direct ADL calls, this usually introduces <em>two</em> levels
of forwarding, increasing the debug runtime and function template
instantiation costs compared with
<code class="sourceCode default">std::ranges</code>-style CPOs.</p>
<p>Summary:</p>
<ul>
<li>Syntax is cumbersome</li>
<li>Lots of boiler-plate to declare a CPO</li>
<li>Syntax for customising is more verbose / harder to follow than
ADL</li>
<li>Potentially very large overload set</li>
<li>Requires everyone to play nice and define
<code class="sourceCode default">tag_invoke</code> overloads as hidden
friends</li>
</ul>
<h3 data-number="7.4.5" id="compile-errors-are-difficult-to-diagnose"><span class="header-section-number">7.4.5</span> Compile Errors are difficult
to diagnose<a href="#compile-errors-are-difficult-to-diagnose" class="self-link"></a></h3>
<p>If you attempt to call a
<code class="sourceCode default">tag_invoke</code>-based CPO with
arguments that do not match an available customisation /
default-implementation, the compile-errors can be difficult to
wade-through.</p>
<p>There are two levels of forwarding and indirection which add extra
lines to the diagnostic output, plus the compiler needs to list all of
the <code class="sourceCode default">tag_invoke</code> overloads it
considered when looking for a valid call - which might be a large list
containing <code class="sourceCode default">tag_invoke()</code>
overloads unrelated to the call.</p>
<h1 data-number="8" id="use-cases"><span class="header-section-number">8</span> Use-cases<a href="#use-cases" class="self-link"></a></h1>
<p>This section discusses some of the use-cases for customisable
functions proposed in this paper.</p>
<h2 data-number="8.1" id="basis-operations"><span class="header-section-number">8.1</span> Basis operations<a href="#basis-operations" class="self-link"></a></h2>
<p>We can use customisable functions to declare a set of basis
operations that are included in a generic concept.</p>
<p>Basis operations are operations that do not have any default
implementation and that need to be customised for a given type (or set
of types) before they can be called.</p>
<p>For example, the
<code class="sourceCode default">std::ranges::begin</code> and
<code class="sourceCode default">std::range::end</code> CPOs are basis
operations for implementing the <em>range</em> concept. They have no
default implementation and they can be customised either by defining a
member function or a namespace-scope function found by ADL.</p>
<p>For the receiver concept defined in <span class="citation" data-cites="P2300R0">[<a href="#ref-P2300R0" role="doc-biblioref">P2300R0</a>]</span>
<code class="sourceCode default">std::execution</code> paper, there are
three separate basis operations;
<code class="sourceCode default">set_value(receiver, values…)</code>,
<code class="sourceCode default">set_error(receiver, error)</code> and
<code class="sourceCode default">set_done(receiver)</code>.</p>
<h2 data-number="8.2" id="customisable-algorithms"><span class="header-section-number">8.2</span> Customisable algorithms<a href="#customisable-algorithms" class="self-link"></a></h2>
<p>Customisable algorithms are another major use-case for this
proposal.</p>
<p>A customisable algorithm differs from a basis-function in that it has
a default implementation that is implemented in terms of some other set
of basis operations. If a customisation of the algorithm is not provided
for a particular set of argument types then the call to a customisable
algorithm dispatches to a default implementation implemented generically
in terms of some basis operations implemented by the arguments (which
are typically constrained to require such basis operations for all
overloads).</p>
<h2 data-number="8.3" id="wrapper-types"><span class="header-section-number">8.3</span> Wrapper types<a href="#wrapper-types" class="self-link"></a></h2>
<p>One of the use-cases that needs to be supported for <span class="citation" data-cites="P2300R5">[<a href="#ref-P2300R5" role="doc-biblioref">P2300R5</a>]</span>-style customisation points is
the ability to generically customise many customisation points and
forward them on to a wrapped object.</p>
<p>This is used extensively in the definition of receiver types, which
often need to customise an open set of queries about the calling context
and forward them on to the parent receiver if the answer is not known
locally.</p>
<p>For example, a receiver defined using
<code class="sourceCode default">tag_invoke</code> proposed by <span class="citation" data-cites="P2300R5">[<a href="#ref-P2300R5" role="doc-biblioref">P2300R5</a>]</span> often looks like this:</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, typenname<span class="op">...</span> Ts<span class="op">&gt;</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> one_of <span class="op">=</span> <span class="op">(</span>std<span class="op">::</span>same_as<span class="op">&lt;</span>T, Ts<span class="op">&gt;</span> <span class="op">||</span> <span class="op">...)</span>;</span>
<span id="cb36-3"><a href="#cb36-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="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> completion_signal <span class="op">=</span> one_of<span class="op">&lt;</span>T, std<span class="op">::</span>tag_t<span class="op">&lt;</span>std<span class="op">::</span>execution<span class="op">::</span>set_value<span class="op">&gt;</span>,</span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a>                                      std<span class="op">::</span>tag_t<span class="op">&lt;</span>std<span class="op">::</span>execution<span class="op">::</span>set_error<span class="op">&gt;</span>,</span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a>                                      std<span class="op">::</span>tag_t<span class="op">&lt;</span>std<span class="op">::</span>execution<span class="op">::</span>set_done<span class="op">&gt;&gt;</span>;</span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-8"><a href="#cb36-8" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> ParentReceiver<span class="op">&gt;</span></span>
<span id="cb36-9"><a href="#cb36-9" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> my_receiver <span class="op">{</span></span>
<span id="cb36-10"><a href="#cb36-10" aria-hidden="true" tabindex="-1"></a>  my_operation_state<span class="op">&lt;</span>ParentReceiver<span class="op">&gt;*</span> op;</span>
<span id="cb36-11"><a href="#cb36-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-12"><a href="#cb36-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">void</span> tag_invoke<span class="op">(</span>tag_t<span class="op">&lt;</span>std<span class="op">::</span>execution<span class="op">::</span>set_value<span class="op">&gt;</span>,</span>
<span id="cb36-13"><a href="#cb36-13" aria-hidden="true" tabindex="-1"></a>                         my_receiver<span class="op">&amp;&amp;</span> r, <span class="dt">int</span> value<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb36-14"><a href="#cb36-14" aria-hidden="true" tabindex="-1"></a>    <span class="co">// transform the result and forward to parent receiver</span></span>
<span id="cb36-15"><a href="#cb36-15" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>execution<span class="op">::</span>set_value<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>r<span class="op">.</span>op<span class="op">-&gt;</span>receiver<span class="op">)</span>, value <span class="op">*</span> <span class="dv">2</span><span class="op">)</span>;</span>
<span id="cb36-16"><a href="#cb36-16" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb36-17"><a href="#cb36-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-18"><a href="#cb36-18" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Forward through error/done unchanged</span></span>
<span id="cb36-19"><a href="#cb36-19" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Error<span class="op">&gt;</span></span>
<span id="cb36-20"><a href="#cb36-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">void</span> tag_invoke<span class="op">(</span>tag_t<span class="op">&lt;</span>std<span class="op">::</span>execution<span class="op">::</span>set_error<span class="op">&gt;</span>,</span>
<span id="cb36-21"><a href="#cb36-21" aria-hidden="true" tabindex="-1"></a>                         my_receiver<span class="op">&amp;&amp;</span> r, Error<span class="op">&amp;&amp;</span> error<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb36-22"><a href="#cb36-22" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>execution<span class="op">::</span>set_error<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>r<span class="op">.</span>op<span class="op">-&gt;</span>receiver<span class="op">)</span>, std<span class="op">::</span>forward<span class="op">&lt;</span>Error<span class="op">&gt;(</span>error<span class="op">))</span>;</span>
<span id="cb36-23"><a href="#cb36-23" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb36-24"><a href="#cb36-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-25"><a href="#cb36-25" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">void</span> tag_invoke<span class="op">(</span>tag_t<span class="op">&lt;</span>std<span class="op">::</span>execution<span class="op">::</span>set_done<span class="op">&gt;</span>, my_receiver<span class="op">&amp;&amp;</span> r<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb36-26"><a href="#cb36-26" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>execution<span class="op">::</span>set_done<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>r<span class="op">.</span>op<span class="op">-&gt;</span>receiver<span class="op">))</span>;</span>
<span id="cb36-27"><a href="#cb36-27" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb36-28"><a href="#cb36-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb36-29"><a href="#cb36-29" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Generically forward through any receiver query supported upstream.</span></span>
<span id="cb36-30"><a href="#cb36-30" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> CPO<span class="op">&gt;</span></span>
<span id="cb36-31"><a href="#cb36-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="op">(!</span>completion_signal<span class="op">&lt;</span>CPO<span class="op">&gt;)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb36-32"><a href="#cb36-32" aria-hidden="true" tabindex="-1"></a>             std<span class="op">::</span>invocable<span class="op">&lt;</span>CPO, <span class="kw">const</span> ParentReceiver<span class="op">&amp;&gt;</span></span>
<span id="cb36-33"><a href="#cb36-33" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="kw">auto</span> tag_invoke<span class="op">(</span>CPO cpo, <span class="kw">const</span> my_receiver<span class="op">&amp;</span> r<span class="op">)</span></span>
<span id="cb36-34"><a href="#cb36-34" aria-hidden="true" tabindex="-1"></a>      <span class="kw">noexcept</span><span class="op">(</span>std<span class="op">::</span>is_nothrow_invocable_v<span class="op">&lt;</span>CPO, <span class="kw">const</span> ParentReceiver<span class="op">&amp;&gt;)</span></span>
<span id="cb36-35"><a href="#cb36-35" aria-hidden="true" tabindex="-1"></a>      <span class="op">-&gt;</span> std<span class="op">::</span>invoke_result_t<span class="op">&lt;</span>CPO, <span class="kw">const</span> ParentReceiver<span class="op">&amp;&gt;</span> <span class="op">{</span></span>
<span id="cb36-36"><a href="#cb36-36" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> cpo<span class="op">(</span>std<span class="op">::</span>as_const<span class="op">(</span>r<span class="op">.</span>op<span class="op">-&gt;</span>receiver<span class="op">))</span>;</span>
<span id="cb36-37"><a href="#cb36-37" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb36-38"><a href="#cb36-38" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Another use-case for building generic forwarding wrappers types is
building generic type-erasing wrappers.</p>
<p>For example, the <code class="sourceCode default">libunifex::any_unique&lt;CPOs…&gt;</code>
type defines a type-erasing wrapper that can generically type-erase any
type that satisfies the set of CPOs.</p>
<div class="sourceCode" id="cb37"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="dt">float</span> width<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> x<span class="op">)</span> customisable;   <span class="co">// this paper, or as-if tag_invoke CPO</span></span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a><span class="dt">float</span> height<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> x<span class="op">)</span> customisable;</span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a><span class="dt">float</span> area<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> x<span class="op">)</span> customisable;</span>
<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-5"><a href="#cb37-5" 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="cb37-6"><a href="#cb37-6" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> shape <span class="op">=</span> <span class="kw">requires</span><span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb37-7"><a href="#cb37-7" aria-hidden="true" tabindex="-1"></a>  width<span class="op">(</span>x<span class="op">)</span>;</span>
<span id="cb37-8"><a href="#cb37-8" aria-hidden="true" tabindex="-1"></a>  height<span class="op">(</span>x<span class="op">)</span>;</span>
<span id="cb37-9"><a href="#cb37-9" aria-hidden="true" tabindex="-1"></a>  area<span class="op">(</span>x<span class="op">)</span>;</span>
<span id="cb37-10"><a href="#cb37-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb37-11"><a href="#cb37-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-12"><a href="#cb37-12" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> square <span class="op">{</span></span>
<span id="cb37-13"><a href="#cb37-13" aria-hidden="true" tabindex="-1"></a>  <span class="dt">float</span> size;</span>
<span id="cb37-14"><a href="#cb37-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">float</span> width<span class="op">(</span><span class="kw">const</span> square<span class="op">&amp;</span> self<span class="op">)</span> <span class="kw">override</span> <span class="op">{</span> <span class="cf">return</span> size; <span class="op">}</span></span>
<span id="cb37-15"><a href="#cb37-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">float</span> height<span class="op">(</span><span class="kw">const</span> square<span class="op">&amp;</span> self<span class="op">)</span> <span class="kw">override</span> <span class="op">{</span> <span class="cf">return</span> size; <span class="op">}</span></span>
<span id="cb37-16"><a href="#cb37-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">float</span> area<span class="op">(</span><span class="kw">const</span> square<span class="op">&amp;</span> self<span class="op">)</span> <span class="kw">override</span> <span class="op">{</span> <span class="cf">return</span> size <span class="op">*</span> size; <span class="op">}</span></span>
<span id="cb37-17"><a href="#cb37-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb37-18"><a href="#cb37-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-19"><a href="#cb37-19" aria-hidden="true" tabindex="-1"></a><span class="co">// Define a type-erased type in terms of a set of CPO signatures.</span></span>
<span id="cb37-20"><a href="#cb37-20" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> any_shape <span class="op">=</span> unifex<span class="op">::</span>any_unique<span class="op">&lt;</span></span>
<span id="cb37-21"><a href="#cb37-21" aria-hidden="true" tabindex="-1"></a>  unifex<span class="op">::</span>overload<span class="op">&lt;</span><span class="dt">float</span><span class="op">(</span><span class="kw">const</span> unifex<span class="op">::</span>this_<span class="op">&amp;)&gt;(</span>width<span class="op">)</span>,</span>
<span id="cb37-22"><a href="#cb37-22" aria-hidden="true" tabindex="-1"></a>  unifex<span class="op">::</span>overload<span class="op">&lt;</span><span class="dt">float</span><span class="op">(</span><span class="kw">const</span> unifex<span class="op">::</span>this_<span class="op">&amp;)&gt;(</span>height<span class="op">)</span>,</span>
<span id="cb37-23"><a href="#cb37-23" aria-hidden="true" tabindex="-1"></a>  unifex<span class="op">::</span>overload<span class="op">&lt;</span><span class="dt">float</span><span class="op">(</span><span class="kw">const</span> unifex<span class="op">::</span>this_<span class="op">&amp;)&gt;(</span>area<span class="op">)&gt;</span>;</span>
<span id="cb37-24"><a href="#cb37-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb37-25"><a href="#cb37-25" aria-hidden="true" tabindex="-1"></a>any_shape s <span class="op">=</span> square<span class="op">{</span><span class="fl">2.0</span><span class="bu">f</span><span class="op">}</span>;</span>
<span id="cb37-26"><a href="#cb37-26" aria-hidden="true" tabindex="-1"></a><span class="ot">assert</span><span class="op">(</span>width<span class="op">(</span>s<span class="op">)</span> <span class="op">==</span> <span class="fl">2.0</span><span class="bu">f</span><span class="op">)</span>;</span>
<span id="cb37-27"><a href="#cb37-27" aria-hidden="true" tabindex="-1"></a><span class="ot">assert</span><span class="op">(</span>height<span class="op">(</span>s<span class="op">)</span> <span class="op">==</span> <span class="fl">2.0</span><span class="bu">f</span><span class="op">)</span>;</span>
<span id="cb37-28"><a href="#cb37-28" aria-hidden="true" tabindex="-1"></a><span class="ot">assert</span><span class="op">(</span>area<span class="op">(</span>s<span class="op">)</span> <span class="op">==</span> <span class="fl">4.0</span><span class="bu">f</span><span class="op">)</span>;</span></code></pre></div>
<p>Building a generic type-erasing wrapper that can be used with any set
of customisable-functions is made possible by the ability to generically
customise on a CPO without needing to know its name. This ability is
discussed further in <a href="#generic-forwarding">Generic
forwarding</a>.</p>
<p>Other type-erasing wrapper types are possible that make different
choices on storage, copyability/movability, ownership, comparability
axes.</p>
<h1 data-number="9" id="design"><span class="header-section-number">9</span> Design<a href="#design" class="self-link"></a></h1>
<p>A <strong>customisable function prototype</strong> is a
namespace-scope function declaration with the
<code class="sourceCode default">customisable</code>
<em>virt-specifier</em>.</p>
<p>Calls to customisable functions dispatch to the appropriate
customisation or default implementation based on the static types of the
arguments to that call.</p>
<h2 data-number="9.1" id="declaring-customisable-functions"><span class="header-section-number">9.1</span> Declaring customisable
functions<a href="#declaring-customisable-functions" class="self-link"></a></h2>
<p>A namespace-scope function declarator declares a customisable
function prototype if the declaration contains the
<code class="sourceCode default">customisable</code> keyword in its
function-specifier. The keyword is placed in the same syntactic location
of the function definition that the
<code class="sourceCode default">override</code> and
<code class="sourceCode default">final</code> keywords are placed for
member functions. i.e. after the
<code class="sourceCode default">noexcept</code> and any trailing return
type.</p>
<div class="sourceCode" id="cb38"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> containers <span class="op">{</span></span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, std<span class="op">::</span>unsigned_integral InitialValue<span class="op">&gt;</span></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a>  InitialValue hash<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> value, InitialValue iv<span class="op">)</span> <span class="kw">noexcept</span> customisable;</span>
<span id="cb38-4"><a href="#cb38-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Note that the declaration of a customisable function prototype is
always a template (otherwise it wouldn’t be customisable).</p>
<p>It is ill-formed to declare a normal function of the same name as a
customisable function in the same namespace as the latter declares the
name to be an object or variable template.</p>
<h2 data-number="9.2" id="customisable-function-objects"><span class="header-section-number">9.2</span> Customisable function objects<a href="#customisable-function-objects" class="self-link"></a></h2>
<p>A customisable function declaration introduces a Customisation
Function Object (CFO), which is a
<code class="sourceCode default">constexpr</code> object of an
unspecified, implementation-generated trivial type with no data
members.</p>
<p>A CFO exists as a way to name the customisable function and can be
copied and passed around as an object that represents the overload set
of all implementations of this function. It allows the implementation of
generic forwarders, and can more generally be used to pass an overload
set generically.</p>
<p>Neither default implementations or customisations are member
functions of CFOs, and a CFO doesn’t have call operators either.
Instead, a call expression on a CFO triggers lookup and overload
resolutions specific to customisable functions.</p>
<p>A CFO’s type cannot be used as a base-class (similar to
function-types). CFO types are default-constructible. All objects of a
given CFO type are structurally identical and are usable as NTTPs.
Members of CFO type are implicitly
<code class="sourceCode default">[[no_unique_address]]</code>.</p>
<h2 data-number="9.3" id="declaring-customizations-and-default-implementations"><span class="header-section-number">9.3</span> Declaring Customizations and
Default Implementations<a href="#declaring-customizations-and-default-implementations" class="self-link"></a></h2>
<p>Customisations and Default Implementations are implementations of
Customisable Functions.</p>
<p>They form separate overload sets: only if overload resolution finds
no suitable customisations do we look for a default implementation.</p>
<p>A customisable function can have multiple default implementations and
multiple customisations. Default implementations and customisations are
never found by normal lookup. It is not possible to take their
address.</p>
<h3 data-number="9.3.1" id="declaring-default-implementations"><span class="header-section-number">9.3.1</span> Declaring default
implementations<a href="#declaring-default-implementations" class="self-link"></a></h3>
<p>We can declare zero or more default implementations or implementation
templates for any customizable function.</p>
<p>Default implementations are only considered during overload
resolution if no viable customisation of the function is found.</p>
<p>Default implementations are overloads of the customisable function
that are declared with the
<code class="sourceCode default">default</code> keyword. The keyword is
placed in the same syntactic location as
<code class="sourceCode default">customisable</code>, ie where the
<code class="sourceCode default">override</code> and
<code class="sourceCode default">final</code> keywords are placed for
member functions, after the
<code class="sourceCode default">noexcept</code> and any trailing return
type.</p>
<p>A default implementation is declared as a separate declaration after
the prototype. This is because the
<code class="sourceCode default">noexcept</code> clause, constraints and
return type of default (and overrides) functions are not handled the
same way as in the prototypes declaration, and keeping them separate
keeps the design simpler.</p>
<p>Example: Declaring a hypothetical customisable
<code class="sourceCode default">std::ranges::contains()</code>
algorithm with a default implementation provided at the point of
declaration.</p>
<div class="sourceCode" id="cb39"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>input_range R, <span class="kw">typename</span> V<span class="op">&gt;</span></span>
<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> equality_comparable_with<span class="op">&lt;</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, <span class="kw">const</span> V<span class="op">&amp;&gt;</span></span>
<span id="cb39-4"><a href="#cb39-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> contains<span class="op">(</span>R<span class="op">&amp;&amp;</span> range, <span class="kw">const</span> V<span class="op">&amp;</span> value<span class="op">)</span> customisable;</span>
<span id="cb39-5"><a href="#cb39-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb39-6"><a href="#cb39-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>input_range R, <span class="kw">typename</span> V<span class="op">&gt;</span></span>
<span id="cb39-7"><a href="#cb39-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> equality_comparable_with<span class="op">&lt;</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, <span class="kw">const</span> V<span class="op">&amp;&gt;</span></span>
<span id="cb39-8"><a href="#cb39-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> contains<span class="op">(</span>R<span class="op">&amp;&amp;</span> range, <span class="kw">const</span> V<span class="op">&amp;</span> value<span class="op">)</span> <span class="cf">default</span> <span class="op">{</span></span>
<span id="cb39-9"><a href="#cb39-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> x <span class="op">:</span> range<span class="op">)</span> <span class="op">{</span></span>
<span id="cb39-10"><a href="#cb39-10" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>x <span class="op">==</span> value<span class="op">)</span></span>
<span id="cb39-11"><a href="#cb39-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="kw">true</span>;</span>
<span id="cb39-12"><a href="#cb39-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb39-13"><a href="#cb39-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">false</span>;</span>
<span id="cb39-14"><a href="#cb39-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb39-15"><a href="#cb39-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>It is also valid to forward-declare a default implementation and
define it later. e.g. we could write</p>
<div class="sourceCode" id="cb40"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Declaration of customisable function.</span></span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>input_range R, <span class="kw">typename</span> V<span class="op">&gt;</span></span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> equality_comparable_with<span class="op">&lt;</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, <span class="kw">const</span> V<span class="op">&amp;&gt;</span></span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> contains<span class="op">(</span>R<span class="op">&amp;&amp;</span> range, <span class="kw">const</span> V<span class="op">&amp;</span> value<span class="op">)</span> customisable;</span>
<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-7"><a href="#cb40-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Forward declaration of default implementation.</span></span>
<span id="cb40-8"><a href="#cb40-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>input_range R, <span class="kw">typename</span> V<span class="op">&gt;</span></span>
<span id="cb40-9"><a href="#cb40-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> equality_comparable_with<span class="op">&lt;</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, <span class="kw">const</span> V<span class="op">&amp;&gt;</span></span>
<span id="cb40-10"><a href="#cb40-10" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> contains<span class="op">(</span>R<span class="op">&amp;&amp;</span> range, <span class="kw">const</span> V<span class="op">&amp;</span> value<span class="op">)</span> <span class="cf">default</span>;</span>
<span id="cb40-11"><a href="#cb40-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb40-12"><a href="#cb40-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-13"><a href="#cb40-13" aria-hidden="true" tabindex="-1"></a><span class="co">// ... later</span></span>
<span id="cb40-14"><a href="#cb40-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-15"><a href="#cb40-15" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb40-16"><a href="#cb40-16" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Definition of default implementation.</span></span>
<span id="cb40-17"><a href="#cb40-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>input_range R, <span class="kw">typename</span> V<span class="op">&gt;</span></span>
<span id="cb40-18"><a href="#cb40-18" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> equality_comparable_with<span class="op">&lt;</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, <span class="kw">const</span> V<span class="op">&amp;&gt;</span></span>
<span id="cb40-19"><a href="#cb40-19" aria-hidden="true" tabindex="-1"></a>  <span class="dt">bool</span> contains<span class="op">(</span>R<span class="op">&amp;&amp;</span> range, <span class="kw">const</span> V<span class="op">&amp;</span> value<span class="op">)</span> <span class="cf">default</span> <span class="op">{</span></span>
<span id="cb40-20"><a href="#cb40-20" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> x <span class="op">:</span> range<span class="op">)</span> <span class="op">{</span></span>
<span id="cb40-21"><a href="#cb40-21" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>x <span class="op">==</span> value<span class="op">)</span> <span class="cf">return</span> <span class="kw">true</span>;</span>
<span id="cb40-22"><a href="#cb40-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb40-23"><a href="#cb40-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">false</span>;</span>
<span id="cb40-24"><a href="#cb40-24" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb40-25"><a href="#cb40-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If we wanted to make a customisable sender algorithm, customisations
might only be required to return some type that satisfies the sender
concept, whereas the default implementation will need to return a
particular sender-type (something that we wouldn’t want all
customisations to have to return). In this case we need to declare the
customisation point with general constraints on the return type, and
define a default implementation that returns a particular concrete type
that satisfies those constraints. e.g.</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution <span class="op">{</span></span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Declaration of customisation-point defines only general constraints.</span></span>
<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>sender S, <span class="kw">typename</span> F<span class="op">&gt;</span></span>
<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> invocable<span class="op">-</span>with<span class="op">-</span>sender<span class="op">-</span>value<span class="op">-</span>results<span class="op">&lt;</span>F, S<span class="op">&gt;</span></span>
<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a>  sender <span class="kw">auto</span> then<span class="op">(</span>S<span class="op">&amp;&amp;</span> src, F<span class="op">&amp;&amp;</span> func<span class="op">)</span> customisable;</span>
<span id="cb41-6"><a href="#cb41-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb41-7"><a href="#cb41-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Class used by default implementation. Satisfies &#39;sender&#39; concept.</span></span>
<span id="cb41-8"><a href="#cb41-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>sender S, <span class="kw">typename</span> F<span class="op">&gt;</span></span>
<span id="cb41-9"><a href="#cb41-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> default_then_sender <span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb41-10"><a href="#cb41-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb41-11"><a href="#cb41-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Default implementation returns a particular implementation.</span></span>
<span id="cb41-12"><a href="#cb41-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>sender S, <span class="kw">typename</span> F<span class="op">&gt;</span></span>
<span id="cb41-13"><a href="#cb41-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> invocable<span class="op">-</span>with<span class="op">-</span>sender<span class="op">-</span>value<span class="op">-</span>results<span class="op">&lt;</span>F, S<span class="op">&gt;</span></span>
<span id="cb41-14"><a href="#cb41-14" aria-hidden="true" tabindex="-1"></a>  default_then_sender<span class="op">&lt;</span>remove_cvref_t<span class="op">&lt;</span>S<span class="op">&gt;</span>, remove_cvref_t<span class="op">&lt;</span>F<span class="op">&gt;&gt;</span></span>
<span id="cb41-15"><a href="#cb41-15" aria-hidden="true" tabindex="-1"></a>  then<span class="op">(</span>S<span class="op">&amp;&amp;</span> src, F<span class="op">&amp;&amp;</span> func<span class="op">)</span> <span class="cf">default</span> <span class="op">{</span></span>
<span id="cb41-16"><a href="#cb41-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">...</span>;</span>
<span id="cb41-17"><a href="#cb41-17" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb41-18"><a href="#cb41-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>We can also declare a customisable function with default
implementations that are only valid for types that satisfy some
additional constraints.</p>
<p>For example: Declaring the
<code class="sourceCode default">swap()</code> customisable function
(which permits swapping between any two types) but only providing a
default that works with types that are
move-constructible/move-assignable.</p>
<div class="sourceCode" id="cb42"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb42-2"><a href="#cb42-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="cb42-3"><a href="#cb42-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> swap<span class="op">(</span>T<span class="op">&amp;&amp;</span> t, U<span class="op">&amp;&amp;</span> u<span class="op">)</span> customisable;</span>
<span id="cb42-4"><a href="#cb42-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb42-5"><a href="#cb42-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> V<span class="op">&gt;</span></span>
<span id="cb42-6"><a href="#cb42-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> std<span class="op">::</span>move_constructible<span class="op">&lt;</span>V<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> std<span class="op">::</span>assignable_from<span class="op">&lt;</span>V<span class="op">&amp;</span>, V<span class="op">&amp;&amp;&gt;</span></span>
<span id="cb42-7"><a href="#cb42-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> swap<span class="op">(</span>V<span class="op">&amp;</span> t, V<span class="op">&amp;</span> u<span class="op">)</span></span>
<span id="cb42-8"><a href="#cb42-8" aria-hidden="true" tabindex="-1"></a>      <span class="kw">noexcept</span><span class="op">(</span>std<span class="op">::</span>is_nothrow_move_constructible_v<span class="op">&lt;</span>V<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb42-9"><a href="#cb42-9" aria-hidden="true" tabindex="-1"></a>               std<span class="op">::</span>is_nothrow_assignable_v<span class="op">&lt;</span>V<span class="op">&amp;</span>, V<span class="op">&gt;)</span> <span class="cf">default</span> <span class="op">{</span></span>
<span id="cb42-10"><a href="#cb42-10" aria-hidden="true" tabindex="-1"></a>    V tmp <span class="op">=</span> std<span class="op">::</span>move<span class="op">(</span>t<span class="op">)</span>;</span>
<span id="cb42-11"><a href="#cb42-11" aria-hidden="true" tabindex="-1"></a>    t <span class="op">=</span> std<span class="op">::</span>move<span class="op">(</span>u<span class="op">)</span>;</span>
<span id="cb42-12"><a href="#cb42-12" aria-hidden="true" tabindex="-1"></a>    u <span class="op">=</span> std<span class="op">::</span>move<span class="op">(</span>tmp<span class="op">)</span>;</span>
<span id="cb42-13"><a href="#cb42-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb42-14"><a href="#cb42-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 data-number="9.3.2" id="multiple-default-overloads-can-be-defined."><span class="header-section-number">9.3.2</span> Multiple default overloads
can be defined.<a href="#multiple-default-overloads-can-be-defined." class="self-link"></a></h3>
<p>For example, we can extend the above
<code class="sourceCode default">swap()</code> example to also define a
default for swapping arrays.</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb43-2"><a href="#cb43-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="cb43-3"><a href="#cb43-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> nothrow_swappable_with <span class="op">=</span></span>
<span id="cb43-4"><a href="#cb43-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span><span class="op">(</span>T<span class="op">&amp;&amp;</span> t, U<span class="op">&amp;&amp;</span> u<span class="op">)</span> <span class="op">{</span> <span class="op">{</span> swap<span class="op">((</span>T<span class="op">&amp;&amp;)</span>t, <span class="op">(</span>U<span class="op">&amp;&amp;)</span>u<span class="op">)</span>; <span class="op">}</span> <span class="kw">noexcept</span> <span class="op">}</span>;</span>
<span id="cb43-5"><a href="#cb43-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb43-6"><a href="#cb43-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="kw">typename</span> U, std<span class="op">::</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb43-7"><a href="#cb43-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> nothrow_swappable_with<span class="op">&lt;</span>T<span class="op">&amp;</span>, U<span class="op">&amp;&gt;</span></span>
<span id="cb43-8"><a href="#cb43-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> swap<span class="op">(</span>T<span class="op">(&amp;</span>t<span class="op">)[</span>N<span class="op">]</span>, U<span class="op">(&amp;</span>u<span class="op">)[</span>N<span class="op">])</span> <span class="kw">noexcept</span> <span class="cf">default</span> <span class="op">{</span></span>
<span id="cb43-9"><a href="#cb43-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span>std<span class="op">::</span><span class="dt">size_t</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">&lt;</span> N<span class="op">:</span> <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb43-10"><a href="#cb43-10" aria-hidden="true" tabindex="-1"></a>      swap<span class="op">(</span>t<span class="op">[</span>i<span class="op">]</span>, u<span class="op">[</span>i<span class="op">])</span>;</span>
<span id="cb43-11"><a href="#cb43-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb43-12"><a href="#cb43-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb43-13"><a href="#cb43-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h3 data-number="9.3.3" id="declaring-default-implementations-in-other-namespaces"><span class="header-section-number">9.3.3</span> Declaring default
implementations in other namespaces<a href="#declaring-default-implementations-in-other-namespaces" class="self-link"></a></h3>
<p>It is possible to declare a default implementation for a customisable
function, even if the declaration is textually within a different
namespace, by fully-qualifying the function name to name the
customisable function that the default is being declared for.</p>
<p>This can be useful in cases where you want to define a default
implementation of a customisable function in terms of some concept local
to a library such that it is valid for all types that implement that
concept.</p>
<p>e.g.</p>
<div class="sourceCode" id="cb44"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> containers <span class="op">{</span></span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, std<span class="op">::</span>unsigned_integral IV<span class="op">&gt;</span></span>
<span id="cb44-3"><a href="#cb44-3" aria-hidden="true" tabindex="-1"></a>  IV hash<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> value, IV iv<span class="op">)</span> <span class="kw">noexcept</span> customisable;</span>
<span id="cb44-4"><a href="#cb44-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb44-5"><a href="#cb44-5" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> otherlib <span class="op">{</span></span>
<span id="cb44-6"><a href="#cb44-6" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Hash function used for types in this library</span></span>
<span id="cb44-7"><a href="#cb44-7" 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="cb44-8"><a href="#cb44-8" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>unsigned_integral hash<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> value<span class="op">)</span> <span class="kw">noexcept</span>;</span>
<span id="cb44-9"><a href="#cb44-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb44-10"><a href="#cb44-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> hashable <span class="op">=</span> <span class="kw">requires</span><span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> value<span class="op">)</span> <span class="op">{</span> hash<span class="op">(</span>value<span class="op">)</span>; <span class="op">}</span>;</span>
<span id="cb44-11"><a href="#cb44-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb44-12"><a href="#cb44-12" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Default implementation of containers::hash() so that hash-containers</span></span>
<span id="cb44-13"><a href="#cb44-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">// from containers:: library can use hash-function of types defined in</span></span>
<span id="cb44-14"><a href="#cb44-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// this library.</span></span>
<span id="cb44-15"><a href="#cb44-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>hashable T, std<span class="op">::</span>unsigned_integral IV<span class="op">&gt;</span></span>
<span id="cb44-16"><a href="#cb44-16" aria-hidden="true" tabindex="-1"></a>  IV containers<span class="op">::</span>hash<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> value, IV iv<span class="op">)</span> <span class="kw">noexcept</span> <span class="cf">default</span> <span class="op">{</span></span>
<span id="cb44-17"><a href="#cb44-17" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">static_cast</span><span class="op">&lt;</span>IV<span class="op">&gt;(</span>otherlib<span class="op">::</span>hash<span class="op">(</span>value<span class="op">))</span> <span class="op">^</span> IV;</span>
<span id="cb44-18"><a href="#cb44-18" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb44-19"><a href="#cb44-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Even though the declaration of this default is textually within the
<code class="sourceCode default">otherlib</code> namespace, and name
lookup of names evaluated within the definition are looked up in the
scope of <code class="sourceCode default">otherlib</code>, the
definition itself is only found when looking for a
<code class="sourceCode default">containers::hash</code> default
implementation.</p>
<h3 data-number="9.3.4" id="why-do-we-need-defaults-to-be-looked-up-as-fallback"><span class="header-section-number">9.3.4</span> Why do we need defaults to be
looked up as fallback?<a href="#why-do-we-need-defaults-to-be-looked-up-as-fallback" class="self-link"></a></h3>
<p>If we provide a customisation for a type that accepts a
<code class="sourceCode default">const&amp;</code> where we have a
default that accepts a universal-reference, we would often prefer
overload resolution to find the less-perfect match of the customisation
rather than the default implementation.</p>
<p>Let us consider the
<code class="sourceCode default">contains()</code> algorithm from the <a href="#examples">Examples</a> section. It has a default implementation
with signature:</p>
<div class="sourceCode" id="cb45"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span>range R, <span class="kw">typename</span> Value<span class="op">&gt;</span></span>
<span id="cb45-2"><a href="#cb45-2" aria-hidden="true" tabindex="-1"></a><span class="kw">requires</span> equality_comparable_with<span class="op">&lt;</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, Value<span class="op">&gt;</span></span>
<span id="cb45-3"><a href="#cb45-3" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> contains<span class="op">(</span>R<span class="op">&amp;&amp;</span> range, <span class="kw">const</span> Value<span class="op">&amp;</span> v<span class="op">)</span> <span class="cf">default</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span></code></pre></div>
<p>We may have a customisation that takes a first argument of type
<code class="sourceCode default">const set&amp;</code>.</p>
<div class="sourceCode" id="cb46"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb46-1"><a href="#cb46-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Key, <span class="kw">class</span> Compare, <span class="kw">class</span> Allocator<span class="op">&gt;</span></span>
<span id="cb46-2"><a href="#cb46-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> set <span class="op">{</span></span>
<span id="cb46-3"><a href="#cb46-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">//...</span></span>
<span id="cb46-4"><a href="#cb46-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Value<span class="op">&gt;</span></span>
<span id="cb46-5"><a href="#cb46-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> <span class="op">(</span><span class="kw">const</span> set<span class="op">&amp;</span> s, <span class="kw">const</span> Value<span class="op">&amp;</span> v<span class="op">)</span> <span class="op">{</span> s<span class="op">.</span>contains<span class="op">(</span>v<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb46-6"><a href="#cb46-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> ranges<span class="op">::</span>contains<span class="op">(</span><span class="kw">const</span> set<span class="op">&amp;</span> s, <span class="kw">const</span> Value<span class="op">&amp;</span> v<span class="op">)</span> <span class="kw">override</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb46-7"><a href="#cb46-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Consider what would happen if, instead of having the two-stage
overload resolution that first looks for customisations and then looks
for default implementations, we just define the default implementation
as a generic customisation - equivalent to changing the default
implementation to an
<code class="sourceCode default">override</code>.</p>
<p>In particular, consider:</p>
<div class="sourceCode" id="cb47"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>set<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> s <span class="op">=</span> <span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span><span class="op">}</span>;</span>
<span id="cb47-2"><a href="#cb47-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb47-3"><a href="#cb47-3" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> result <span class="op">=</span> std<span class="op">::</span>ranges<span class="op">::</span>contains<span class="op">(</span>s, <span class="dv">2</span><span class="op">)</span>; <span class="co">// passes type &#39;std::set&lt;int&gt;&amp;&#39;</span></span></code></pre></div>
<p>If the default were considered in overload resolution at the same
time as customisations, then the default implementation with a deduced
template parameter <code class="sourceCode default">R</code> of type
<code class="sourceCode default">std::set&lt;int&gt;&amp;</code> would
actually represent a better match for overload resolution than the
customisation which has a parameter of type
<code class="sourceCode default">const std::set&lt;int&gt;&amp;</code>,,
and so this call would resolve to the more expensive default
implementation.</p>
<p>By allowing implementations to be declared as defaults, and by
defining overload resolution as a two-phase process - first try to find
an overload marked as <code class="sourceCode default">override</code>,
and only if no such overload was found try to find an overload marked
<code class="sourceCode default">default</code> - we can ensure that
customisations marked as
<code class="sourceCode default">override</code> are preferred to
default implementations, even if a default implementation would be a
better match.</p>
<p>Note that this approach closely matches the approach taken by
<code class="sourceCode default">tag_invoke</code>-based CPOs defined in
[P2300R5], which will generally check if there is a valid
<code class="sourceCode default">tag_invoke()</code> overload that it
can dispatch to, and only if there is no valid
<code class="sourceCode default">tag_invoke()</code> overload, fall back
to a default implementation.</p>
<h3 data-number="9.3.5" id="calling-an-override-with-argument-conversion-is-preferred-over-calling-a-default"><span class="header-section-number">9.3.5</span> Calling an override with
argument conversion is preferred over calling a default<a href="#calling-an-override-with-argument-conversion-is-preferred-over-calling-a-default" class="self-link"></a></h3>
<p>One of the implications of this two-phase approach to name lookup is
that it means that overload resolution can potentially prefer calling
customisations found through implicit conversions over calling a default
implementation that doesn’t require one.</p>
<p>For example, consider:</p>
<div class="sourceCode" id="cb48"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb48-1"><a href="#cb48-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">typename</span> U<span class="op">&gt;</span></span>
<span id="cb48-2"><a href="#cb48-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> swap<span class="op">(</span>T<span class="op">&amp;&amp;</span> t, U<span class="op">&amp;&amp;</span> u<span class="op">)</span> customisable;</span>
<span id="cb48-3"><a href="#cb48-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-4"><a href="#cb48-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="cb48-5"><a href="#cb48-5" aria-hidden="true" tabindex="-1"></a><span class="kw">requires</span> std<span class="op">::</span>move_constructible<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> std<span class="op">::</span>assignable_from<span class="op">&lt;</span>T<span class="op">&amp;</span>, T<span class="op">&amp;&amp;&gt;</span></span>
<span id="cb48-6"><a href="#cb48-6" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> swap<span class="op">(</span>T<span class="op">&amp;</span> a, T<span class="op">&amp;</span> b<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(</span><span class="co">/*...*/</span><span class="op">)</span> <span class="cf">default</span> <span class="op">{</span></span>
<span id="cb48-7"><a href="#cb48-7" aria-hidden="true" tabindex="-1"></a>  T tmp<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>a<span class="op">))</span>;</span>
<span id="cb48-8"><a href="#cb48-8" aria-hidden="true" tabindex="-1"></a>  a <span class="op">=</span> std<span class="op">::</span>move<span class="op">(</span>b<span class="op">)</span>;</span>
<span id="cb48-9"><a href="#cb48-9" aria-hidden="true" tabindex="-1"></a>  b <span class="op">=</span> std<span class="op">::</span>move<span class="op">(</span>a<span class="op">)</span>;</span>
<span id="cb48-10"><a href="#cb48-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb48-11"><a href="#cb48-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-12"><a href="#cb48-12" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> X <span class="op">{</span></span>
<span id="cb48-13"><a href="#cb48-13" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> value <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb48-14"><a href="#cb48-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">void</span> swap<span class="op">(</span>X<span class="op">&amp;</span> a, X<span class="op">&amp;</span> b<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">override</span> <span class="op">{</span> swap<span class="op">(</span>a<span class="op">.</span>value, b<span class="op">.</span>value<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb48-15"><a href="#cb48-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb48-16"><a href="#cb48-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-17"><a href="#cb48-17" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> example1<span class="op">()</span> <span class="op">{</span></span>
<span id="cb48-18"><a href="#cb48-18" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> a <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb48-19"><a href="#cb48-19" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> b <span class="op">=</span> <span class="dv">1</span>;</span>
<span id="cb48-20"><a href="#cb48-20" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>reference_wrapper<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> ref1 <span class="op">=</span> a;</span>
<span id="cb48-21"><a href="#cb48-21" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>reference_wrapper<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> ref2 <span class="op">=</span> b;</span>
<span id="cb48-22"><a href="#cb48-22" aria-hidden="true" tabindex="-1"></a>  swap<span class="op">(</span>ref1, ref2<span class="op">)</span>; <span class="co">// calls default implementation - swaps references.</span></span>
<span id="cb48-23"><a href="#cb48-23" aria-hidden="true" tabindex="-1"></a>  <span class="ot">assert</span><span class="op">(&amp;</span>ref1<span class="op">.</span>get<span class="op">()</span> <span class="op">==</span> <span class="op">&amp;</span>b<span class="op">)</span>;</span>
<span id="cb48-24"><a href="#cb48-24" aria-hidden="true" tabindex="-1"></a>  <span class="ot">assert</span><span class="op">(&amp;</span>ref2<span class="op">.</span>get<span class="op">()</span> <span class="op">==</span> <span class="op">&amp;</span>a<span class="op">)</span>;</span>
<span id="cb48-25"><a href="#cb48-25" aria-hidden="true" tabindex="-1"></a>  <span class="ot">assert</span><span class="op">(</span>a <span class="op">==</span> <span class="dv">0</span> <span class="op">&amp;&amp;</span> b <span class="op">==</span> <span class="dv">1</span><span class="op">)</span>;</span>
<span id="cb48-26"><a href="#cb48-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb48-27"><a href="#cb48-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb48-28"><a href="#cb48-28" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> example2<span class="op">()</span> <span class="op">{</span></span>
<span id="cb48-29"><a href="#cb48-29" aria-hidden="true" tabindex="-1"></a>  X a<span class="op">{</span> <span class="dv">0</span> <span class="op">}</span>;</span>
<span id="cb48-30"><a href="#cb48-30" aria-hidden="true" tabindex="-1"></a>  X b<span class="op">{</span> <span class="dv">1</span> <span class="op">}</span>;</span>
<span id="cb48-31"><a href="#cb48-31" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>reference_wrapper<span class="op">&lt;</span>X<span class="op">&gt;</span> ref1 <span class="op">=</span> a;</span>
<span id="cb48-32"><a href="#cb48-32" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>reference_wrapper<span class="op">&lt;</span>X<span class="op">&gt;</span> ref2 <span class="op">=</span> b;</span>
<span id="cb48-33"><a href="#cb48-33" aria-hidden="true" tabindex="-1"></a>  swap<span class="op">(</span>ref1, ref2<span class="op">)</span>; <span class="co">// calls X’s customisation. swaps contents of &#39;a&#39; and &#39;b&#39;</span></span>
<span id="cb48-34"><a href="#cb48-34" aria-hidden="true" tabindex="-1"></a>  <span class="ot">assert</span><span class="op">(&amp;</span>ref1<span class="op">.</span>get<span class="op">()</span> <span class="op">==</span> <span class="op">&amp;</span>a<span class="op">)</span>; <span class="co">// ref1/ref2 still point to same objects</span></span>
<span id="cb48-35"><a href="#cb48-35" aria-hidden="true" tabindex="-1"></a>  <span class="ot">assert</span><span class="op">(&amp;</span>ref2<span class="op">.</span>get<span class="op">()</span> <span class="op">==</span> <span class="op">&amp;</span>b<span class="op">)</span>;</span>
<span id="cb48-36"><a href="#cb48-36" aria-hidden="true" tabindex="-1"></a>  <span class="ot">assert</span><span class="op">(</span>a<span class="op">.</span>value <span class="op">==</span> <span class="dv">1</span> <span class="op">&amp;&amp;</span> b<span class="op">.</span>value <span class="op">==</span> <span class="dv">0</span><span class="op">)</span>; <span class="co">// contents of ‘a’ and ‘b’ have been swapped.</span></span>
<span id="cb48-37"><a href="#cb48-37" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In the case where we call
<code class="sourceCode default">swap()</code> on <code class="sourceCode default">std::reference_wrapper&lt;int&gt;</code>
(example 1) the overload resolution finds no overrides and so falls back
to the default implementation which then swaps the
<code class="sourceCode default">reference_wrapper</code> values,
swapping <code class="sourceCode default">ref1</code> to reference
<code class="sourceCode default">b</code> and
<code class="sourceCode default">ref2</code> to reference
<code class="sourceCode default">a</code>.</p>
<p>However, when calling <code class="sourceCode default">swap()</code>
on
<code class="sourceCode default">std::reference_wrapper&lt;X&gt;</code>
(example 2), the overload resolution finds the override defined for
<code class="sourceCode default">X</code> (since
<code class="sourceCode default">X</code> is an associated entity of
<code class="sourceCode default">std::reference_wrapper&lt;X&gt;</code>)
and this overload is viable because
<code class="sourceCode default">std::reference_wrapper&lt;X&gt;</code>
is implicitly convertible to
<code class="sourceCode default">X&amp;</code>. Overload resolution ends
up preferring to call
<code class="sourceCode default">swap(X&amp;, X&amp;)</code> instead of
<code class="sourceCode default">swap(reference_wrapper&lt;X&gt;&amp;, reference_wrapper&lt;X&gt;&amp;)</code>.</p>
<p>This difference in behaviour may be surprising for some. It could be
made consistent in this case by explicitly defining an overload of
<code class="sourceCode default">swap()</code> for
<code class="sourceCode default">std::reference_wrapper&lt;T&gt;</code>
to ensure that this always swaps the references rather than swapping the
contents of the referenced objects.</p>
<h2 data-number="9.4" id="declaring-multiple-forms-of-a-customisable-function"><span class="header-section-number">9.4</span> Declaring multiple forms of a
customisable function<a href="#declaring-multiple-forms-of-a-customisable-function" class="self-link"></a></h2>
<p>Sometimes we would like to use a given name for multiple forms of a
customisable function. For example, to add overloads that take different
numbers of arguments, or that take arguments of different types or
concepts.</p>
<p>It is possible to declare multiple customisation point overloads with
the same name by declaring multiple
<code class="sourceCode default">customisable</code> functions with the
same name in the same namespace.</p>
<p>For example, we might want to define two flavours of the sender
algorithm <code class="sourceCode default">stop_when()</code>.</p>
<div class="sourceCode" id="cb49"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb49-1"><a href="#cb49-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>execution</span>
<span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb49-3"><a href="#cb49-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Create a sender that runs both input senders concurrently.</span></span>
<span id="cb49-4"><a href="#cb49-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Requests cancellation of the other operation when one completes.</span></span>
<span id="cb49-5"><a href="#cb49-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Completes with result of &#39;source&#39; once both operations have completed.</span></span>
<span id="cb49-6"><a href="#cb49-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>sender Source, sender Trigger<span class="op">&gt;</span></span>
<span id="cb49-7"><a href="#cb49-7" aria-hidden="true" tabindex="-1"></a>  sender <span class="kw">auto</span> stop_when<span class="op">(</span>Source source, Trigger trigger<span class="op">)</span> customisable;</span>
<span id="cb49-8"><a href="#cb49-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb49-9"><a href="#cb49-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Create a sender that sends a stop-request to &#39;source&#39; if a stop-request</span></span>
<span id="cb49-10"><a href="#cb49-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// is delivered on the input stop-token.</span></span>
<span id="cb49-11"><a href="#cb49-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>sender Source, stoppable_token ST<span class="op">&gt;</span></span>
<span id="cb49-12"><a href="#cb49-12" aria-hidden="true" tabindex="-1"></a>  sender <span class="kw">auto</span> stop_when<span class="op">(</span>Source source, ST stop_token<span class="op">)</span> customisable;</span>
<span id="cb49-13"><a href="#cb49-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This ends up creating a single customisation function object named
<code class="sourceCode default">std::execution::stop_when</code> that
is callable with and that allows customisation of either of these
signatures. i.e. that forms a single overload-set.</p>
<h2 data-number="9.5" id="customising-customisable-functions"><span class="header-section-number">9.5</span> Customising customisable
functions<a href="#customising-customisable-functions" class="self-link"></a></h2>
<p>If a namespace-scope function declaration contains the
<code class="sourceCode default">override</code> specifier then the
(possibly scoped) function name must name a previously declared
customisable function. In this case, the declaration adds an overload to
that customisable function’s customisations overload-set.</p>
<p>For example: Given the following customisation point declaration</p>
<div class="sourceCode" id="cb50"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb50-1"><a href="#cb50-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> shapes <span class="op">{</span></span>
<span id="cb50-2"><a href="#cb50-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="op">&gt;</span></span>
<span id="cb50-3"><a href="#cb50-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">float</span> area<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> shape<span class="op">)</span> <span class="kw">noexcept</span> customisable;</span>
<span id="cb50-4"><a href="#cb50-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>We can declare a customisation of this function for our own data-type
as follows:</p>
<div class="sourceCode" id="cb51"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb51-1"><a href="#cb51-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> mylib <span class="op">{</span></span>
<span id="cb51-2"><a href="#cb51-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> circle <span class="op">{</span></span>
<span id="cb51-3"><a href="#cb51-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">float</span> radius;</span>
<span id="cb51-4"><a href="#cb51-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb51-5"><a href="#cb51-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb51-6"><a href="#cb51-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">inline</span> <span class="dt">float</span> shapes<span class="op">::</span>area<span class="op">(</span><span class="kw">const</span> circle<span class="op">&amp;</span> c<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb51-7"><a href="#cb51-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> c<span class="op">.</span>radius <span class="op">*</span> c<span class="op">.</span>radius <span class="op">*</span> std<span class="op">::</span>numbers<span class="op">::</span>pi_v<span class="op">&lt;</span><span class="dt">float</span><span class="op">&gt;</span>;</span>
<span id="cb51-8"><a href="#cb51-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb51-9"><a href="#cb51-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Customisations can also be declared as hidden-friends, in which case
the overloads are only considered if the containing type is considered
an associated type of an argument to the call to a customisable
function. e.g.</p>
<div class="sourceCode" id="cb52"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb52-1"><a href="#cb52-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> mylib <span class="op">{</span></span>
<span id="cb52-2"><a href="#cb52-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> circle <span class="op">{</span></span>
<span id="cb52-3"><a href="#cb52-3" aria-hidden="true" tabindex="-1"></a>    <span class="dt">float</span> radius;</span>
<span id="cb52-4"><a href="#cb52-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-5"><a href="#cb52-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="dt">float</span> shapes<span class="op">::</span>area<span class="op">(</span><span class="kw">const</span> circle<span class="op">&amp;</span> c<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb52-6"><a href="#cb52-6" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> c<span class="op">.</span>radius <span class="op">*</span> c<span class="op">.</span>radius <span class="op">*</span> std<span class="op">::</span>numbers<span class="op">::</span>pi_v<span class="op">&lt;</span><span class="dt">float</span><span class="op">&gt;</span>;</span>
<span id="cb52-7"><a href="#cb52-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb52-8"><a href="#cb52-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb52-9"><a href="#cb52-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="9.6" id="customisable-functions-with-explicit-template-arguments"><span class="header-section-number">9.6</span> Customisable functions with
explicit template arguments<a href="#customisable-functions-with-explicit-template-arguments" class="self-link"></a></h2>
<p>Some customisable functions are intended to be called with explicit
template arguments.</p>
<p>For example, if we were to hypothetically define
<code class="sourceCode default">std::get</code> as a customisable
function so that user-defined types can customise it. e.g. for
supporting structured bindings, then we might declare it as follows:</p>
<div class="sourceCode" id="cb53"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb53-1"><a href="#cb53-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb53-2"><a href="#cb53-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="cb53-3"><a href="#cb53-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> reference_to <span class="op">=</span> std<span class="op">::</span>is_reference_v<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb53-4"><a href="#cb53-4" aria-hidden="true" tabindex="-1"></a>                           std<span class="op">::</span>same_as<span class="op">&lt;</span>std<span class="op">::</span>remove_cvref_t<span class="op">&lt;</span>T<span class="op">&gt;</span>, U<span class="op">&gt;</span>;</span>
<span id="cb53-5"><a href="#cb53-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Get the element of &#39;obj&#39; with type T</span></span>
<span id="cb53-6"><a href="#cb53-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="kw">typename</span> Obj<span class="op">&gt;</span></span>
<span id="cb53-7"><a href="#cb53-7" aria-hidden="true" tabindex="-1"></a>  reference_to<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="kw">auto</span> get<span class="op">&lt;</span>T<span class="op">&gt;(</span>Obj<span class="op">&amp;&amp;</span> obj<span class="op">)</span> customisable;</span>
<span id="cb53-8"><a href="#cb53-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb53-9"><a href="#cb53-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Get the Nth element of &#39;obj&#39;</span></span>
<span id="cb53-10"><a href="#cb53-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="dt">size_t</span> N, <span class="kw">typename</span> Obj<span class="op">&gt;</span></span>
<span id="cb53-11"><a href="#cb53-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span><span class="op">&amp;&amp;</span> get<span class="op">&lt;</span>N<span class="op">&gt;(</span>Obj<span class="op">&amp;&amp;</span> obj<span class="op">)</span> customisable;</span>
<span id="cb53-12"><a href="#cb53-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>This ends up declaring two variable templates with the same name,
each specialization of which represents a customisable function object
with a distinct type and thus a distinct overload-set.</p>
<p>This is intended to mimic the behaviour of normal template functions,
such as <code class="sourceCode default">std::get</code>, which permit
different sets of template function declarations to coexist alongside
each other.</p>
<p>Note that it is similarly valid for a customisable function template
and a non-template customisable function of the same name to coexist
beside each other as well, similar to normal functions.</p>
<p>e.g. The following creates an object named
<code class="sourceCode default">N::foo</code> and a variable template
named <code class="sourceCode default">N::foo&lt;T&gt;</code>. These
represent independent CFOs that can be customised separately.</p>
<div class="sourceCode" id="cb54"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb54-1"><a href="#cb54-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> N <span class="op">{</span></span>
<span id="cb54-2"><a href="#cb54-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> foo<span class="op">(</span><span class="kw">auto</span><span class="op">&amp;</span> obj, <span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> value<span class="op">)</span> customisable;</span>
<span id="cb54-3"><a href="#cb54-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb54-4"><a href="#cb54-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="cb54-5"><a href="#cb54-5" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> foo<span class="op">&lt;</span>T<span class="op">&gt;(</span><span class="kw">auto</span><span class="op">&amp;</span> obj, <span class="kw">const</span> T<span class="op">&amp;</span> value<span class="op">)</span> customisable;</span>
<span id="cb54-6"><a href="#cb54-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb54-7"><a href="#cb54-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb54-8"><a href="#cb54-8" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> X <span class="op">{</span></span>
<span id="cb54-9"><a href="#cb54-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">void</span> N<span class="op">::</span>foo<span class="op">(</span>X<span class="op">&amp;</span>, <span class="kw">const</span> <span class="dt">int</span><span class="op">&amp;</span> x<span class="op">)</span> <span class="kw">override</span>;      <span class="co">// 1</span></span>
<span id="cb54-10"><a href="#cb54-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">void</span> N<span class="op">::</span>foo<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;(</span>X<span class="op">&amp;</span>, <span class="kw">const</span> <span class="dt">int</span><span class="op">&amp;</span> x<span class="op">)</span> <span class="kw">override</span>; <span class="co">// 2</span></span>
<span id="cb54-11"><a href="#cb54-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb54-12"><a href="#cb54-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb54-13"><a href="#cb54-13" aria-hidden="true" tabindex="-1"></a>X x;</span>
<span id="cb54-14"><a href="#cb54-14" aria-hidden="true" tabindex="-1"></a>N<span class="op">::</span>foo<span class="op">(</span>x, <span class="dv">42</span><span class="op">)</span>;      <span class="co">// calls 1.</span></span>
<span id="cb54-15"><a href="#cb54-15" aria-hidden="true" tabindex="-1"></a>N<span class="op">::</span>foo<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;(</span>x, <span class="dv">42</span><span class="op">)</span>; <span class="co">// calls 2.</span></span></code></pre></div>
<p>Given the example declaration of
<code class="sourceCode default">std::get</code> above we could
write:</p>
<div class="sourceCode" id="cb55"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb55-1"><a href="#cb55-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Assume that std::tuple has customised std::get&lt;T&gt; and std::get&lt;N&gt;</span></span>
<span id="cb55-2"><a href="#cb55-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>tuple<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">float</span>, <span class="dt">bool</span><span class="op">&gt;</span> t<span class="op">{</span><span class="dv">42</span>, <span class="fl">1.0</span><span class="bu">f</span>, <span class="kw">true</span><span class="op">}</span>;</span>
<span id="cb55-3"><a href="#cb55-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb55-4"><a href="#cb55-4" aria-hidden="true" tabindex="-1"></a><span class="ot">assert</span><span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;(</span>t<span class="op">)</span> <span class="op">==</span> <span class="dv">42</span><span class="op">)</span>;</span>
<span id="cb55-5"><a href="#cb55-5" aria-hidden="true" tabindex="-1"></a><span class="ot">assert</span><span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span><span class="dt">float</span><span class="op">&gt;(</span>t<span class="op">)</span> <span class="op">==</span> <span class="fl">1.0</span><span class="bu">f</span><span class="op">)</span>;</span>
<span id="cb55-6"><a href="#cb55-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb55-7"><a href="#cb55-7" aria-hidden="true" tabindex="-1"></a><span class="co">// A customisable-function object that when called gets the first element</span></span>
<span id="cb55-8"><a href="#cb55-8" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> get_first <span class="op">=</span> std<span class="op">::</span>get<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;</span>;</span>
<span id="cb55-9"><a href="#cb55-9" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> get_second <span class="op">=</span> std<span class="op">::</span>get<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;</span>;</span>
<span id="cb55-10"><a href="#cb55-10" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span>std<span class="op">::</span>same_as<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>get_first<span class="op">)</span>, <span class="kw">decltype</span><span class="op">(</span>get_second<span class="op">)&gt;)</span>;</span>
<span id="cb55-11"><a href="#cb55-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb55-12"><a href="#cb55-12" aria-hidden="true" tabindex="-1"></a><span class="co">// A customisable-function object that when called gets the &#39;float&#39; element</span></span>
<span id="cb55-13"><a href="#cb55-13" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> get_float <span class="op">=</span> std<span class="op">::</span>get<span class="op">&lt;</span><span class="dt">float</span><span class="op">&gt;</span>;</span>
<span id="cb55-14"><a href="#cb55-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb55-15"><a href="#cb55-15" aria-hidden="true" tabindex="-1"></a><span class="ot">assert</span><span class="op">(</span>get_first<span class="op">(</span>t<span class="op">)</span> <span class="op">==</span> <span class="dv">42</span><span class="op">)</span>;</span>
<span id="cb55-16"><a href="#cb55-16" aria-hidden="true" tabindex="-1"></a><span class="ot">assert</span><span class="op">(</span>get_float<span class="op">(</span>t<span class="op">)</span> <span class="op">==</span> <span class="fl">1.0</span><span class="bu">f</span><span class="op">)</span>;</span></code></pre></div>
<p>Note that the template arguments of
<code class="sourceCode default">std::get</code> are never deduced, they
must always be explicitly provided by the caller.</p>
<p>A type can define non-template customisations of template
customisable functions as follows:</p>
<div class="sourceCode" id="cb56"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb56-1"><a href="#cb56-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> First, <span class="kw">typename</span> Second<span class="op">&gt;</span></span>
<span id="cb56-2"><a href="#cb56-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> pair <span class="op">{</span></span>
<span id="cb56-3"><a href="#cb56-3" aria-hidden="true" tabindex="-1"></a>  First first;</span>
<span id="cb56-4"><a href="#cb56-4" aria-hidden="true" tabindex="-1"></a>  Second second;</span>
<span id="cb56-5"><a href="#cb56-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb56-6"><a href="#cb56-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> First<span class="op">&amp;</span> std<span class="op">::</span>get<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;(</span>pair<span class="op">&amp;</span> self<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">override</span> <span class="op">{</span> <span class="cf">return</span> self<span class="op">.</span>first; <span class="op">}</span></span>
<span id="cb56-7"><a href="#cb56-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> Second<span class="op">&amp;</span> std<span class="op">::</span>get<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;(</span>pair<span class="op">&amp;</span> self<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">override</span> <span class="op">{</span> <span class="cf">return</span> self<span class="op">.</span>second; <span class="op">}</span></span>
<span id="cb56-8"><a href="#cb56-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb56-9"><a href="#cb56-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> First<span class="op">&amp;</span> std<span class="op">::</span>get<span class="op">&lt;</span>First<span class="op">&gt;(</span>pair<span class="op">&amp;</span> self<span class="op">)</span> <span class="kw">noexcept</span></span>
<span id="cb56-10"><a href="#cb56-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> <span class="op">(!</span>std<span class="op">::</span>same_as<span class="op">&lt;</span>First, Second<span class="op">&gt;)</span> <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb56-11"><a href="#cb56-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> self<span class="op">.</span>first;</span>
<span id="cb56-12"><a href="#cb56-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb56-13"><a href="#cb56-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb56-14"><a href="#cb56-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> Second<span class="op">&amp;</span> std<span class="op">::</span>get<span class="op">&lt;</span>Second<span class="op">&gt;(</span>pair<span class="op">&amp;</span> self<span class="op">)</span> <span class="kw">noexcept</span></span>
<span id="cb56-15"><a href="#cb56-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> <span class="op">(!</span>std<span class="op">::</span>same_as<span class="op">&lt;</span>First, Second<span class="op">&gt;)</span> <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb56-16"><a href="#cb56-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> self<span class="op">.</span>second;</span>
<span id="cb56-17"><a href="#cb56-17" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb56-18"><a href="#cb56-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>A type can also define a generic customisation of a template
customisable function that allows deduction of the template arguments
from the customisable-function template mentioned in the function
declarator. e.g.</p>
<div class="sourceCode" id="cb57"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb57-1"><a href="#cb57-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, std<span class="op">::</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb57-2"><a href="#cb57-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> array <span class="op">{</span></span>
<span id="cb57-3"><a href="#cb57-3" aria-hidden="true" tabindex="-1"></a>  T data<span class="op">[</span>N<span class="op">]</span>;</span>
<span id="cb57-4"><a href="#cb57-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb57-5"><a href="#cb57-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="dt">size_t</span> Idx<span class="op">&gt;</span></span>
<span id="cb57-6"><a href="#cb57-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="op">(</span>Idx <span class="op">&lt;</span> N<span class="op">)</span></span>
<span id="cb57-7"><a href="#cb57-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> T<span class="op">&amp;</span> std<span class="op">::</span>get<span class="op">&lt;</span>Idx<span class="op">&gt;(</span>array<span class="op">&amp;</span> self<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> data<span class="op">[</span>Idx<span class="op">]</span>; <span class="op">}</span></span>
<span id="cb57-8"><a href="#cb57-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<h2 data-number="9.7" id="generic-forwarding"><span class="header-section-number">9.7</span> Generic forwarding<a href="#generic-forwarding" class="self-link"></a></h2>
<p>When we are building wrapper types we want to be able to forward
through a set of customisable function calls on the wrapper to the
wrapped object.</p>
<p>Examples of such wrapper types include:</p>
<ul>
<li>Type-erasing wrappers, where the list of customisable functions to
forward is specified via template parameters. e.g. <code class="sourceCode default">unifex::any_unique&lt;cfo1, cfo2, cfo3&gt;</code>
where the generic type
<code class="sourceCode default">any_unique</code> needs to be able to
customise the arbitrary set of user-provided CFOs.</li>
<li>Types that customise one or more CFOs to have different behaviour
and forward calls to other CFOs onto the wrapped value (if it supports
them). This technique is used heavily in sender/receiver-based algorithm
implementations (e.g. a receiver customising
<code class="sourceCode default">get_allocator()</code> to return an
allocator owned by the current operation, while forwarding other queries
to the parent receiver).</li>
</ul>
<p>The ability to be able to generically customise different CFOs is
built on the ability to define an override with a declarator-id that is
deducible.</p>
<p>Example: A receiver type that customises the
<code class="sourceCode default">get_allocator()</code> query and
forwards other queries.</p>
<div class="sourceCode" id="cb58"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb58-1"><a href="#cb58-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">auto</span> Signal, <span class="kw">typename</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb58-2"><a href="#cb58-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> receiver_of <span class="op">=</span></span>
<span id="cb58-3"><a href="#cb58-3" aria-hidden="true" tabindex="-1"></a>  receiver<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb58-4"><a href="#cb58-4" aria-hidden="true" tabindex="-1"></a>  completion_signal<span class="op">&lt;</span>Signal<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb58-5"><a href="#cb58-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span><span class="op">(</span>T<span class="op">&amp;&amp;</span> r, Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span> <span class="op">{</span></span>
<span id="cb58-6"><a href="#cb58-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span> Signal<span class="op">((</span>T<span class="op">&amp;&amp;)</span>r, <span class="op">(</span>Args<span class="op">&amp;&amp;)</span>args<span class="op">...)</span> <span class="op">}</span> <span class="kw">noexcept</span>;</span>
<span id="cb58-7"><a href="#cb58-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb58-8"><a href="#cb58-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb58-9"><a href="#cb58-9" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Receiver, <span class="kw">typename</span> Allocator<span class="op">&gt;</span></span>
<span id="cb58-10"><a href="#cb58-10" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> allocator_receiver <span class="op">{</span></span>
<span id="cb58-11"><a href="#cb58-11" aria-hidden="true" tabindex="-1"></a>  Receiver receiver;</span>
<span id="cb58-12"><a href="#cb58-12" aria-hidden="true" tabindex="-1"></a>  Allocator alloc;</span>
<span id="cb58-13"><a href="#cb58-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb58-14"><a href="#cb58-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Customise the get_allocator query</span></span>
<span id="cb58-15"><a href="#cb58-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> Allocator std<span class="op">::</span>execution<span class="op">::</span>get_allocator<span class="op">(</span><span class="kw">const</span> allocator_receiver<span class="op">&amp;</span> r<span class="op">)</span></span>
<span id="cb58-16"><a href="#cb58-16" aria-hidden="true" tabindex="-1"></a>      <span class="kw">noexcept</span> <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb58-17"><a href="#cb58-17" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> r<span class="op">.</span>alloc;</span>
<span id="cb58-18"><a href="#cb58-18" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb58-19"><a href="#cb58-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb58-20"><a href="#cb58-20" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Forward completion-signals</span></span>
<span id="cb58-21"><a href="#cb58-21" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span> Signal, <span class="kw">typename</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb58-22"><a href="#cb58-22" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> receiver_of<span class="op">&lt;</span>Receiver, Signal, Args<span class="op">...&gt;</span></span>
<span id="cb58-23"><a href="#cb58-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">void</span> Signal<span class="op">(</span>allocator_receiver<span class="op">&amp;&amp;</span> r, Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb58-24"><a href="#cb58-24" aria-hidden="true" tabindex="-1"></a>    Signal<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>r<span class="op">.</span>receiver<span class="op">)</span>, std<span class="op">::</span>forward<span class="op">&lt;</span>Args<span class="op">&gt;(</span>args<span class="op">)...)</span>;</span>
<span id="cb58-25"><a href="#cb58-25" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb58-26"><a href="#cb58-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb58-27"><a href="#cb58-27" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Forward query-like calls onto inner receiver</span></span>
<span id="cb58-28"><a href="#cb58-28" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span> Query<span class="op">&gt;</span></span>
<span id="cb58-29"><a href="#cb58-29" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> <span class="op">(!</span>completion_signal<span class="op">&lt;</span>Query<span class="op">&gt;)</span> <span class="op">&amp;&amp;</span> std<span class="op">::</span>invocable<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>Query<span class="op">)</span>, <span class="kw">const</span> Receiver<span class="op">&amp;&gt;</span></span>
<span id="cb58-30"><a href="#cb58-30" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> Query<span class="op">(</span><span class="kw">const</span> allocator_receiver<span class="op">&amp;</span> r<span class="op">)</span></span>
<span id="cb58-31"><a href="#cb58-31" aria-hidden="true" tabindex="-1"></a>      <span class="kw">noexcept</span><span class="op">(</span>std<span class="op">::</span>is_nothrow_invocable_v<span class="op">&lt;</span>Query, <span class="kw">const</span> Receiver<span class="op">&amp;&gt;)</span> <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb58-32"><a href="#cb58-32" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> Query<span class="op">(</span>r<span class="op">.</span>receiver<span class="op">)</span>;</span>
<span id="cb58-33"><a href="#cb58-33" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb58-34"><a href="#cb58-34" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<h2 data-number="9.8" id="overload-resolution-for-customisable-function-calls"><span class="header-section-number">9.8</span> Overload resolution for
customisable function calls<a href="#overload-resolution-for-customisable-function-calls" class="self-link"></a></h2>
<p>In a function-call expression, if the <em>postfix-expression</em>
operand of the call expression denotes a Customizable Function Object,
then overload resolution is performed as follows:</p>
<ul>
<li>Let:
<ul>
<li><code class="sourceCode default">O</code> be the customisable
function object in the <em>postfix-expression</em> operand position</li>
<li><code class="sourceCode default">F</code> be the decayed type of the
customisable function object,
<code class="sourceCode default">O</code>,</li>
<li><code class="sourceCode default">args...</code> be the sequence of
argument expressions for the call expression</li>
</ul></li>
<li>Let the set, <code class="sourceCode default">Ef</code>, contain the
associated entites of the type <code class="sourceCode default">F</code>
<ul>
<li>This includes the associated entities of any explicit type template
parameters of a generic CFO</li>
</ul></li>
<li>Let the set, <code class="sourceCode default">Ea</code>, contain the
associated entities of each of the argument types in
<code class="sourceCode default">args...</code></li>
<li>If the customisable function object has any associated function
declarations marked <code class="sourceCode default">customisable</code>
then let <code class="sourceCode default">E</code> be the union of
<code class="sourceCode default">Ef</code> and
<code class="sourceCode default">Ea</code></li>
<li>Otherwise, let <code class="sourceCode default">E</code> be
<code class="sourceCode default">Ef</code></li>
<li>Let the <em>customisation overload set</em> be initially the empty
set.</li>
<li>For each associated entity,
<code class="sourceCode default">e</code>, in
<code class="sourceCode default">E</code> look in its associated
namespaces of <code class="sourceCode default">e</code> for
<ul>
<li>non-member functions marked with
<code class="sourceCode default">override</code> or
<code class="sourceCode default">final</code> where either;
<ul>
<li>the declarator-id names an object that has type
<code class="sourceCode default">F</code>; or</li>
<li>the declarator-id is a dependent name deducible to
<code class="sourceCode default">O</code></li>
</ul></li>
<li>if the overload is a function template then attempt to deduce the
template arguments based on the types of the argument expressions in the
postfix call expression.
<ul>
<li>if template argument deduction fails then discard this overload</li>
</ul></li>
<li>if any of the constraints of the overload declaration are not met
then discard this overload.</li>
<li>otherwise, if the overload was not discarded, add it to the
<em>customisation overload set</em>.</li>
</ul></li>
<li>form an argument list
<code class="sourceCode default">(args...)</code> and attempt to perform
overload resolution using this argument list on the overloads in the
<em>customisation overload set</em>.</li>
<li>if overload resolution finds a single, best overload then
call-expression resolves to a call to this overload
<ul>
<li>if any of the candidate overloads in the <em>customisation overload
set</em> are marked <code class="sourceCode default">final</code> then
there must be exactly one such overload and it must be the selected
overload (otherwise this indicates that someone has declared an override
for a function marked
<code class="sourceCode default">final</code>)</li>
</ul></li>
<li>otherwise, if there were viable candidates; then the call-expression
is ill-formed [[Note: Because the call is ambiguous]]</li>
<li>otherwise, if there were no viable candidates in the overload set,
perform a second overload resolution with the same argument list, this
time on the set of function definitions marked marked with
<code class="sourceCode default">default</code> (which are found in the
customisable function’s private associated namespace).</li>
<li>if overload resolution finds a single, best overload then the
call-expression resolves to a call to this overload</li>
<li>otherwise, the call expression is ill-formed [[Note: Because either
there is no viable candidate, or the call is ambiguous]]</li>
</ul>
<p>Once the single, best overload is selected the next step is to check
that the selected overload is a valid customisation of the customisable
function prototype, described in the <a href="#validating-customizations">Validating customisations</a>
section.</p>
<h3 data-number="9.8.1" id="validating-customisations"><span class="header-section-number">9.8.1</span> Validating customisations<a href="#validating-customisations" class="self-link"></a></h3>
<p>The process of checking that a particular customisation of a
customisable function is a valid customisation helps to eliminate bugs
caused by defining a customisation that doesn’t match the expectation of
a caller of the customisation point.</p>
<p>One of the points from <span class="citation" data-cites="P2279R0">[<a href="#ref-P2279R0" role="doc-biblioref">P2279R0</a>]</span> states that
customisation-points should have:</p>
<ol start="4" type="1">
<li>The inability to <em>incorrectly</em> opt in to the interface (for
instance, if the interface has a function that takes an
<code class="sourceCode default">int</code>, you cannot opt in by
accidentally taking an
<code class="sourceCode default">unsigned int</code>)</li>
</ol>
<p>For example, if I declare the following customisable function:</p>
<div class="sourceCode" id="cb59"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb59-1"><a href="#cb59-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Obj<span class="op">&gt;</span></span>
<span id="cb59-2"><a href="#cb59-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> resize<span class="op">(</span>Obj<span class="op">&amp;</span> obj, <span class="dt">size_t</span> size<span class="op">)</span> customisable;</span></code></pre></div>
<p>And if I had a type, say:</p>
<div class="sourceCode" id="cb60"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb60-1"><a href="#cb60-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> size_wrapper <span class="op">{</span></span>
<span id="cb60-2"><a href="#cb60-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">operator</span> <span class="dt">size_t</span><span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;size_t&quot;</span><span class="op">)</span>; <span class="cf">return</span> <span class="dv">1</span>; <span class="op">}</span></span>
<span id="cb60-3"><a href="#cb60-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">operator</span> <span class="dt">int</span><span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;int&quot;</span><span class="op">)</span>; <span class="cf">return</span> <span class="dv">2</span>; <span class="op">}</span></span>
<span id="cb60-4"><a href="#cb60-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>You would never expect a call to
<code class="sourceCode default">resize(someObj, size_wrapper{})</code>
as the second argument to invoke the
<code class="sourceCode default">operator int()</code> conversion
operator. However, if we were to allow a type to define the override
<code class="sourceCode default">resize(some_type&amp;, int)</code>,
then a call that resolves to this overload might end up calling
<code class="sourceCode default">operator int()</code> unexpectedly.</p>
<p>To avoid this situation, the signature of customisations and default
implementations are checked against the customisable function prototypes
to ensure that they are consistent with the signature of at least one
customisable function prototype.</p>
<p>This is done by attempting to match the signature of the selected
overload to the signature of each of the customisable function
prototypes - for each customisable function prototype
<code class="sourceCode default">F</code> for the current customisable
function - if it was a <em>customisable function template</em>
prototype, then first deduce the template arguments required to match
the declarator-id such that
<code class="sourceCode default">decltype(declarator-id)</code> is
<code class="sourceCode default">F</code>. - Then, for each function
parameter of the declaration in-order from left to right - Attempt to
deduce template arguments so that the parameter type exactly matches the
corresponding parameter type from the selected overload. - If this step
fails then ignore this customisable function prototype - Then, attempt
to deduce template arguments such that the return type exactly matches
the return type of the selected overload [[Example:
<code class="sourceCode default">copyable auto f() = 0;</code> deduces
an implicit template argument to the return type of the overload and
then checks the <code class="sourceCode default">copyable</code>
constraint on the deduced implicit template argument – end example]]. -
If this step fails then ignore this customisable function prototype -
Then evaluate the constraints on the declaration with the deduced
template arguments. - If the constraints are not met then ignore this
customisable function prototype - Then evaluate the
<code class="sourceCode default">noexcept</code>-specifier of the
customisable function prototype using the deduced template arguments. -
If the <code class="sourceCode default">noexcept</code>-specifier
evaluates to <code class="sourceCode default">noexcept(true)</code> then
if the implementation does not have a
<code class="sourceCode default">noexcept(true)</code> specifier, the
program is ill-formed. - If the
<code class="sourceCode default">consteval</code>-ness of the prototype
does not match the
<code class="sourceCode default">consteval</code>-ness of the selected
overload, discard the prototype. - If there were no customisable
function prototypes that were not discarded for which the overload was
able to successfully match then the program is ill-formed. [[Note:
Because the implementation was an invalid overload]].</p>
<p>Parts of this process are described in more detail <a href="#noexcept-specifications">Noexcept specifications</a>, <a href="#constraining-parameter-types">Constraining parameter-types</a>
and <a href="#constraining-return%20types">Constraining return
types</a>.</p>
<p>The above checks are not performed if the selected overload was
declared <code class="sourceCode default">final</code> and in the same
namespace as the CFO being invoked. Such overloads are not considered to
be implmentations of a customisable function prototype but instead are
independent function overloads.</p>
<h3 data-number="9.8.2" id="noexcept-specifications"><span class="header-section-number">9.8.2</span> Noexcept specifications<a href="#noexcept-specifications" class="self-link"></a></h3>
<p>When a customisable function is declared, the declaration may contain
a <code class="sourceCode default">noexcept</code> specification.</p>
<p>If the customisable function prototype has a
<code class="sourceCode default">noexcept(true)</code> specification
then all customisations and default implementations of that function
must also be declared as
<code class="sourceCode default">noexcept(true)</code>.</p>
<div class="sourceCode" id="cb61"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb61-1"><a href="#cb61-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> somelib <span class="op">{</span></span>
<span id="cb61-2"><a href="#cb61-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="op">&gt;</span></span>
<span id="cb61-3"><a href="#cb61-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> customisable_func<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> x<span class="op">)</span> <span class="kw">noexcept</span> customisable;</span>
<span id="cb61-4"><a href="#cb61-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb61-5"><a href="#cb61-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb61-6"><a href="#cb61-6" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> mylib <span class="op">{</span></span>
<span id="cb61-7"><a href="#cb61-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> type_a <span class="op">{</span> <span class="co">/*...*/</span> <span class="op">}</span>;</span>
<span id="cb61-8"><a href="#cb61-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> type_b <span class="op">{</span> <span class="co">/*...*/</span> <span class="op">}</span>;</span>
<span id="cb61-9"><a href="#cb61-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb61-10"><a href="#cb61-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// OK, customisation is noexcept</span></span>
<span id="cb61-11"><a href="#cb61-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">void</span> somelib<span class="op">::</span>customisable_func<span class="op">(</span><span class="kw">const</span> type_a<span class="op">&amp;</span> x<span class="op">)</span> <span class="kw">noexcept</span> <span class="op">{</span></span>
<span id="cb61-12"><a href="#cb61-12" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> <span class="st">&quot;type_a&quot;</span>;</span>
<span id="cb61-13"><a href="#cb61-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb61-14"><a href="#cb61-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb61-15"><a href="#cb61-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Ill-formed: customisation not declared noexcept</span></span>
<span id="cb61-16"><a href="#cb61-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">void</span> somelib<span class="op">::</span>customisable_func<span class="op">(</span><span class="kw">const</span> type_b<span class="op">&amp;</span> x<span class="op">)</span> <span class="op">{</span></span>
<span id="cb61-17"><a href="#cb61-17" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>cout <span class="op">&lt;&lt;</span> <span class="st">&quot;type_b&quot;</span>;</span>
<span id="cb61-18"><a href="#cb61-18" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb61-19"><a href="#cb61-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>If the customisable function prototype has a
<code class="sourceCode default">noexcept(false)</code> specification or
if the <code class="sourceCode default">noexcept</code> specification is
absent then customisations and default implementations may either be
declared as <code class="sourceCode default">noexcept(true)</code> or
<code class="sourceCode default">noexcept(false)</code>. These rules are
the same as for function pointer convertibility around
<code class="sourceCode default">noexcept</code>.</p>
<p>When a <em>noexcept-expression</em> contains a
<em>call-expression</em> in its argument that resolves to a call to a
customisable function, the result is evaluated based on the
<code class="sourceCode default">noexcept</code>-specification of the
selected overload of the customisable function rather than the
<code class="sourceCode default">noexcept</code>-specification of the
declaration of the customisable function prototype.</p>
<div class="sourceCode" id="cb62"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb62-1"><a href="#cb62-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb62-2"><a href="#cb62-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="cb62-3"><a href="#cb62-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> swap<span class="op">(</span>T<span class="op">&amp;&amp;</span> t, U<span class="op">&amp;&amp;</span> u<span class="op">)</span> customisable;</span>
<span id="cb62-4"><a href="#cb62-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb62-5"><a href="#cb62-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb62-6"><a href="#cb62-6" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> type_a <span class="op">{</span></span>
<span id="cb62-7"><a href="#cb62-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">void</span> std<span class="op">::</span>ranges<span class="op">::</span>swap<span class="op">(</span>type_a<span class="op">&amp;</span> a, type_a<span class="op">&amp;</span> b<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">override</span>;</span>
<span id="cb62-8"><a href="#cb62-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb62-9"><a href="#cb62-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb62-10"><a href="#cb62-10" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> type_b <span class="op">{</span></span>
<span id="cb62-11"><a href="#cb62-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">void</span> std<span class="op">::</span>ranges<span class="op">::</span>swap<span class="op">(</span>type_b<span class="op">&amp;</span> a, type_b<span class="op">&amp;</span> b<span class="op">)</span> <span class="kw">override</span>;</span>
<span id="cb62-12"><a href="#cb62-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb62-13"><a href="#cb62-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb62-14"><a href="#cb62-14" aria-hidden="true" tabindex="-1"></a>type_a a1, a2;</span>
<span id="cb62-15"><a href="#cb62-15" aria-hidden="true" tabindex="-1"></a>type_b b2, b2;</span>
<span id="cb62-16"><a href="#cb62-16" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span><span class="kw">noexcept</span><span class="op">(</span>std<span class="op">::</span>ranges<span class="op">::</span>swap<span class="op">(</span>a1, a2<span class="op">)))</span>;</span>
<span id="cb62-17"><a href="#cb62-17" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(!</span><span class="kw">noexcept</span><span class="op">(</span>std<span class="op">::</span>ranges<span class="op">::</span>swap<span class="op">(</span>b1, b2<span class="op">)))</span>;</span></code></pre></div>
<p>For example: Consider a hypothetical
<code class="sourceCode default">make_stop_callback()</code> inspired
from <span class="citation" data-cites="P2175R0">[<a href="#ref-P2175R0" role="doc-biblioref">P2175R0</a>]</span></p>
<div class="sourceCode" id="cb63"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb63-1"><a href="#cb63-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span>stoppable_token ST, <span class="kw">typename</span> F<span class="op">&gt;</span></span>
<span id="cb63-2"><a href="#cb63-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> std<span class="op">::</span>invocable<span class="op">&lt;</span>std<span class="op">::</span>decay_t<span class="op">&lt;</span>F<span class="op">&gt;&gt;</span></span>
<span id="cb63-3"><a href="#cb63-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> make_stop_callback<span class="op">(</span>ST st, F func<span class="op">)</span></span>
<span id="cb63-4"><a href="#cb63-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">noexcept</span><span class="op">(</span>std<span class="op">::</span>is_nothrow_constructible_v<span class="op">&lt;</span>std<span class="op">::</span>decay_t<span class="op">&lt;</span>F<span class="op">&gt;</span>, F<span class="op">&gt;)</span> customisable;</span>
<span id="cb63-5"><a href="#cb63-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb63-6"><a href="#cb63-6" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> never_stop_token <span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb63-7"><a href="#cb63-7" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> never_stop_callback <span class="op">{}</span>;</span>
<span id="cb63-8"><a href="#cb63-8" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> F<span class="op">&gt;</span></span>
<span id="cb63-9"><a href="#cb63-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> std<span class="op">::</span>invocable<span class="op">&lt;</span>std<span class="op">::</span>decay_t<span class="op">&lt;</span>F<span class="op">&gt;&gt;</span></span>
<span id="cb63-10"><a href="#cb63-10" aria-hidden="true" tabindex="-1"></a>never_stop_callback make_stop_callback<span class="op">(</span>never_stop_token, F<span class="op">&amp;&amp;)</span> <span class="kw">noexcept</span> <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb63-11"><a href="#cb63-11" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="op">{}</span>;</span>
<span id="cb63-12"><a href="#cb63-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb63-13"><a href="#cb63-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb63-14"><a href="#cb63-14" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> example<span class="op">()</span> <span class="op">{</span></span>
<span id="cb63-15"><a href="#cb63-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> cb <span class="op">=</span> make_stop_callback<span class="op">(</span>never_stop_token<span class="op">{}</span>, <span class="op">[]()</span> <span class="op">{</span> do_something<span class="op">()</span>; <span class="op">})</span>;</span>
<span id="cb63-16"><a href="#cb63-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In this case, the overload resolution for the call to
<code class="sourceCode default">make_stop_callback</code> finds the
<code class="sourceCode default">never_stop_token</code> overload which
has argument types:
<code class="sourceCode default">never_stop_token</code> and
<code class="sourceCode default">lambda&amp;&amp;</code>.</p>
<p>The compiler then looks at the customisable function prototype and
deduces the template arguments:</p>
<ul>
<li><code class="sourceCode default">ST</code> is deduced to be
<code class="sourceCode default">never_stop_token</code></li>
<li><code class="sourceCode default">F</code> is deduced to be
<code class="sourceCode default">lambda&amp;&amp;</code></li>
</ul>
<p>Next, the compiler evaluates
<code class="sourceCode default">noexcept</code> specification: - <code class="sourceCode default">noexcept(std::is_nothrow_constructible_v&lt;lambda, lambda&amp;&amp;&gt;)</code>
evaluates to <code class="sourceCode default">noexcept(true)</code>.</p>
<p>Next, as the declaration evaluated the
<code class="sourceCode default">noexcept</code> specification to
<code class="sourceCode default">noexcept(true)</code>, the compiler
then checks the <code class="sourceCode default">noexcept</code>
specification of the selected overload: - The selected overload is
declared <code class="sourceCode default">noexcept</code>
unconditionally, so the <code class="sourceCode default">noexcept</code>
specification of customisation is considered compatible.</p>
<h3 data-number="9.8.3" id="constraining-parameter-types"><span class="header-section-number">9.8.3</span> Constraining
parameter-types<a href="#constraining-parameter-types" class="self-link"></a></h3>
<p>A customisation point may put constraints on the parameter types that
it is designed to handle.</p>
<p>For example, a customisable range-based algorithm may want to
constrain a <code class="sourceCode default">contains()</code> algorithm
so that its first argument is a range and the second argument is a value
that is <code class="sourceCode default">equality_comparable_with the elements</code>
of that range.</p>
<p>Given:</p>
<div class="sourceCode" id="cb64"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb64-1"><a href="#cb64-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span>std<span class="op">::</span>ranges<span class="op">::</span>range R,</span>
<span id="cb64-2"><a href="#cb64-2" aria-hidden="true" tabindex="-1"></a>         std<span class="op">::</span>equality_comparable_with<span class="op">&lt;</span>std<span class="op">::</span>ranges<span class="op">::</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;&gt;</span> V<span class="op">&gt;</span></span>
<span id="cb64-3"><a href="#cb64-3" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> contains<span class="op">(</span>R range, V value<span class="op">)</span> customisable;</span>
<span id="cb64-4"><a href="#cb64-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb64-5"><a href="#cb64-5" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span>std<span class="op">::</span>ranges<span class="op">::</span>range R, <span class="kw">typename</span> V<span class="op">&gt;</span></span>
<span id="cb64-6"><a href="#cb64-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> std<span class="op">::</span>equality_comparable_with<span class="op">&lt;</span></span>
<span id="cb64-7"><a href="#cb64-7" aria-hidden="true" tabindex="-1"></a>             std<span class="op">::</span>ranges<span class="op">::</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, <span class="kw">const</span> V<span class="op">&amp;&gt;</span></span>
<span id="cb64-8"><a href="#cb64-8" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> contains<span class="op">(</span>R<span class="op">&amp;&amp;</span> range, <span class="kw">const</span> V<span class="op">&amp;</span> value<span class="op">)</span> <span class="cf">default</span> <span class="op">{</span></span>
<span id="cb64-9"><a href="#cb64-9" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> x <span class="op">:</span> range<span class="op">)</span> <span class="op">{</span></span>
<span id="cb64-10"><a href="#cb64-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>x <span class="op">==</span> value<span class="op">)</span> <span class="cf">return</span> <span class="kw">true</span>;</span>
<span id="cb64-11"><a href="#cb64-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb64-12"><a href="#cb64-12" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="kw">false</span>;</span>
<span id="cb64-13"><a href="#cb64-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb64-14"><a href="#cb64-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb64-15"><a href="#cb64-15" 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="cb64-16"><a href="#cb64-16" aria-hidden="true" tabindex="-1"></a><span class="kw">requires</span> std<span class="op">::</span>equality_comparable<span class="op">&lt;</span>T<span class="op">&gt;</span></span>
<span id="cb64-17"><a href="#cb64-17" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> contains<span class="op">(</span><span class="kw">const</span> my_container<span class="op">&lt;</span>T<span class="op">&gt;&amp;</span> c, <span class="kw">const</span> T<span class="op">&amp;</span> value<span class="op">)</span> <span class="kw">noexcept</span> <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb64-18"><a href="#cb64-18" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> c<span class="op">.</span>find<span class="op">(</span>value<span class="op">)</span> <span class="op">!=</span> c<span class="op">.</span>end<span class="op">()</span>;</span>
<span id="cb64-19"><a href="#cb64-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Then when evaluating the following call to
<code class="sourceCode default">contains()</code>:</p>
<div class="sourceCode" id="cb65"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb65-1"><a href="#cb65-1" aria-hidden="true" tabindex="-1"></a>my_container<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> c;</span>
<span id="cb65-2"><a href="#cb65-2" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> result <span class="op">=</span> contains<span class="op">(</span>c, <span class="dv">42</span><span class="op">)</span>;</span></code></pre></div>
<p>The compiler performs the following steps:</p>
<ul>
<li>using the argument types
<code class="sourceCode default">my_container&lt;int&gt;&amp;</code> and
<code class="sourceCode default">int</code> performs overload resolution
on overloads of the <code class="sourceCode default">contains()</code>
customisable function (see <a href="#overload-resolution">overload
resolution</a>).</li>
<li>If the selected overload corresponds to an overload with an
<code class="sourceCode default">override</code> specifier, then we look
at the types of the parameters of the selected overload. In our example,
the parameter types are <code class="sourceCode default">(const my_container&lt;int&gt;&amp;, const int&amp;)</code>.</li>
<li>For each associated customisable function prototype, attempt to
deduce template arguments to make the parameter types of the prototype
identical to the parameter types of the selected overload.<br> Note:
This is exactly the mechanism used to deduce arguments to partial class
template specialisations.<br> Note: This means that non-dependent
parameter types must match exactly.<br> Note: Conversions are not
considered at this stage (they were already considered during overload
resolution)</li>
<li>If template argument deduction fails then this declaration is
removed from the considered set of declarations.</li>
<li>If template argument deduction succeeds then the compiler evaluates
the constraints to determine if the deduced template arguments satisfy
the constraints. In this example we evaluate the constraints:
<ul>
<li><code class="sourceCode default">std::ranges::range&lt;const my_container&lt;int&gt;&amp;&gt;</code></li>
<li><code class="sourceCode default">std::equality_comparable_with&lt;std::ranges::range_reference_t&lt;const my_container&lt;int&gt;&amp;&gt;, const int&amp;&gt;</code></li>
</ul></li>
<li>If the deduced template arguments do not satisfy the constraints,
then this declaration is removed from the considered set of
declarations.</li>
<li>If, after evaluating the constraints of all prototype declarations
there are no declarations remaining in the considered set of
declarations then the call expression is considered ill-formed.</li>
</ul>
<p>Important to note here is that the customisable function prototype
having parameters types that are unqualified template parameters that
appear to be prvalues does not necessarily mean that all customisations
must define those parameters as prvalues. If you want to require
customisations to accept parameters by-value then you will need to add
additional constraints for this. e.g.</p>
<div class="sourceCode" id="cb66"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb66-1"><a href="#cb66-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="cb66-2"><a href="#cb66-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> prvalue <span class="op">=</span> <span class="op">(!</span>std<span class="op">::</span>is_reference_v<span class="op">&lt;</span>T<span class="op">&gt;)</span>;</span>
<span id="cb66-3"><a href="#cb66-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb66-4"><a href="#cb66-4" aria-hidden="true" tabindex="-1"></a><span class="co">// Force customisations to accept parameters by-value</span></span>
<span id="cb66-5"><a href="#cb66-5" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> combine<span class="op">(</span>prvalue <span class="kw">auto</span> first, prvalue <span class="kw">auto</span> second<span class="op">)</span> customisable;</span></code></pre></div>
<p>It is also important to note that we can constrain the signature of
the selected overload to have particular concrete parameter types, or to
have a parameter that is a specialization of a particular template.
e.g.</p>
<div class="sourceCode" id="cb67"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb67-1"><a href="#cb67-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Shape<span class="op">&gt;</span></span>
<span id="cb67-2"><a href="#cb67-2" aria-hidden="true" tabindex="-1"></a>Shape scale<span class="op">(</span>Shape s, <span class="dt">float</span> factor<span class="op">)</span> customisable; <span class="co">// &#39;factor&#39; param must be</span></span>
<span id="cb67-3"><a href="#cb67-3" aria-hidden="true" tabindex="-1"></a>                                                 <span class="co">// &#39;float&#39; to match signature.</span></span>
<span id="cb67-4"><a href="#cb67-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb67-5"><a href="#cb67-5" aria-hidden="true" tabindex="-1"></a><span class="co">// The &#39;request&#39; parameter can be constrained to be a shared_ptr of some</span></span>
<span id="cb67-6"><a href="#cb67-6" aria-hidden="true" tabindex="-1"></a><span class="co">// type that satisfies the &#39;httplib::request&#39; concept.</span></span>
<span id="cb67-7"><a href="#cb67-7" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Processor, httplib<span class="op">::</span>request Request<span class="op">&gt;</span></span>
<span id="cb67-8"><a href="#cb67-8" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> process_request<span class="op">(</span>Processor<span class="op">&amp;</span> p,</span>
<span id="cb67-9"><a href="#cb67-9" aria-hidden="true" tabindex="-1"></a>                     std<span class="op">::</span>shared_ptr<span class="op">&lt;</span>Request<span class="op">&gt;</span> request<span class="op">)</span> customisable;</span></code></pre></div>
<h3 data-number="9.8.4" id="constraining-return-types"><span class="header-section-number">9.8.4</span> Constraining return types<a href="#constraining-return-types" class="self-link"></a></h3>
<p>Often, a customisation point wants to allow the return type of the
customisation point to be deduced from the customisation, but still
wants to be able to constrain customisations to require that they return
types that satisfy some concept or other constraints.</p>
<p>For example, the
<code class="sourceCode default">std::ranges::begin()</code>
customisation point allows customisations to determine the return type
(different types of ranges usually need different iterator types) but
requires customisations to return a type that satisfies <code class="sourceCode default">std::ranges::input_or_output_iterator</code>.</p>
<p>Where there is an existing concept that describes the return type
requirements one can use the
<code class="sourceCode default">concept-auto</code> syntax for the
return type to require that the return type satisfies some concept.</p>
<p>For example, the
<code class="sourceCode default">std::ranges::begin()</code>
customisation point might be defined as follows:</p>
<div class="sourceCode" id="cb68"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb68-1"><a href="#cb68-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb68-2"><a href="#cb68-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> R<span class="op">&gt;</span></span>
<span id="cb68-3"><a href="#cb68-3" aria-hidden="true" tabindex="-1"></a>  input_or_output_iterator <span class="kw">auto</span> begin<span class="op">(</span>R range<span class="op">)</span> customisable;</span>
<span id="cb68-4"><a href="#cb68-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb68-5"><a href="#cb68-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, std<span class="op">::</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb68-6"><a href="#cb68-6" aria-hidden="true" tabindex="-1"></a>  T<span class="op">*</span> begin<span class="op">(</span>T<span class="op">(&amp;</span>range<span class="op">)[</span>N<span class="op">])</span> <span class="kw">noexcept</span> <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb68-7"><a href="#cb68-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> range;</span>
<span id="cb68-8"><a href="#cb68-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb68-9"><a href="#cb68-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb68-10"><a href="#cb68-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> R<span class="op">&gt;</span></span>
<span id="cb68-11"><a href="#cb68-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> <span class="op">(</span>R<span class="op">&amp;</span> r<span class="op">)</span> <span class="op">{</span> <span class="op">{</span> <span class="kw">auto</span><span class="op">(</span>r<span class="op">.</span>begin<span class="op">())</span>; <span class="op">}</span> <span class="op">-&gt;</span> input_or_output_iterator <span class="op">}</span></span>
<span id="cb68-12"><a href="#cb68-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> begin<span class="op">(</span>R<span class="op">&amp;&amp;</span> r<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(</span><span class="kw">noexcept</span><span class="op">(</span>r<span class="op">.</span>begin<span class="op">()))</span> <span class="cf">default</span> <span class="op">{</span></span>
<span id="cb68-13"><a href="#cb68-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> r<span class="op">.</span>begin<span class="op">()</span>;</span>
<span id="cb68-14"><a href="#cb68-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb68-15"><a href="#cb68-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Much like the act of constraining parameters in the previous section,
the return type is also deduced from the signature of the selected
overload and then constraints are then applied to the deduced template
parameters.</p>
<p>The <code class="sourceCode default">begin()</code> customisable
function prototype above uses the
<code class="sourceCode default">concept-auto</code> syntax, which this
paper is defining as a syntactic sugar for the following equivalent
code:</p>
<div class="sourceCode" id="cb69"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb69-1"><a href="#cb69-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges</span>
<span id="cb69-2"><a href="#cb69-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb69-3"><a href="#cb69-3" 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> It<span class="op">&gt;</span></span>
<span id="cb69-4"><a href="#cb69-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> input_or_output_iterator<span class="op">&lt;</span>It<span class="op">&gt;</span></span>
<span id="cb69-5"><a href="#cb69-5" aria-hidden="true" tabindex="-1"></a>  It begin<span class="op">(</span>R range<span class="op">)</span> customisable;</span>
<span id="cb69-6"><a href="#cb69-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>When a call to a customisable function is made, the compiler looks at
the signature of the selected overload and then uses this signature
(both the return type and the parameter-types) to deduce the template
arguments of the customisable function prototype. Constraints can then
be applied to a deduced return type.</p>
<p>This more explicit syntax can be used to apply multiple constraints
to the return type, or apply constraints to a function of the return
type without having to define a new concept that composes those
constraints. e.g.</p>
<div class="sourceCode" id="cb70"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb70-1"><a href="#cb70-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> T<span class="op">&gt;</span></span>
<span id="cb70-2"><a href="#cb70-2" aria-hidden="true" tabindex="-1"></a><span class="kw">requires</span> decay_copyable<span class="op">&lt;</span>R<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> some_concept<span class="op">&lt;</span>std<span class="op">::</span>decay_t<span class="op">&lt;</span>R<span class="op">&gt;&gt;</span></span>
<span id="cb70-3"><a href="#cb70-3" aria-hidden="true" tabindex="-1"></a>R some_getter<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> x<span class="op">)</span> customisable;</span></code></pre></div>
<h1 data-number="10" id="additional-design-discussions"><span class="header-section-number">10</span> Additional Design Discussions<a href="#additional-design-discussions" class="self-link"></a></h1>
<h2 data-number="10.1" id="syntax"><span class="header-section-number">10.1</span> Syntax<a href="#syntax" class="self-link"></a></h2>
<p>This version of the proposal uses the
<code class="sourceCode default">customisable</code> contextual keyword,
and uses <code class="sourceCode default">customisable</code>,
<code class="sourceCode default">default</code>,
<code class="sourceCode default">override</code> and
<code class="sourceCode default">final</code> all as trailing keywords
in function declarations. The syntax is of course subject to change.</p>
<p>R0 of the proposal used the
<code class="sourceCode default">virtual</code> keyword, on non-member
functions, as an argument could be made that what we proposes is, in
some way, a form of static polymorphism.</p>
<p>However, it is clear from the initial reactions, that most people
associate <code class="sourceCode default">virtual</code> with
inheritence and dynamic polymorphism. As this proposal is definitively
not that (it is a compile-time mechanism which does not impact runtime
performance), R1 introduced a different syntax.</p>
<p>Some additional concerns were raised that
<code class="sourceCode default">virtual</code> may also be used by
multimethods, should such a proposal ever be made and be accepted. We
note in languages with a similar feature, the syntactic marker is
usually on parameters rather than on the function itself, and so there
would not be an issue in terms of keeping the design space open.</p>
<p>In general, we agree that there were enough arguments against
<code class="sourceCode default">virtual</code> to warrant a different
syntax. We realized a syntax not associated with dynamic polymorphism
would be better perceived and more easily learned by C++ users.</p>
<p>We welcome suggestions to further improve the syntax.</p>
<h2 data-number="10.2" id="default-arguments"><span class="header-section-number">10.2</span> Default arguments<a href="#default-arguments" class="self-link"></a></h2>
<p>Default arguments are not currently permitted for customisable
function prototypes or for declarations of default implementations or
customisations of customisable functions.</p>
<p>Support for default arguments may be explored as an extension in
future if desired.</p>
<h2 data-number="10.3" id="attributes"><span class="header-section-number">10.3</span> Attributes<a href="#attributes" class="self-link"></a></h2>
<p>It should be possible to place attributes like
<code class="sourceCode default">[[deprecated]]</code> and
<code class="sourceCode default">[[noreturn]]</code> on customisable
function prototypes, this has not been fully fleshed out yet.</p>
<h2 data-number="10.4" id="controlling-the-set-of-associated-namespaces"><span class="header-section-number">10.4</span> Controlling the set of
associated namespaces<a href="#controlling-the-set-of-associated-namespaces" class="self-link"></a></h2>
<p>This proposal makes use of argument-dependent lookup for finding
customisations of customisable functions.</p>
<p>The current argument dependent lookup rules can often result in the
compiler searching many more associated namespaces for overloads than
desired, hurting compile-times and sometimes resulting in unexpected
overloads being called.</p>
<p>It would be great if we had better control over which set of
associated namespaces the compiler considers when performing
argument-dependent lookup.</p>
<p>There are two main features that could be considered as companions to
this paper: - Declaring that certain parameters of a customisable
function should not be considered when constructing the list of
associated namespaces (this can build on top of this paper) - Declaring
that certain template parameters of a class template should not be
considered when constructing the list of associated namespaces (this is
discussed in <span class="citation" data-cites="P2256R0">[<a href="#ref-P2256R0" role="doc-biblioref"><strong>P2256R0?</strong></a>]</span>).</p>
<h2 data-number="10.5" id="comparison-to-rust-traits"><span class="header-section-number">10.5</span> Comparison to Rust Traits<a href="#comparison-to-rust-traits" class="self-link"></a></h2>
<p>This is an example from Barry Revzin’s blog post on customisation
points <span class="citation" data-cites="Revzin2020">[<a href="#ref-Revzin2020" role="doc-biblioref">Revzin2020</a>]</span>,
which compares C++ to Rust at the end when discussing ideals.</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Rust</strong>
</div></th>
<th><div style="text-align:center">
<strong>This proposal</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb1"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">trait</span> <span class="bu">PartialEq</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> eq(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> rhs<span class="op">:</span> <span class="op">&amp;</span><span class="dt">Self</span>) <span class="op">-&gt;</span> <span class="dt">bool</span><span class="op">;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">fn</span> ne(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> rhs<span class="op">:</span> <span class="op">&amp;</span><span class="dt">Self</span>) <span class="op">-&gt;</span> <span class="dt">bool</span> <span class="op">{</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">!</span><span class="kw">self</span><span class="op">.</span>eq(rhs)</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>

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

<div class="sourceCode" id="cb71"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb71-1"><a href="#cb71-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="cb71-2"><a href="#cb71-2" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> eq<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> x, <span class="kw">const</span> T<span class="op">&amp;</span> y<span class="op">)</span> customisable;</span>
<span id="cb71-3"><a href="#cb71-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb71-4"><a href="#cb71-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="cb71-5"><a href="#cb71-5" aria-hidden="true" tabindex="-1"></a><span class="kw">requires</span> <span class="kw">requires</span><span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> x, <span class="kw">const</span> T<span class="op">&amp;</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb71-6"><a href="#cb71-6" aria-hidden="true" tabindex="-1"></a>  eq<span class="op">(</span>x, y<span class="op">)</span>;</span>
<span id="cb71-7"><a href="#cb71-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb71-8"><a href="#cb71-8" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> ne<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> x, <span class="kw">const</span> T<span class="op">&amp;</span> y<span class="op">)</span> customisable;</span>
<span id="cb71-9"><a href="#cb71-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb71-10"><a href="#cb71-10" aria-hidden="true" tabindex="-1"></a><span class="dt">bool</span> ne<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> x, <span class="kw">const</span> T<span class="op">&amp;</span> y<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(</span>eq<span class="op">(</span>x, y<span class="op">))</span> <span class="cf">default</span> <span class="op">{</span></span>
<span id="cb71-11"><a href="#cb71-11" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="op">!</span>eq<span class="op">(</span>x, y<span class="op">)</span>;</span>
<span id="cb71-12"><a href="#cb71-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb71-13"><a href="#cb71-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb71-14"><a href="#cb71-14" 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="cb71-15"><a href="#cb71-15" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> PartialEq <span class="op">=</span></span>
<span id="cb71-16"><a href="#cb71-16" aria-hidden="true" tabindex="-1"></a><span class="kw">requires</span><span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> x, <span class="kw">const</span> T<span class="op">&amp;</span> y<span class="op">)</span> <span class="op">{</span></span>
<span id="cb71-17"><a href="#cb71-17" aria-hidden="true" tabindex="-1"></a>    eq<span class="op">(</span>x, y<span class="op">)</span>;</span>
<span id="cb71-18"><a href="#cb71-18" aria-hidden="true" tabindex="-1"></a>    ne<span class="op">(</span>x, y<span class="op">)</span>;</span>
<span id="cb71-19"><a href="#cb71-19" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
<tr class="even">
<td><div>

<div class="sourceCode" id="cb2"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Point <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  x<span class="op">:</span> <span class="dt">f64</span><span class="op">,</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  y<span class="op">:</span> <span class="dt">f64</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>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="kw">impl</span> <span class="bu">PartialEq</span> <span class="cf">for</span> Point <span class="op">{</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">fn</span> eq(<span class="op">&amp;</span><span class="kw">self</span><span class="op">,</span> rhs<span class="op">:</span> <span class="op">&amp;</span><span class="dt">Self</span>) <span class="op">-&gt;</span> <span class="dt">bool</span> <span class="op">{</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>    eq(<span class="kw">self</span><span class="op">.</span>x<span class="op">,</span> rhs<span class="op">.</span>x) <span class="op">&amp;&amp;</span> eq(<span class="kw">self</span><span class="op">.</span>y<span class="op">,</span> rhs<span class="op">.</span>y)</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

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

<div class="sourceCode" id="cb72"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb72-1"><a href="#cb72-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Point <span class="op">{</span></span>
<span id="cb72-2"><a href="#cb72-2" aria-hidden="true" tabindex="-1"></a>  <span class="dt">double</span> x;</span>
<span id="cb72-3"><a href="#cb72-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">double</span> y;</span>
<span id="cb72-4"><a href="#cb72-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb72-5"><a href="#cb72-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="dt">bool</span> eq<span class="op">(</span><span class="kw">const</span> Point<span class="op">&amp;</span> lhs,</span>
<span id="cb72-6"><a href="#cb72-6" aria-hidden="true" tabindex="-1"></a>                 <span class="kw">const</span> Point<span class="op">&amp;</span> rhs<span class="op">)</span> <span class="kw">override</span> <span class="op">{</span></span>
<span id="cb72-7"><a href="#cb72-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> eq<span class="op">(</span>lhs<span class="op">.</span>x, rhs<span class="op">.</span>x<span class="op">)</span> <span class="op">&amp;&amp;</span> eq<span class="op">(</span>lhs<span class="op">.</span>y, rhs<span class="op">.</span>y<span class="op">)</span>;</span>
<span id="cb72-8"><a href="#cb72-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb72-9"><a href="#cb72-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb72-10"><a href="#cb72-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb72-11"><a href="#cb72-11" aria-hidden="true" tabindex="-1"></a><span class="kw">static_assert</span><span class="op">(</span>PartialEq<span class="op">&lt;</span>Point<span class="op">&gt;)</span>;</span></code></pre></div>

</div></td>
</tr>
<tr class="odd">
<td><div>

<div class="sourceCode" id="cb3"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> a <span class="op">=</span> Point <span class="op">{</span> x<span class="op">:</span> <span class="dv">1.0</span><span class="op">,</span> y<span class="op">:</span> <span class="dv">2.0</span> <span class="op">};</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> b <span class="op">=</span> Point <span class="op">{</span> x<span class="op">:</span> <span class="dv">1.0</span><span class="op">,</span> y<span class="op">:</span> <span class="dv">3.0</span> <span class="op">};</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> a<span class="op">.</span>eq(b) <span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>  <span class="pp">println!</span>(<span class="st">&quot;equal&quot;</span>)<span class="op">;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

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

<div class="sourceCode" id="cb73"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb73-1"><a href="#cb73-1" aria-hidden="true" tabindex="-1"></a>Point a<span class="op">{</span><span class="fl">1.0</span>, <span class="fl">2.0</span><span class="op">}</span>;</span>
<span id="cb73-2"><a href="#cb73-2" aria-hidden="true" tabindex="-1"></a>Point b<span class="op">{</span><span class="fl">1.0</span>, <span class="fl">3.0</span><span class="op">}</span>;</span>
<span id="cb73-3"><a href="#cb73-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb73-4"><a href="#cb73-4" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(</span>eq<span class="op">(</span>a, b<span class="op">))</span> <span class="op">{</span></span>
<span id="cb73-5"><a href="#cb73-5" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>puts<span class="op">(</span><span class="st">&quot;equal&quot;</span><span class="op">)</span>;</span>
<span id="cb73-6"><a href="#cb73-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>We are able to express the same semantics in C++, although without
some of the explicitness that we get from the Rust implementation of
<code class="sourceCode default">PartialEq</code>. The C++ code that
customises <code class="sourceCode default">eq()</code> does not make
any reference to the <code class="sourceCode default">PartialEq</code>
concept to indicate that we are customising a function associated with
that trait.</p>
<p>The implementation on the C++ side is slightly more involved:</p>
<ul>
<li>The declaration of the <code class="sourceCode default">ne()</code>
prototype requires that <code class="sourceCode default">eq()</code> is
valid. This means you can’t accidentally customise
<code class="sourceCode default">ne()</code> and not define
<code class="sourceCode default">eq()</code>.</li>
<li>The default implementation of
<code class="sourceCode default">ne()</code> deals with forwarding
<code class="sourceCode default">noexcept</code>-ness</li>
</ul>
<h2 data-number="10.6" id="redefining-existing-customisation-points-in-terms-of-this-solution"><span class="header-section-number">10.6</span> Redefining existing
customisation points in terms of this solution<a href="#redefining-existing-customisation-points-in-terms-of-this-solution" class="self-link"></a></h2>
<p>Our intent is to replace all
<code class="sourceCode default">tag_invoke</code> usages in <span class="citation" data-cites="P2300R5">[<a href="#ref-P2300R5" role="doc-biblioref">P2300R5</a>]</span> by this proposal. (<span class="citation" data-cites="P2300R5">[<a href="#ref-P2300R5" role="doc-biblioref">P2300R5</a>]</span> makes extensive use of CPOs and
forwarding)</p>
<p>We also cover other usage patterns of the standard library like
<code class="sourceCode default">swap</code>,
<code class="sourceCode default">std::begin</code>,
<code class="sourceCode default">ranges::begin</code>,
<code class="sourceCode default">std::get</code>, etc.</p>
<p>However we have not investigated whether it would be possible to
respecify the existing facilities in terms of language customisable
functions without ABI breaks or subtle change of behaviour and we are
not proposing to do that in this paper.</p>
<p>Some facilities, like ranges for loops and structured bindings are
currently specified in terms of raw ADL calls.</p>
<h1 data-number="11" id="implementation"><span class="header-section-number">11</span> Implementation<a href="#implementation" class="self-link"></a></h1>
<p>This proposal has not yet been implemented in a compiler and so does
not yet have implementation or usage experience. The authors are seeking
directional guidance from the language evolution group at this point in
time.</p>
<h1 data-number="12" id="acknowledgements"><span class="header-section-number">12</span> Acknowledgements<a href="#acknowledgements" class="self-link"></a></h1>
<ul>
<li>Barry Revzin, for generously providing his time to read and give
feedback on early drafts of this paper.</li>
<li>Sean Baxter, for implementing an early draft of this feature in his
circle compiler. It found many an underspecification, and we are looking
forward to having a full test suite in time.</li>
</ul>
<h1 data-number="13" id="bibliography"><span class="header-section-number">13</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-Odwyer2019" class="csl-entry" role="doc-biblioentry">
[O’Dwyer2019] Arthur O’Dwyer. How hana::type<T> disables ADL. <a href="https://quuxplusone.github.io/blog/2019/04/09/adl-insanity-round-2/"><div class="csl-block">https://quuxplusone.github.io/blog/2019/04/09/adl-insanity-round-2/</div></a>
</div>
<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-P1170R0" class="csl-entry" role="doc-biblioentry">
[P1170R0] Barry Revzin, Andrew Sutton. 2018-10-08. Overload sets as
function parameters. <a href="https://wg21.link/p1170r0"><div class="csl-block">https://wg21.link/p1170r0</div></a>
</div>
<div id="ref-P1292R0" class="csl-entry" role="doc-biblioentry">
[P1292R0] Matt Calabrese. 2018-10-08. Customization Point Functions. <a href="https://wg21.link/p1292r0"><div class="csl-block">https://wg21.link/p1292r0</div></a>
</div>
<div id="ref-P1895R0" class="csl-entry" role="doc-biblioentry">
[P1895R0] Lewis Baker, Eric Niebler, Kirk Shoop. 2019-10-08. tag_invoke:
A general pattern for supporting customisable functions. <a href="https://wg21.link/p1895r0"><div class="csl-block">https://wg21.link/p1895r0</div></a>
</div>
<div id="ref-P2175R0" class="csl-entry" role="doc-biblioentry">
[P2175R0] Lewis Baker. 2020-12-15. Composable cancellation for
sender-based async operations. <a href="https://wg21.link/p2175r0"><div class="csl-block">https://wg21.link/p2175r0</div></a>
</div>
<div id="ref-P2279R0" class="csl-entry" role="doc-biblioentry">
[P2279R0] Barry Revzin. 2021-01-15. We need a language mechanism for
customization points. <a href="https://wg21.link/p2279r0"><div class="csl-block">https://wg21.link/p2279r0</div></a>
</div>
<div id="ref-P2300R0" class="csl-entry" role="doc-biblioentry">
[P2300R0] Michał Dominiak, Lewis Baker, Lee Howes, Michael Garland, Eric
Niebler, Bryce Adelstein Lelbach. 2021-06-16. std::execution. <a href="https://wg21.link/p2300r0"><div class="csl-block">https://wg21.link/p2300r0</div></a>
</div>
<div id="ref-P2300R4" class="csl-entry" role="doc-biblioentry">
[P2300R4] Michał Dominiak, Lewis Baker, Lee Howes, Kirk Shoop, Michael
Garland, Eric Niebler, Bryce Adelstein Lelbach. 2022-01-19.
std::execution. <a href="https://wg21.link/p2300r4"><div class="csl-block">https://wg21.link/p2300r4</div></a>
</div>
<div id="ref-P2300R5" class="csl-entry" role="doc-biblioentry">
[P2300R5] Michał Dominiak, Georgy Evtushenko, Lewis Baker, Lucian Radu
Teodorescu, Lee Howes, Kirk Shoop, Michael Garland, Eric Niebler, Bryce
Adelstein Lelbach. 2022-04-22. `std::execution`. <a href="https://wg21.link/p2300r5"><div class="csl-block">https://wg21.link/p2300r5</div></a>
</div>
<div id="ref-Revzin2020" class="csl-entry" role="doc-biblioentry">
[Revzin2020] Barry Revzin. Why tag_invoke is not the solution I want. <a href="https://brevzin.github.io/c++/2020/12/01/tag-invoke/"><div class="csl-block">https://brevzin.github.io/c++/2020/12/01/tag-invoke/</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
