<!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="2021-04-05" />
  <title>static `operator()`</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.hanging-indent{margin-left: 1.5em; text-indent: -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; }
      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;
}
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>
  <style type="text/css">a {
color : #4183C4;
text-decoration: underline;
}
a.marginalized {
text-decoration: none;
}
a.self-link {
text-decoration: none;
}
h1#toctitle {
border-bottom: 1px solid #cccccc;
}
#TOC li {
margin-top: 1px;
margin-bottom: 1px;
}
#TOC ul>li:before { display: none; }
h3.subtitle { margin-top: -15px; }
h1:target { background-color: transparent; }
h2:target { background-color: transparent; }
h3:target { background-color: transparent; }
h4:target { background-color: transparent; }
h5:target { background-color: transparent; }
h6:target { background-color: transparent; }
code span.co { font-family: monospace; }
table tr {
background-color: white;
}
table tr:nth-child(2n) {
background-color: #f6f8fa;
}
#title-block-header > table tr:nth-child(2n) {
background-color: white;
}
td > div.sourceCode {
background-color: inherit;
}
table {
border-collapse: collapse;
}
table td, table th {
border: 1px solid #cccccc;
}
table th {
border-bottom: 1px solid black;
text-align: center;
}
table tr:first-child th {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child,
table tr th:first-child {
border-left: 0;
}
table tr td:last-child,
table tr th:last-child {
border-right: 0;
}
table tbody tr:first-child td {
border-top: 1px solid black;
}
#title-block-header td { border: 0; }
@media all {
body {
margin: 2em;
}
}
@media screen and (min-width: 480px) {
body {
margin: 5em;
}
}
#refs code{padding-left: 0px; text-indent: 0px;}
:root {
--diff-ins: #e6ffed;
--diff-strongins: #acf2bd;
--diff-del: #ffdddd;
--diff-strongdel: #ff8888;
}
span.diffins {
background-color: var(--diff-strongins);
}
span.diffdel {
background-color: var(--diff-strongdel);
}
div.rm { text-decoration: line-through; }
div.rm code.sourceCode { text-decoration: line-through; }
div.addu, span.addu {
color: #006e28;
background-color: var(--diff-ins);
}

div.rm pre, div.add pre { background-color: #f6f8fa; }
div.addu pre { background-color: var(--diff-ins); }
div.add, div.add pre { background-color: var(--diff-ins); }
div.addu blockquote {
border-left: 4px solid #00a000;
padding: 0 15px;
color: #006e28;
text-decoration: none;
}
div.addu blockquote code.sourceCode { text-decoration: none; }
div.addu blockquote pre { text-decoration: none; }
div.addu blockquote pre code { text-decoration: none; }
div.quote {
border-left: 7px solid #ccc;
background: #f9f9f9;
margin: 1.5em 10px;
padding-left: 20px;
}
code.diff span.va { color: #000000; background-color: var(--diff-ins); }
code.diff span.st { color: #000000; background-color: var(--diff-del); }
</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">static <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code></h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P1169R1</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2021-04-05</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      EWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Barry Revzin<br>&lt;<a href="mailto:barry.revzin@gmail.com" class="email">barry.revzin@gmail.com</a>&gt;<br>
      Casey Carter<br>&lt;<a href="mailto:casey@carter.net" class="email">casey@carter.net</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="#revision-history"><span class="toc-section-number">1</span> Revision History<span></span></a></li>
<li><a href="#motivation"><span class="toc-section-number">2</span> Motivation<span></span></a></li>
<li><a href="#proposal"><span class="toc-section-number">3</span> Proposal<span></span></a>
<ul>
<li><a href="#overload-resolution"><span class="toc-section-number">3.1</span> Overload Resolution<span></span></a></li>
<li><a href="#lambdas"><span class="toc-section-number">3.2</span> Lambdas<span></span></a></li>
<li><a href="#deduction-guides"><span class="toc-section-number">3.3</span> Deduction Guides<span></span></a></li>
<li><a href="#prior-references"><span class="toc-section-number">3.4</span> Prior References<span></span></a></li>
<li><a href="#implementation-experience"><span class="toc-section-number">3.5</span> Implementation Experience<span></span></a></li>
</ul></li>
<li><a href="#wording"><span class="toc-section-number">4</span> Wording<span></span></a>
<ul>
<li><a href="#language-wording"><span class="toc-section-number">4.1</span> Language Wording<span></span></a></li>
<li><a href="#library-wording"><span class="toc-section-number">4.2</span> Library Wording<span></span></a></li>
</ul></li>
<li><a href="#bibliography"><span class="toc-section-number">5</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="revision-history"><span class="header-section-number">1</span> Revision History<a href="#revision-history" class="self-link"></a></h1>
<p><span class="citation" data-cites="P1169R0">[<a href="#ref-P1169R0" role="doc-biblioref">P1169R0</a>]</span> was presented to EWGI in San Diego, where there was no consensus to pursue the paper. However, recent discussion has caused renewed interest in this paper so it has been resurfaced. R0 of this paper additionally proposed implicitly changing capture-less lambdas to have static function call operators, which would be an breaking change. That part of this paper has been changed to instead allow for an explicit opt-in to static. Additionally, this language change has been implemented.</p>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="motivation"><span class="header-section-number">2</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>The standard library has always accepted arbitrary function objects - whether to be unary or binary predicates, or perform arbitrary operations. Function objects with call operator templates in particular have a significant advantage today over using overload sets since you can just pass them into algorithms. This makes, for instance, <code class="sourceCode cpp">std<span class="op">::</span>less<span class="op">&lt;&gt;{}</span></code> very useful.</p>
<p>As part of the Ranges work, more and more function objects are being added to the standard library - the set of Customization Point Objects (CPOs). These objects are Callable, but they don’t, as a rule, have any members. They simply exist to do what Eric Niebler termed the <a href="http://ericniebler.com/2014/10/21/customization-point-design-in-c11-and-beyond/">“Std Swap Two-Step”</a>. Nevertheless, the call operators of all of these types are non-static member functions. Because <em>all</em> call operators have to be non-static member functions.</p>
<p>What this means is that if the call operator happens to not be inlined, an extra register must be used to pass in the <code class="sourceCode cpp"><span class="kw">this</span></code> pointer to the object - even if there is no need for it whatsoever. Here is a <a href="https://godbolt.org/z/ajTZo2">simple example</a>:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a><span class="kw">struct</span> X <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2"></a>    <span class="dt">bool</span> <span class="kw">operator</span><span class="op">()(</span><span class="dt">int</span><span class="op">)</span> <span class="kw">const</span>;</span>
<span id="cb1-3"><a href="#cb1-3"></a>    <span class="kw">static</span> <span class="dt">bool</span> f<span class="op">(</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb1-4"><a href="#cb1-4"></a><span class="op">}</span>;</span>
<span id="cb1-5"><a href="#cb1-5"></a></span>
<span id="cb1-6"><a href="#cb1-6"></a><span class="kw">inline</span> <span class="kw">constexpr</span> X x;</span>
<span id="cb1-7"><a href="#cb1-7"></a></span>
<span id="cb1-8"><a href="#cb1-8"></a><span class="dt">int</span> count_x<span class="op">(</span>std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> <span class="kw">const</span><span class="op">&amp;</span> xs<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-9"><a href="#cb1-9"></a>    <span class="cf">return</span> std<span class="op">::</span>count_if<span class="op">(</span>xs<span class="op">.</span>begin<span class="op">()</span>, xs<span class="op">.</span>end<span class="op">()</span>,</span>
<span id="cb1-10"><a href="#cb1-10"></a><span class="pp">#ifdef STATIC</span></span>
<span id="cb1-11"><a href="#cb1-11"></a>    X<span class="op">::</span>f</span>
<span id="cb1-12"><a href="#cb1-12"></a><span class="pp">#else</span></span>
<span id="cb1-13"><a href="#cb1-13"></a>    x</span>
<span id="cb1-14"><a href="#cb1-14"></a><span class="pp">#endif</span></span>
<span id="cb1-15"><a href="#cb1-15"></a>    <span class="op">)</span>;</span>
<span id="cb1-16"><a href="#cb1-16"></a><span class="op">}</span>    </span></code></pre></div>
<p><code class="sourceCode cpp">x</code> is a global function object that has no members that is intended to be passed into various algorithms. But in order to work in algorithms, it needs to have a call operator - which must be non-static. You can see the difference in the generated asm btween using the function object as intended and passing in an equivalent static member function:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Non-static call operator</strong>
</div></th>
<th><div style="text-align:center">
<strong>Static member function</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb2"><pre class="sourceCode nasm"><code class="sourceCode nasm"><span id="cb2-1"><a href="#cb2-1"></a>count_x(<span class="kw">std</span>::vector&lt;<span class="kw">int</span>, <span class="kw">std</span>::allocator&lt;<span class="kw">int</span>&gt; &gt; const&amp;):</span>
<span id="cb2-2"><a href="#cb2-2"></a>        <span class="kw">push</span>    r12</span>
<span id="cb2-3"><a href="#cb2-3"></a>        <span class="kw">push</span>    rbp</span>
<span id="cb2-4"><a href="#cb2-4"></a>        <span class="kw">push</span>    rbx</span>
<span id="cb2-5"><a href="#cb2-5"></a>        <span class="kw">sub</span>     rsp, <span class="dv">16</span></span>
<span id="cb2-6"><a href="#cb2-6"></a>        <span class="kw">mov</span>     r12, <span class="dt">QWORD</span> <span class="dt">PTR</span> [rdi+<span class="dv">8</span>]</span>
<span id="cb2-7"><a href="#cb2-7"></a>        <span class="kw">mov</span>     rbx, <span class="dt">QWORD</span> <span class="dt">PTR</span> [rdi]</span>
<span id="cb2-8"><a href="#cb2-8"></a>        <span class="addu"><span class="kw">mov</span> <span class="dt">BYTE</span> <span class="dt">PTR</span> [rsp+<span class="dv">15</span>], <span class="dv">0</span></span></span>
<span id="cb2-9"><a href="#cb2-9"></a>        <span class="kw">cmp</span>     r12, rbx</span>
<span id="cb2-10"><a href="#cb2-10"></a>        <span class="kw">je</span>      .L5</span>
<span id="cb2-11"><a href="#cb2-11"></a>        <span class="kw">xor</span>     <span class="kw">ebp</span>, <span class="kw">ebp</span></span>
<span id="cb2-12"><a href="#cb2-12"></a><span class="fu">.L4:</span></span>
<span id="cb2-13"><a href="#cb2-13"></a>        <span class="kw">mov</span>     <span class="kw">esi</span>, <span class="dt">DWORD</span> <span class="dt">PTR</span> [rbx]</span>
<span id="cb2-14"><a href="#cb2-14"></a>        <span class="addu"><span class="kw">lea</span> rdi, [rsp+<span class="dv">15</span>]</span></span>
<span id="cb2-15"><a href="#cb2-15"></a>        <span class="kw">call</span>    X::operator()(<span class="kw">int</span>) const</span>
<span id="cb2-16"><a href="#cb2-16"></a>        <span class="kw">cmp</span>     <span class="kw">al</span>, <span class="dv">1</span></span>
<span id="cb2-17"><a href="#cb2-17"></a>        <span class="kw">sbb</span>     rbp, <span class="dv">-1</span></span>
<span id="cb2-18"><a href="#cb2-18"></a>        <span class="kw">add</span>     rbx, <span class="dv">4</span></span>
<span id="cb2-19"><a href="#cb2-19"></a>        <span class="kw">cmp</span>     r12, rbx</span>
<span id="cb2-20"><a href="#cb2-20"></a>        <span class="kw">jne</span>     .L4</span>
<span id="cb2-21"><a href="#cb2-21"></a>        <span class="kw">add</span>     rsp, <span class="dv">16</span></span>
<span id="cb2-22"><a href="#cb2-22"></a>        <span class="kw">mov</span>     <span class="kw">eax</span>, <span class="kw">ebp</span></span>
<span id="cb2-23"><a href="#cb2-23"></a>        <span class="kw">pop</span>     rbx</span>
<span id="cb2-24"><a href="#cb2-24"></a>        <span class="kw">pop</span>     rbp</span>
<span id="cb2-25"><a href="#cb2-25"></a>        <span class="kw">pop</span>     r12</span>
<span id="cb2-26"><a href="#cb2-26"></a>        <span class="kw">ret</span></span>
<span id="cb2-27"><a href="#cb2-27"></a><span class="fu">.L5:</span></span>
<span id="cb2-28"><a href="#cb2-28"></a>        <span class="kw">add</span>     rsp, <span class="dv">16</span></span>
<span id="cb2-29"><a href="#cb2-29"></a>        <span class="kw">xor</span>     <span class="kw">eax</span>, <span class="kw">eax</span></span>
<span id="cb2-30"><a href="#cb2-30"></a>        <span class="kw">pop</span>     rbx</span>
<span id="cb2-31"><a href="#cb2-31"></a>        <span class="kw">pop</span>     rbp</span>
<span id="cb2-32"><a href="#cb2-32"></a>        <span class="kw">pop</span>     r12</span>
<span id="cb2-33"><a href="#cb2-33"></a>        <span class="kw">ret</span>    </span></code></pre></div></td>
<td><div class="sourceCode" id="cb3"><pre class="sourceCode nasm"><code class="sourceCode nasm"><span id="cb3-1"><a href="#cb3-1"></a>count_x(<span class="kw">std</span>::vector&lt;<span class="kw">int</span>, <span class="kw">std</span>::allocator&lt;<span class="kw">int</span>&gt; &gt; const&amp;):</span>
<span id="cb3-2"><a href="#cb3-2"></a>        <span class="kw">push</span>    r12</span>
<span id="cb3-3"><a href="#cb3-3"></a>        <span class="kw">push</span>    rbp</span>
<span id="cb3-4"><a href="#cb3-4"></a>        <span class="kw">push</span>    rbx</span>
<span id="cb3-5"><a href="#cb3-5"></a>        <span class="kw">mov</span>     r12, <span class="dt">QWORD</span> <span class="dt">PTR</span> [rdi+<span class="dv">8</span>]</span>
<span id="cb3-6"><a href="#cb3-6"></a>        <span class="kw">mov</span>     rbx, <span class="dt">QWORD</span> <span class="dt">PTR</span> [rdi]</span>
<span id="cb3-7"><a href="#cb3-7"></a>        <span class="kw">cmp</span>     r12, rbx</span>
<span id="cb3-8"><a href="#cb3-8"></a>        <span class="kw">je</span>      .L5</span>
<span id="cb3-9"><a href="#cb3-9"></a>        <span class="kw">xor</span>     <span class="kw">ebp</span>, <span class="kw">ebp</span></span>
<span id="cb3-10"><a href="#cb3-10"></a><span class="fu">.L4:</span></span>
<span id="cb3-11"><a href="#cb3-11"></a>        <span class="kw">mov</span>     <span class="kw">edi</span>, <span class="dt">DWORD</span> <span class="dt">PTR</span> [rbx]</span>
<span id="cb3-12"><a href="#cb3-12"></a>        <span class="kw">call</span>    X::f(<span class="kw">int</span>)</span>
<span id="cb3-13"><a href="#cb3-13"></a>        <span class="kw">cmp</span>     <span class="kw">al</span>, <span class="dv">1</span></span>
<span id="cb3-14"><a href="#cb3-14"></a>        <span class="kw">sbb</span>     rbp, <span class="dv">-1</span></span>
<span id="cb3-15"><a href="#cb3-15"></a>        <span class="kw">add</span>     rbx, <span class="dv">4</span></span>
<span id="cb3-16"><a href="#cb3-16"></a>        <span class="kw">cmp</span>     r12, rbx</span>
<span id="cb3-17"><a href="#cb3-17"></a>        <span class="kw">jne</span>     .L4</span>
<span id="cb3-18"><a href="#cb3-18"></a>        <span class="kw">mov</span>     <span class="kw">eax</span>, <span class="kw">ebp</span></span>
<span id="cb3-19"><a href="#cb3-19"></a>        <span class="kw">pop</span>     rbx</span>
<span id="cb3-20"><a href="#cb3-20"></a>        <span class="kw">pop</span>     rbp</span>
<span id="cb3-21"><a href="#cb3-21"></a>        <span class="kw">pop</span>     r12</span>
<span id="cb3-22"><a href="#cb3-22"></a>        <span class="kw">ret</span></span>
<span id="cb3-23"><a href="#cb3-23"></a><span class="fu">.L5:</span></span>
<span id="cb3-24"><a href="#cb3-24"></a>        <span class="kw">pop</span>     rbx</span>
<span id="cb3-25"><a href="#cb3-25"></a>        <span class="kw">xor</span>     <span class="kw">eax</span>, <span class="kw">eax</span></span>
<span id="cb3-26"><a href="#cb3-26"></a>        <span class="kw">pop</span>     rbp</span>
<span id="cb3-27"><a href="#cb3-27"></a>        <span class="kw">pop</span>     r12</span>
<span id="cb3-28"><a href="#cb3-28"></a>        <span class="kw">ret</span>    </span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>Even in this simple example, you can see the extra zeroing out of <code class="sourceCode cpp"><span class="op">[</span>rsp<span class="op">+</span><span class="dv">15</span><span class="op">]</span></code>, the extra <code class="sourceCode cpp">lea</code> to move that zero-ed out area as the object parameter - which we know doesn’t need to be used. This is wasteful, and seems to violate the fundamental philosophy that we don’t pay for what we don’t need.</p>
<p>The typical way to express the idea that we don’t need an object parameter is to declare functions <code class="sourceCode cpp"><span class="kw">static</span></code>. We just don’t have that ability in this case.</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="proposal"><span class="header-section-number">3</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>The proposal is to just allow the ability to make the call operator a static member function, instead of requiring it to be a non-static member function. We have many years of experience with member-less function objects being useful. Let’s remove the unnecessary object parameter overhead. There does not seem to be any value provided by this restriction.</p>
<p>There are other operators that are currently required to be implemented as non-static member functions - all the unary operators, assignment, subscripting, conversion functions, and class member access. We do not believe that being able to declare any of these as static will have as much value, so we are not pursuing those at this time. We’re not aware of any use-case for making any of these other operators static, while the use-case of having stateless function objects is extremely common.</p>
<h2 data-number="3.1" id="overload-resolution"><span class="header-section-number">3.1</span> Overload Resolution<a href="#overload-resolution" class="self-link"></a></h2>
<p>There is one case that needs to be specially considered when it comes to overload resolution, which did not need to be considered until now:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1"></a><span class="kw">struct</span> less <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">()(</span><span class="dt">int</span> i, <span class="dt">int</span> j<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span> <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3"></a>        <span class="cf">return</span> i <span class="op">&lt;</span> j;</span>
<span id="cb4-4"><a href="#cb4-4"></a>    <span class="op">}</span></span>
<span id="cb4-5"><a href="#cb4-5"></a></span>
<span id="cb4-6"><a href="#cb4-6"></a>    <span class="kw">using</span> P <span class="op">=</span> <span class="dt">bool</span><span class="op">(*)(</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb4-7"><a href="#cb4-7"></a>    <span class="kw">operator</span> P<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> <span class="kw">operator</span><span class="op">()</span>; <span class="op">}</span></span>
<span id="cb4-8"><a href="#cb4-8"></a><span class="op">}</span>;</span>
<span id="cb4-9"><a href="#cb4-9"></a></span>
<span id="cb4-10"><a href="#cb4-10"></a><span class="kw">static_assert</span><span class="op">(</span>less<span class="op">{}(</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">))</span>;</span></code></pre></div>
<p>If we simply allow <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code> to be declared <code class="sourceCode cpp"><span class="kw">static</span></code>, we’d have two candidates here: the function call operator and the surrogate call function. Overload resolution between those candidates would work as considering between:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1"></a><span class="kw">operator</span><span class="op">()(</span><em>contrived-parameter</em>, <span class="dt">int</span>, <span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb5-2"><a href="#cb5-2"></a><em>call-function</em><span class="op">(</span><span class="dt">bool</span><span class="op">(*)(</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">)</span>, <span class="dt">int</span>, <span class="dt">int</span><span class="op">)</span>;</span></code></pre></div>
<p>And currently this is ambiguous because <span>12.2.4.1
 <a href="https://wg21.link/over.match.best.general">[over.match.best.general]</a></span>/1.1 stipulates that the conversion sequence for the contrived implicit object parameter of a static member function is neither better nor worse than <em>any other conversion sequence</em>. This needs to be reined in slightly such that the conversion sequence for the contrived implicit object parameter is neither better nor worse than any <em>standard</em> conversion sequence, but still better than user-defined or ellipsis conversion sequences. Such a change would disambiguate this case in favor of the call operator.</p>
<h2 data-number="3.2" id="lambdas"><span class="header-section-number">3.2</span> Lambdas<a href="#lambdas" class="self-link"></a></h2>
<p>A common source of function objects whose call operators could be static but are not are lambdas without any capture. Had we been able to declare the call operator static when lambdas were originally introduced in the language, we would surely have had a lambda such as:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1"></a><span class="kw">auto</span> four <span class="op">=</span> <span class="op">[]{</span> <span class="cf">return</span> <span class="dv">4</span>; <span class="op">}</span>;</span></code></pre></div>
<p>desugar into:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1"></a><span class="kw">struct</span> __unique <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">()()</span> <span class="op">{</span> <span class="cf">return</span> <span class="dv">4</span>; <span class="op">}</span>;</span>
<span id="cb7-3"><a href="#cb7-3"></a>    </span>
<span id="cb7-4"><a href="#cb7-4"></a>    <span class="kw">using</span> P <span class="op">=</span> <span class="dt">int</span><span class="op">()</span>;</span>
<span id="cb7-5"><a href="#cb7-5"></a>    <span class="kw">constexpr</span> <span class="kw">operator</span> P<span class="op">*()</span> <span class="op">{</span> <span class="cf">return</span> <span class="kw">operator</span><span class="op">()</span>; <span class="op">}</span></span>
<span id="cb7-6"><a href="#cb7-6"></a><span class="op">}</span>;</span>
<span id="cb7-7"><a href="#cb7-7"></a></span>
<span id="cb7-8"><a href="#cb7-8"></a>__unique four<span class="op">{}</span>;</span></code></pre></div>
<p>Rather than desugaring to a type that has a non-static call operator along with a conversion function that has to return some other function.</p>
<p>However, we can’t simply change such lambdas because this could break code. There exists code that takes a template parameter of callable type and does <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(&amp;</span>F<span class="op">::</span><span class="kw">operator</span><span class="op">())</span></code>, expecting the resulting type to be a pointer to member type (which is the only thing it can be right now). If we change captureless lambdas to have a static call operator implicitly, all such code would break for captureless lambdas. Additionally, this would be a language ABI break. While lambdas shouldn’t show up in your ABI anyway, we can’t with confidence state that such code doesn’t exist nor that such code deserves to be broken.</p>
<p>Instead, we propose that this can be opt-in: a lambda is allowed to be declared <code class="sourceCode cpp"><span class="kw">static</span></code>, which will then cause the call operator (or call operator template) of the lambda to be a static member function rather than a non-static member function:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1"></a><span class="kw">auto</span> four <span class="op">=</span> <span class="op">[]()</span> <span class="kw">static</span> <span class="op">{</span> <span class="cf">return</span> <span class="dv">4</span>; <span class="op">}</span>;</span></code></pre></div>
<p>We then also need to ensure that a lambda cannot be declared <code class="sourceCode cpp"><span class="kw">static</span></code> if it is declared <code class="sourceCode cpp"><span class="kw">mutable</span></code> (an inherently non-static property) or has any capture (as that would be fairly pointless, since you could not access any of that capture).</p>
<h2 data-number="3.3" id="deduction-guides"><span class="header-section-number">3.3</span> Deduction Guides<a href="#deduction-guides" class="self-link"></a></h2>
<p>Consider the following, assuming a version of <code class="sourceCode cpp">less</code> that uses a static call operator:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-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"></a><span class="kw">struct</span> less <span class="op">{</span></span>
<span id="cb9-3"><a href="#cb9-3"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">()(</span>T <span class="kw">const</span><span class="op">&amp;</span> x, T <span class="kw">const</span><span class="op">&amp;</span> y<span class="op">)</span> <span class="op">-&gt;</span> <span class="dt">bool</span> <span class="op">{</span></span>
<span id="cb9-4"><a href="#cb9-4"></a>        <span class="cf">return</span> x <span class="op">&lt;</span> y;</span>
<span id="cb9-5"><a href="#cb9-5"></a>    <span class="op">}</span>;</span>
<span id="cb9-6"><a href="#cb9-6"></a><span class="op">}</span>;</span>
<span id="cb9-7"><a href="#cb9-7"></a></span>
<span id="cb9-8"><a href="#cb9-8"></a>std<span class="op">::</span>function f <span class="op">=</span> less<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;{}</span>;</span></code></pre></div>
<p>This will not compile with this change, because <code class="sourceCode cpp">std<span class="op">::</span>function</code>’s deduction guides only work with either function pointers (which does not apply) or class types whose call operator is a non-static member function. These will need to be extended to support call operators with function type (as they would for <span class="citation" data-cites="P0847R6">[<a href="#ref-P0847R6" role="doc-biblioref">P0847R6</a>]</span> anyway).</p>
<h2 data-number="3.4" id="prior-references"><span class="header-section-number">3.4</span> Prior References<a href="#prior-references" class="self-link"></a></h2>
<p>This idea was previously referenced in <span class="citation" data-cites="EWG88">[<a href="#ref-EWG88" role="doc-biblioref">EWG88</a>]</span>, which reads:</p>
<div class="quote">
<p>In c++std-core-14770, Dos Reis suggests that <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">[]</span></code> and <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code> should both be allowed to be static. In addition to that, he suggests that both should allow multiple parameters. It’s well known that there’s a possibility that this breaks existing code (<code class="sourceCode cpp">foo<span class="op">[</span><span class="dv">1</span>,<span class="dv">2</span><span class="op">]</span></code> is valid, the thing in brackets is a comma-expression) but there are possibilities to fix such cases (by requiring parens if a comma-expression is desired). EWG should discuss whether such unification is to be strived for.</p>
<p>Discussed in Rapperswil 2014. EWG points out that there are more issues to consider here, in terms of other operators, motivations, connections with captureless lambdas, who knows what else, so an analysis paper is requested.</p>
</div>
<p>There is a separate paper proposing multi-argument subscripting <span class="citation" data-cites="P2128R3">[<a href="#ref-P2128R3" role="doc-biblioref">P2128R3</a>]</span> already, with preexisting code such as <code class="sourceCode cpp">foo<span class="op">[</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">]</span></code> already having been deprecated.</p>
<h2 data-number="3.5" id="implementation-experience"><span class="header-section-number">3.5</span> Implementation Experience<a href="#implementation-experience" class="self-link"></a></h2>
<p>The language changes have been implemented in EDG.</p>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="wording"><span class="header-section-number">4</span> Wording<a href="#wording" class="self-link"></a></h1>
<h2 data-number="4.1" id="language-wording"><span class="header-section-number">4.1</span> Language Wording<a href="#language-wording" class="self-link"></a></h2>
<p>Change <span>7.5.5.1
 <a href="https://wg21.link/expr.prim.lambda.general">[expr.prim.lambda.general]</a></span>/3:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span> In the <em>decl-specifier-seq</em> of the <em>lambda-declarator</em>, each <em>decl-specifier</em> shall be one of <code class="sourceCode cpp"><span class="kw">mutable</span></code>, <span class="addu"><code class="sourceCode cpp"><span class="kw">static</span></code>,</span> <code class="sourceCode cpp"><span class="kw">constexpr</span></code>, or <code class="sourceCode cpp"><span class="kw">consteval</span></code>. <span class="addu">The <em>decl-specifier-seq</em> shall not contain both <code class="sourceCode cpp"><span class="kw">mutable</span></code> and <code class="sourceCode cpp"><span class="kw">static</span></code>. If the <em>decl-specifier-seq</em> contains <code class="sourceCode cpp"><span class="kw">static</span></code>, there shall be no <em>lambda-capture</em>.</span></p>
</blockquote>
<p>Change <span>7.5.5.2
 <a href="https://wg21.link/expr.prim.lambda.closure">[expr.prim.lambda.closure]</a></span>/4:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span> The function call operator or operator template is <span class="addu">a static member function or static member function template ([class.static.mfct]) if the <em>lambda-expression</em>’s <em>parameter-declaration-clause</em> is followed by <code class="sourceCode cpp"><span class="kw">static</span></code>. Otherwise, it is a non-static member function or member function template ([class.mfct.non-static]) that is</span> declared <code class="sourceCode cpp"><span class="kw">const</span></code> ([class.mfct.non-static]) if and only if the <em>lambda-expression</em>’s <em>parameter-declaration-clause</em> is not followed by <code class="sourceCode cpp"><span class="kw">mutable</span></code>. It is neither virtual nor declared <code class="sourceCode cpp"><span class="kw">volatile</span></code>. Any <em>noexcept-specifier</em> specified on a <em>lambda-expression</em> applies to the corresponding function call operator or operator template. An <em>attribute-specifier-seq</em> in a <em>lambda-declarator</em> appertains to the type of the corresponding function call operator or operator template. The function call operator or any given operator template specialization is a <code class="sourceCode cpp"><span class="kw">constexpr</span></code> function if either the corresponding <em>lambda-expression</em>’s <em>parameter-declaration-clause</em> is followed by <code class="sourceCode cpp"><span class="kw">constexpr</span></code>, or it satisfies the requirements for a <code class="sourceCode cpp"><span class="kw">constexpr</span></code> function.</p>
</blockquote>
<p>Add a note to <span>7.5.5.2
 <a href="https://wg21.link/expr.prim.lambda.closure">[expr.prim.lambda.closure]</a></span>/7 and /10 indicating that we could just return the call operator. The wording as-is specifies the behavior of the return here, and returning the call operator already would be allowed, so no wording change is necessary. But the note would be helpful:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span> The closure type for a non-generic <em>lambda-expression</em> with no <em>lambda-capture</em> whose constraints (if any) are satisfied has a conversion function to pointer to function with C++ language linkage having the same parameter and return types as the closure type’s function call operator. The conversion is to “pointer to <code class="sourceCode cpp"><span class="kw">noexcept</span></code> function” if the function call operator has a non-throwing exception specification. The value returned by this conversion function is the address of a function <code class="sourceCode cpp">F</code> that, when invoked, has the same effect as invoking the closure type’s function call operator on a default-constructed instance of the closure type. <code class="sourceCode cpp">F</code> is a constexpr function if the function call operator is a constexpr function and is an immediate function if the function call operator is an immediate function. <span class="addu">[<em>Note</em>: if the function call operator is a static member function, the conversion function may return the address of the function call operator. -<em>end note</em>]</span></p>
<p><span class="marginalizedparent"><a class="marginalized">10</a></span> The value returned by any given specialization of this conversion function template is the address of a function <code class="sourceCode cpp">F</code> that, when invoked, has the same effect as invoking the generic lambda’s corresponding function call operator template specialization on a default-constructed instance of the closure type. F is a constexpr function if the corresponding specialization is a constexpr function and F is an immediate function if the function call operator template specialization is an immediate function. <span class="addu">[<em>Note</em>: if the function call operator template is a static member function template, the conversion function may return the address of a specialization of the function call operator template. -<em>end note</em>]</span></p>
</blockquote>
<p>Change <span>12.2.4.1
 <a href="https://wg21.link/over.match.best.general">[over.match.best.general]</a></span>/1 to drop the static member exception and remove the bullets and the footnote:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span> Define ICS<sup>i</sup>(<code class="sourceCode cpp">F</code>) as <span class="rm" style="color: #bf0303"><del>follows:</del></span></p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(1.1)</a></span> <span class="rm" style="color: #bf0303"><del>If <span><code class="sourceCode default">F</code></span> is a static member function, ICS<sup>1</sup>(<span><code class="sourceCode default">F</code></span>) is defined such that ICS<sup>1</sup>(<span><code class="sourceCode default">F</code></span>) is neither better nor worse than ICS<sup>1</sup>(<span><code class="sourceCode default">G</code></span>) for any function <span><code class="sourceCode default">G</code></span>, and, symmetrically, ICS<sup>1</sup>(<span><code class="sourceCode default">G</code></span>) is neither better nor worse than ICS<sup>1</sup>(<span><code class="sourceCode default">F</code></span>);<sup>117</sup> otherwise,</del></span></li>
<li><span class="marginalizedparent"><a class="marginalized">(1.2)</a></span> <span class="rm" style="color: #bf0303"><del>let ICS<sup>i</sup>(<span><code class="sourceCode default">F</code></span>) denote</del></span> the implicit conversion sequence that converts the i<sup>th</sup> argument in the list to the type of the i<sup>th</sup> parameter of viable function <code class="sourceCode cpp">F</code>. [over.best.ics] defines the implicit conversion sequences and [over.ics.rank] defines what it means for one implicit conversion sequence to be a better conversion sequence or worse conversion sequence than another.</li>
</ul>
</blockquote>
<p>Add to <span>12.2.4.2.1
 <a href="https://wg21.link/over.best.ics.general">[over.best.ics.general]</a></span> a way to compare this static member function case:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">*</a></span> <span class="addu">When the parameter is the implicit object parameter of a static member function, the implicit conversion sequence is a standard conversion sequence that is neither better nor worse than any other standard conversion sequence.</span></p>
</blockquote>
<p>Change <span>12.4
 <a href="https://wg21.link/over.oper">[over.oper]</a></span> paragraph 6 and introduce bullets to clarify the parsing. <code class="sourceCode cpp"><span class="kw">static</span> <span class="dt">void</span> <span class="kw">operator</span><span class="op">()()</span> <span class="op">{</span> <span class="op">}</span></code> is a valid function call operator that has no parameters with this proposal, so needs to be clear that the “has at least one parameter” part refers to the non-member function part of the clause.</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span> An operator function shall either</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(6.1)</a></span> be a <span class="rm" style="color: #bf0303"><del>non-static</del></span> member function or</li>
<li><span class="marginalizedparent"><a class="marginalized">(6.2)</a></span> be a non-member function that has at least one parameter whose type is a class, a reference to a class, an enumeration, or a reference to an enumeration.</li>
</ul>
<p>It is not possible to change the precedence, grouping, or number of operands of operators. The meaning of the operators <code class="sourceCode cpp"><span class="op">=</span></code>, (unary) <code class="sourceCode cpp"><span class="op">&amp;</span></code>, and <code class="sourceCode cpp">,</code> (comma), predefined for each type, can be changed for specific class and enumeration types by defining operator functions that implement these operators. Operator functions are inherited in the same manner as other base class functions.</p>
</blockquote>
<p>Change <span>12.4.4
 <a href="https://wg21.link/over.call">[over.call]</a></span> paragraph 1:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span> A <em>function call operator function</em> is a function named <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code> that is a <span class="rm" style="color: #bf0303"><del>non-static</del></span> member function with an arbitrary number of parameters.</p>
</blockquote>
<h2 data-number="4.2" id="library-wording"><span class="header-section-number">4.2</span> Library Wording<a href="#library-wording" class="self-link"></a></h2>
<p>Change the deduction guide for <code class="sourceCode cpp">function</code> in <span>20.14.17.3.2
 <a href="https://wg21.link/func.wrap.func.con">[func.wrap.func.con]</a></span>/14-15:</p>
<blockquote>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> F<span class="op">&gt;</span> function<span class="op">(</span>F<span class="op">)</span> <span class="op">-&gt;</span> function<span class="op">&lt;</span><em>see below</em><span class="op">&gt;</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">14</a></span> <em>Constraints</em>: <code class="sourceCode cpp"><span class="op">&amp;</span>F​<span class="op">::</span>​<span class="kw">operator</span><span class="op">()</span></code> is well-formed when treated as an unevaluated operand and <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span>​<span class="op">&amp;</span>F​<span class="op">::</span>​<span class="kw">operator</span><span class="op">())</span></code> is <span class="addu">either</span> of the form <code class="sourceCode cpp">R<span class="op">(</span>G​<span class="op">::</span>​<span class="op">*)(</span>A<span class="op">...)</span> cv <span class="op">&amp;</span><sub>opt</sub> noexcept<sub>opt</sub></code> for a class type <code class="sourceCode cpp">G</code> <span class="addu">or of the form <code class="sourceCode cpp">R<span class="op">(*)(</span>A<span class="op">...)</span> noexcept<sub>opt</sub></code></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized">15</a></span> <em>Remarks</em>: The deduced type is <code class="sourceCode cpp">function<span class="op">&lt;</span>R<span class="op">(</span>A<span class="op">...)&gt;</span></code>.</p>
</blockquote>
<p>Change the deduction guide for <code class="sourceCode cpp">packaged_task</code> in <span>32.9.10.2
 <a href="https://wg21.link/futures.task.members">[futures.task.members]</a></span>/7-8 in the same way (it’s nearly the same wording today):</p>
<blockquote>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> F<span class="op">&gt;</span> packaged_task<span class="op">(</span>F<span class="op">)</span> <span class="op">-&gt;</span> packaged_task<span class="op">&lt;</span><em>see below</em><span class="op">&gt;</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span> <em>Constraints</em>: <code class="sourceCode cpp"><span class="op">&amp;</span>F​<span class="op">::</span>​<span class="kw">operator</span><span class="op">()</span></code> is well-formed when treated as an unevaluated operand and <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span>​<span class="op">&amp;</span>F​<span class="op">::</span>​<span class="kw">operator</span><span class="op">())</span></code> is <span class="addu">either</span> of the form <code class="sourceCode cpp">R<span class="op">(</span>G​<span class="op">::</span>​<span class="op">*)(</span>A<span class="op">...)</span> cv <span class="op">&amp;</span><sub>opt</sub> noexcept<sub>opt</sub></code> for a class type <code class="sourceCode cpp">G</code> <span class="addu">or of the form <code class="sourceCode cpp">R<span class="op">(*)(</span>A<span class="op">...)</span> noexcept<sub>opt</sub></code></span>.</p>
<p><span class="marginalizedparent"><a class="marginalized">8</a></span> <em>Remarks</em>: The deduced type is <code class="sourceCode cpp">packaged_task<span class="op">&lt;</span>R<span class="op">(</span>A<span class="op">...)&gt;</span></code>.</p>
</blockquote>
<h1 data-number="5" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">5</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references hanging-indent" role="doc-bibliography">
<div id="ref-EWG88">
<p>[EWG88] Gabriel Dos Reis. [tiny] Uniform handling of operator[] and operator(). <br />
<a href="https://wg21.link/ewg88">https://wg21.link/ewg88</a></p>
</div>
<div id="ref-P0847R6">
<p>[P0847R6] Barry Revzin, Gašper Ažman, Sy Brand, Ben Deane. 2021-01-15. Deducing this. <br />
<a href="https://wg21.link/p0847r6">https://wg21.link/p0847r6</a></p>
</div>
<div id="ref-P1169R0">
<p>[P1169R0] Barry Revzin, Casey Carter. 2018-10-07. static operator(). <br />
<a href="https://wg21.link/p1169r0">https://wg21.link/p1169r0</a></p>
</div>
<div id="ref-P2128R3">
<p>[P2128R3] Corentin Jabot, Isabella Muerte, Daisy Hollman, Christian Trott, Mark Hoemmen. 2021-02-15. Multidimensional subscript operator. <br />
<a href="https://wg21.link/p2128r3">https://wg21.link/p2128r3</a></p>
</div>
</div>
</div>
</div>
</body>
</html>
