<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>make_function_ref_more_functional</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      overflow-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
      overflow-wrap: normal;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    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; }
    .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
      {   }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<style type="text/css">
ins { background-color: #CCFFCC }
s { background-color: #FFCACA }
blockquote { color: inherit !important }
</style>
<table>
<tr>
<td>
Document number
</td>
<td>
P2472R2
</td>
</tr>
<tr>
<td>
Date
</td>
<td>
2022-03-08
</td>
</tr>
<tr>
<td>
Reply-to
</td>
<td>
<p>Jarrad J. Waterloo &lt;<descender76 at gmail dot com>&gt;</p>
<p>Zhihao Yuan &lt;<zy at miator dot net>&gt;</p>
</td>
</tr>
<tr>
<td>
Audience
</td>
<td>
Library Evolution Working Group (LEWG)
</td>
</tr>
</table>
<h1 id="make-function_ref-more-functional">make <code>function_ref</code> more functional</h1>
<style>
.inline-link
{
    font-size: small;
    margin-top: -2.8em;
    margin-right: 4px;
    text-align: right;
    font-weight: bold;
}

code
{
    font-family: "Fira Code", monospace !important;
    font-size: 0.87em;
}

.sourceCode
{
    font-size: 0.95em;
}

a code
{
    color: #0645ad;
}
</style>
<h2 id="table-of-contents">Table of contents</h2>
<ul>
<li><a href="#make-functionref-more-functional">make <code>function_ref</code> more functional</a>
<ul>
<li><a href="#changelog">Changelog</a></li>
<li><a href="#abstract">Abstract</a></li>
<li><a href="#motivating-examples">Motivating examples</a></li>
<li><a href="#wording">Wording</a></li>
<li><a href="#feature-test-macro">Feature test macro</a></li>
<li><a href="#other-languages">Other languages</a></li>
<li><a href="#example-implementation">Example implementation</a></li>
<li><a href="#acknowledgments">Acknowledgments</a></li>
<li><a href="#references">References</a></li>
</ul></li>
</ul>
<h2 id="changelog">Changelog</h2>
<h3 id="r1">R1</h3>
<ul>
<li>Moved from my make_function_ref implementation to Zhihao Yuan’s nontype implementation
<ul>
<li>Constructors were always my ideal over factory function but I was unable to make it work.</li>
<li>nontype has better type deduction</li>
<li>Most of the changes were syntactical and reasoning based on feedback as well as making examples even more concise</li>
</ul></li>
</ul>
<h3 id="r2">R2</h3>
<ul>
<li>Added this changelog</li>
<li>Transformed solution into the wording</li>
<li>Added a third constructor which takes a pointer instead of a reference for convenience</li>
<li>Revised example from cat to rule/test</li>
<li>Added deduction guide</li>
</ul>
<h2 id="abstract">Abstract</h2>
<p>This document proposes adding additional constructors to <code>function_ref</code> <a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> in order to make it easier to use, more efficient, and safer to use with common use cases.</p>
<p>Currently, a <code>function_ref</code>, can be constructed from a lambda/functor, a free function pointer, and a member function pointer. While the lambda/functor use case does support type erasing <code>this</code> pointer, its free/member function pointer constructors do <strong>not</strong> allow type erasing any arguments, even though these two use cases are common.</p>
<table>
<tr>
<td colspan="3">
<p><code>function_ref</code></p>
</td>
</tr>
<tr>
<td>
</td>
<td>
Stateless
</td>
<td>
Stateful
</td>
</tr>
<tr>
<td>
Lambda/Functor
</td>
<td>
🗸
</td>
<td>
🗸
</td>
</tr>
<tr>
<td>
Free Function
</td>
<td>
🗸
</td>
<td>
✗
</td>
</tr>
<tr>
<td>
Member Function
</td>
<td>
🗸
</td>
<td>
✗
</td>
</tr>
</table>
<h2 id="motivating-examples">Motivating Examples</h2>
<h3 id="given">Given</h3>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> rule <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> when<span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="co">// rule could just as easily be test which also have when and then functions</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> then<span class="op">(</span>rule<span class="op">&amp;</span> r<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> rule_when<span class="op">(</span>rule<span class="op">&amp;</span> r<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    r<span class="op">.</span>when<span class="op">();</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> callback <span class="op">{</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    rule<span class="op">*</span> r<span class="op">;</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="op">(*</span>f<span class="op">)(</span>rule<span class="op">&amp;);</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a>rule localTaxRule<span class="op">;</span></span></code></pre></div>
<h4 id="memberfree-function-with-type-erasure">member/free function with type erasure</h4>
<p>Since typed erased free and member functions are not currently supported, the current <code>function_ref</code> proposal forces users to create an unnecessary temporary functor, likely with <code>std::bind_front</code> or a stateful/capturing lambda that the developer hopes the optimizer to elide.</p>
<h5 id="member-function-with-type-erasure">member function with type erasure</h5>
<table>
<tr>
<td>
C/C++ core language
</td>
<td>
<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>callback cb <span class="op">=</span> <span class="op">{&amp;</span>localTaxRule<span class="op">,</span> <span class="op">[](</span>rule<span class="op">&amp;</span> r<span class="op">){</span>r<span class="op">.</span>when<span class="op">();}};</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="co">// or</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>callback cb <span class="op">=</span> <span class="op">{&amp;</span>localTaxRule<span class="op">,</span> rule_when<span class="op">};</span></span></code></pre></div>
</td>
</tr>
<tr>
<td>
function_ref
</td>
<td>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">// separate temp to prevent dangling</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="co">// when temp is passed to multiple arguments</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> temp <span class="op">=</span> <span class="op">[&amp;</span>localTaxRule<span class="op">](){</span>localTaxRule<span class="op">.</span>when<span class="op">();};</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>function_ref<span class="op">&lt;</span><span class="dt">void</span><span class="op">()&gt;</span> fr <span class="op">=</span> temp<span class="op">;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="co">// or when given directly as a function argument</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>some_function<span class="op">([&amp;</span>localTaxRule<span class="op">](){</span>localTaxRule<span class="op">.</span>when<span class="op">();});</span></span></code></pre></div>
</td>
</tr>
<tr>
<td>
proposed
</td>
<td>
<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>function_ref<span class="op">&lt;</span><span class="dt">void</span><span class="op">()&gt;</span> fr <span class="op">=</span> <span class="op">{</span>nontype<span class="op">&lt;&amp;</span>rule<span class="op">::</span>when<span class="op">&gt;,</span> localTaxRule<span class="op">};</span></span></code></pre></div>
</td>
</tr>
</table>
<h5 id="free-function-with-type-erasure">free function with type erasure</h5>
<table>
<tr>
<td>
C/C++ core language
</td>
<td>
<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>callback cb <span class="op">=</span> <span class="op">{&amp;</span>localTaxRule<span class="op">,</span> <span class="op">[](</span>rule<span class="op">&amp;</span> r<span class="op">){</span>then<span class="op">(</span>r<span class="op">);}};</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="co">// or</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>callback cb <span class="op">=</span> <span class="op">{&amp;</span>localTaxRule<span class="op">,</span> then<span class="op">};</span></span></code></pre></div>
</td>
</tr>
<tr>
<td>
function_ref
</td>
<td>
<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="co">// separate temp to prevent dangling</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="co">// when temp is passed to multiple arguments</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> temp <span class="op">=</span> <span class="op">[&amp;</span>localTaxRule<span class="op">](){</span>then<span class="op">(</span>localTaxRule<span class="op">);};</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>function_ref<span class="op">&lt;</span><span class="dt">void</span><span class="op">()&gt;</span> fr <span class="op">=</span> temp<span class="op">;</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="co">// or when given directly as a function argument</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>some_function<span class="op">([&amp;</span>localTaxRule<span class="op">](){</span>then<span class="op">(</span>localTaxRule<span class="op">);});</span></span></code></pre></div>
</td>
</tr>
<tr>
<td>
proposed
</td>
<td>
<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>function_ref<span class="op">&lt;</span><span class="dt">void</span><span class="op">()&gt;</span> fr <span class="op">=</span> <span class="op">{</span>nontype<span class="op">&lt;</span>then<span class="op">&gt;,</span> localTaxRule<span class="op">}</span></span></code></pre></div>
</td>
</tr>
</table>
<p>This has numerous disadvantages compared to what the C++ core language can do. It is inefficient, hard to use, and unsafe to use.</p>
<h5 id="not-easy-to-use">Not easy to use</h5>
<ul>
<li>Unlike the direct initialization of the C/C++ core language example, the initialization of <code>function_ref</code> is bifurcated by passing it directly as a function argument or using 2-step initialization by first creating a named temporary. Direct initializing a variable of <code>function_ref</code> is needed if the same object serves as multiple arguments on either the same but more likely different functions. However, this leads to immediate dangling, which must introduce an extra line of code. Furthermore, getting in the habit of only passing <code>function_ref</code> as an argument to a function results in users duplicating lambdas when needed to be used more than once, again needless increasing the code volume. Initialization is consistently safe in both the C/C++ core language and the proposed revision, regardless of whether <code>function_ref</code> appears as a variable.</li>
</ul>
<h5 id="why-should-a-stateful-lambda-even-be-needed-when-the-signature-is-compatible">Why should a stateful lambda even be needed when the signature is compatible?</h5>
<ul>
<li>The C/C++ core language example works with a “stateless” lambda. A new anonymous type is created with states when requiring a “stateful” lambda. That state’s lifetime also needs to be managed by the user.</li>
<li>When using a lambda, the user must manually forward the function arguments. However, in the C/C++ core language example, the syntax is straightforward when the function exists. We simply pass a function pointer to the callback struct.</li>
</ul>
<h5 id="inefficient">Inefficient</h5>
<ul>
<li>By requiring a “stateful” lambda, a new type is created with a lifetime that must be managed. <code>function_ref</code> is a reference to a “stateful” lambda which also is a reference. Even if the optimizer can remove the cost, the user is still left with the burden in the code.</li>
<li>In the proposed, <code>nontype</code> does not take a pointer but rather a member function pointer initialization statement thus giving the compiler more information to resolve the function selection at compile time rather than runtime, granted it is more likely with free functions instead of member functions.</li>
</ul>
<h5 id="unsafe">Unsafe</h5>
<ul>
<li>Direct initialization of <code>function_ref</code> outside of a function argument immediately dangles. Some would say that this is no different than other standardized types such as <code>string_view</code>. However, this is not true.
<table>
<tr>
<td>
C/C++ core language
</td>
<td>
<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="bu">std::</span>string_view<span class="op"> </span>sv <span class="op">=</span> <span class="st">&quot;hello world&quot;</span><span class="bu">s</span><span class="op">;</span><span class="co">// immediately dangling</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> c <span class="op">=</span> <span class="st">&quot;hello world&quot;</span><span class="bu">s</span><span class="op">;</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="bu">std::</span>string_view<span class="op"> </span>sv <span class="op">=</span> c<span class="op">;</span><span class="co">// DOES NOT DANGLE</span></span></code></pre></div>
</td>
</tr>
<tr>
<td>
function_ref
</td>
<td>
<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>function_ref<span class="op">&lt;</span><span class="dt">void</span><span class="op">()&gt;</span> fr <span class="op">=</span> <span class="op">[&amp;</span>localTaxRule<span class="op">](){</span>localTaxRule<span class="op">.</span>when<span class="op">();};</span><span class="co">// immediately dangling</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="co">// or</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>function_ref<span class="op">&lt;</span><span class="dt">void</span><span class="op">()&gt;</span> fr <span class="op">=</span> <span class="op">[&amp;</span>localTaxRule<span class="op">](){</span>then<span class="op">(</span>localTaxRule<span class="op">);};</span><span class="co">// immediately dangling</span></span></code></pre></div>
</td>
</tr>
<tr>
<td>
proposed
</td>
<td>
<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>function_ref<span class="op">&lt;</span><span class="dt">void</span><span class="op">()&gt;</span> fr <span class="op">=</span> <span class="op">{</span>nontype<span class="op">&lt;&amp;</span>rule<span class="op">::</span>when<span class="op">&gt;,</span> localTaxRule<span class="op">};</span><span class="co">// DOES NOT DANGLE</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="co">// or</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>function_ref<span class="op">&lt;</span><span class="dt">void</span><span class="op">()&gt;</span> fr <span class="op">=</span> <span class="op">{</span>nontype<span class="op">&lt;</span>then<span class="op">&gt;,</span> localTaxRule<span class="op">}</span><span class="co">// DOES NOT DANGLE</span></span></code></pre></div>
</td>
</tr>
</table>
While both the original <code>function_ref</code> proposal and the proposed addendum perform the same desired task, the former dangles and the later doesn’t. It is clear from the immediately dangling <code>string_view</code> example that it dangles because <code>sv</code> is a reference and <code>""s</code> is a temporary. However, it is less clear in the original <code>function_ref</code> example. While it is true and clear that <code>fr</code> is a reference and the stateful lambda is a temporary. It is not what the user of <code>function_ref</code> is intending or wanting to express. <code>localTaxRule</code> is the state that the user wants to type erase and <code>function_ref</code> would not dangle if <code>localTaxRule</code> was the state since it is not a temporary and has already been constructed higher up in the call stack. Further, the member function <code>when</code> or the free function <code>then</code> should not dangle since functions are stateless and also global. So member/free function with type erasure use cases are more like <code>string_view</code> when the referenced object is safely constructed.</li>
</ul>
<table>
<thead>
<tr class="header">
<th></th>
<th>easier to use</th>
<th>more efficient</th>
<th>safer to use</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>C/C++ core language</strong></td>
<td>🗸</td>
<td>🗸</td>
<td>🗸</td>
</tr>
<tr class="even">
<td><strong>function_ref</strong></td>
<td>✗</td>
<td>✗</td>
<td>✗</td>
</tr>
<tr class="odd">
<td><strong>proposed</strong></td>
<td>🗸</td>
<td>🗸</td>
<td>🗸</td>
</tr>
</tbody>
</table>
<p>What is more, member/free functions with type erasure are common use cases! “Member functions with type erasure” is used by delegates/events in object oriented programming and “free functions with type erasure” are common with callbacks in procedural/functional programming.</p>
<h4 id="member-function-without-type-erasure">member function without type erasure</h4>
<p>The fact that users do not expect “stateless” things to dangle becomes even more apparent with the member function without type erasure use case.</p>
<table>
<tr>
<td>
C/C++ core language
</td>
<td>
<pre><code>void (rule::*mf)() = &amp;rule::when;</code></pre>
</td>
</tr>
<tr>
<td>
function_ref
</td>
<td>
<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="co">// separate temp needed to prevent dangling</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="co">// when temp is passed to multiple arguments</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> temp <span class="op">=</span> <span class="op">&amp;</span>rule<span class="op">::</span>when<span class="op">;</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>function_ref<span class="op">&lt;</span><span class="dt">void</span><span class="op">(</span>rule<span class="op">&amp;)&gt;</span> fr <span class="op">=</span> temp<span class="op">;</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="co">// or when given directly as a function argument</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>some_function<span class="op">(&amp;</span>rule<span class="op">::</span>when<span class="op">);</span></span></code></pre></div>
</td>
</tr>
<tr>
<td>
proposed
</td>
<td>
<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>function_ref<span class="op">&lt;</span><span class="dt">void</span><span class="op">(</span>rule<span class="op">&amp;)&gt;</span> fr <span class="op">=</span> <span class="op">{</span>nontype<span class="op">&lt;&amp;</span>rule<span class="op">::</span>when<span class="op">&gt;};</span></span></code></pre></div>
</td>
</tr>
</table>
<p>Current <code>function_ref</code> implementations store a reference to the member function pointer as the state inside <code>function_ref</code>. A trampoline function is required regardless. However, the user <strong>expected</strong> behavior is for <code>function_ref</code> referenced state to be unused/<code>nullptr</code>, as <strong>all</strong> of the arguments must be forwarded since <strong>none</strong> are being type erased. Such dangling is <strong>never</strong> expected, yet the current <code>function_ref</code> proposal/implementation does. Similarly, this use case suffers, just as the previous two did, with respect to ease of use, efficiency, and safety due to the superfluous lambda/functor and two-step initialization.</p>
<table>
<thead>
<tr class="header">
<th></th>
<th>easier to use</th>
<th>more efficient</th>
<th>safer to use</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>C/C++ core language</strong></td>
<td>🗸</td>
<td>🗸</td>
<td>🗸</td>
</tr>
<tr class="even">
<td><strong>function_ref</strong></td>
<td>✗</td>
<td>✗</td>
<td>✗</td>
</tr>
<tr class="odd">
<td><strong>proposed</strong></td>
<td>🗸</td>
<td>🗸</td>
<td>🗸</td>
</tr>
</tbody>
</table>
<h4 id="free-function-without-type-erasure">free function without type erasure</h4>
<p>The C/C++ core language, <code>function_ref</code>, and the proposed examples are approximately equal concerning ease of use, efficiency, and safety for the free function without type erasure use case. While the proposed <code>nontype</code> example is slightly wordier because of the template <code>nontype</code>, it is more consistent with the other three use cases, making it more teachable and usable since the user does not need to choose between bifurcation practices. Also, the expectation of unused state and the function being selected at compile time still applies here, as it does for member function without type erasure use case.</p>
<table>
<tr>
<td>
C/C++ core language
</td>
<td>
<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="dt">void</span> <span class="op">(*</span>f<span class="op">)(</span>rule<span class="op">&amp;)</span> <span class="op">=</span> then<span class="op">;</span></span></code></pre></div>
</td>
</tr>
<tr>
<td>
function_ref
</td>
<td>
<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>function_ref<span class="op">&lt;</span><span class="dt">void</span><span class="op">(</span>rule<span class="op">&amp;)&gt;</span> fr <span class="op">=</span> then<span class="op">;</span></span></code></pre></div>
</td>
</tr>
<tr>
<td>
proposed
</td>
<td>
<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>function_ref<span class="op">&lt;</span><span class="dt">void</span><span class="op">(</span>rule<span class="op">&amp;)&gt;</span> fr <span class="op">=</span> <span class="op">{</span>nontype<span class="op">&lt;</span>then<span class="op">&gt;};</span></span></code></pre></div>
</td>
</tr>
</table>
<table>
<thead>
<tr class="header">
<th></th>
<th>easier to use</th>
<th>more efficient</th>
<th>safer to use</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>C/C++ core language</strong></td>
<td>🗸</td>
<td>🗸</td>
<td>🗸</td>
</tr>
<tr class="even">
<td><strong>function_ref</strong></td>
<td>🗸</td>
<td>🗸</td>
<td>🗸</td>
</tr>
<tr class="odd">
<td><strong>proposed</strong></td>
<td>🗸</td>
<td>🗸</td>
<td>🗸</td>
</tr>
</tbody>
</table>
<h4 id="remove-existing-free-function-constructor">Remove existing free function constructor?</h4>
<p>Should the existing free function constructor be removed with the overlap in functionality with the free function without type erasure use case? NO. Initializing a <code>function_ref</code> from a function pointer instead of a non-type function pointer template argument is still usable in the most runtime of libraries, such as dynamically loaded libraries where function pointers are looked up. However, it is not necessarily the general case where users work with declarations found in header files and modules.</p>
<h2 id="wording">Wording</h2>
<p>The wording is relative to P0792R8.</p>
<p>Add new templates to 20.2.1 [utility.syn], header <code>&lt;utility&gt;</code> synopsis after <code>in_place_index_t</code> and <code>in_place_index</code>:</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> std <span class="op">{</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>  <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="co">// nontype argument tag</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span> V<span class="op">&gt;</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> <span class="dt">nontype_t</span> <span class="op">{</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>      <span class="kw">explicit</span> <span class="dt">nontype_t</span><span class="op">()</span> <span class="op">=</span> <span class="cf">default</span><span class="op">;</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>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span> V<span class="op">&gt;</span> <span class="kw">inline</span> <span class="kw">constexpr</span> <span class="dt">nontype_t</span><span class="op">&lt;</span>V<span class="op">&gt;</span> nontype<span class="op">{};</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Add a definition to 20.14.3 [func.def]:</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><span class="kw">auto</span> f<span class="op">&gt;</span> <span class="kw">constexpr</span> function_ref<span class="op">(</span><span class="dt">nontype_t</span><span class="op">&lt;</span>f<span class="op">&gt;)</span> <span class="kw">noexcept</span><span class="op">;</span></span></code></pre></div>
<blockquote>
<p><em>Constraints:</em> <code>is-invocable-using&lt;decltype(f)&gt;</code> is <code>true</code>.</p>
<p><em>Effects:</em> Initializes <code>bound-entity</code> with <code>nullptr</code>, and <code>thunk-ptr</code> to address of a function such that <code>thunk-ptr(bound-entity, call-args...)</code> is expression equivalent to <code>invoke_r&lt;R&gt;(f, nullptr, call-args...)</code>.</p>
</blockquote>
<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">template</span><span class="op">&lt;</span><span class="kw">auto</span> f<span class="op">,</span> <span class="kw">class</span> T<span class="op">&gt;</span> function_ref<span class="op">(</span><span class="dt">nontype_t</span><span class="op">&lt;</span>f<span class="op">&gt;,</span> T<span class="op">&amp;</span> state<span class="op">)</span> <span class="kw">noexcept</span><span class="op">;</span></span></code></pre></div>
<blockquote>
<p><em>Constraints:</em> <code>is-invocable-using&lt;decltype(f), cv T&amp;&gt;</code> is true.</p>
<p><em>Effects:</em> Initializes <code>bound-entity</code> with <code>addressof(state)</code>, and <code>thunk-ptr</code> to address of a function such that <code>thunk-ptr(bound-entity, call-args...)</code> is expression equivalent to <code>invoke_r&lt;R&gt;(f, static_cast&lt;T cv&amp;&gt;(bound-entity), call-args...)</code>.</p>
</blockquote>
<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">template</span><span class="op">&lt;</span><span class="kw">auto</span> f<span class="op">,</span> <span class="kw">class</span> T<span class="op">&gt;</span> function_ref<span class="op">(</span><span class="dt">nontype_t</span><span class="op">&lt;</span>f<span class="op">&gt;,</span> cv T<span class="op">*</span> state<span class="op">)</span> <span class="kw">noexcept</span><span class="op">;</span></span></code></pre></div>
<blockquote>
<p><em>Constraints:</em> <code>is-invocable-using&lt;decltype(f), cv T*&gt;</code> is <code>true</code>.</p>
<p><em>Effects:</em> Initializes <code>bound-entity</code> with <code>state</code>, and <code>thunk-ptr</code> to address of a function such that <code>thunk-ptr(bound-entity, call-args...)</code> is expression equivalent to <code>invoke_r&lt;R&gt;(f, static_cast&lt;cv T*&gt;(bound-entity), call-args...)</code>.</p>
</blockquote>
<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">template</span><span class="op">&lt;</span><span class="kw">class</span> R<span class="op">,</span> <span class="kw">class</span><span class="op">...</span> ArgTypes<span class="op">&gt;</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> function_ref<span class="op">&lt;</span>R<span class="op">(</span>ArgTypes<span class="op">...)</span> cv ref <span class="kw">noexcept</span><span class="op">(</span>noex<span class="op">)&gt;</span> <span class="op">{</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">public</span><span class="op">:</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">// [func.wrap.ref.ctor], constructors ...</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">...</span></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span> f<span class="op">&gt;</span> <span class="kw">constexpr</span> function_ref<span class="op">(</span><span class="dt">nontype_t</span><span class="op">&lt;</span>f<span class="op">&gt;)</span> <span class="kw">noexcept</span><span class="op">;</span></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span> f<span class="op">,</span> <span class="kw">class</span> T<span class="op">&gt;</span> function_ref<span class="op">(</span><span class="dt">nontype_t</span><span class="op">&lt;</span>f<span class="op">&gt;,</span> T<span class="op">&amp;)</span> <span class="kw">noexcept</span><span class="op">;</span></span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span> f<span class="op">,</span> <span class="kw">class</span> T<span class="op">&gt;</span> function_ref<span class="op">(</span><span class="dt">nontype_t</span><span class="op">&lt;</span>f<span class="op">&gt;,</span> cv T<span class="op">*)</span> <span class="kw">noexcept</span><span class="op">;</span></span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">...</span></span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a>  <span class="op">};</span></span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [func.wrap.ref.deduct], deduction guides</span></span>
<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span> f<span class="op">&gt;</span></span>
<span id="cb21-15"><a href="#cb21-15" aria-hidden="true" tabindex="-1"></a>    function_ref<span class="op">(</span><span class="dt">nontype_t</span><span class="op">&lt;</span>f<span class="op">&gt;)</span> <span class="op">-&gt;</span> function_ref<span class="op">&lt;</span><span class="bu">std::</span>remove_pointer_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>f<span class="op">)&gt;;</span></span>
<span id="cb21-16"><a href="#cb21-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span> f<span class="op">&gt;</span></span>
<span id="cb21-17"><a href="#cb21-17" aria-hidden="true" tabindex="-1"></a>    function_ref<span class="op">(</span><span class="dt">nontype_t</span><span class="op">&lt;</span>f<span class="op">&gt;,</span> <span class="kw">auto</span><span class="op">)</span> <span class="op">-&gt;</span> function_ref<span class="op">&lt;</span>see below<span class="op">&gt;;</span></span>
<span id="cb21-18"><a href="#cb21-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<blockquote>
<p><strong>Deduction guides</strong></p>
<p>[func.wrap.ref.deduct]</p>
</blockquote>
<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">template</span><span class="op">&lt;</span><span class="kw">auto</span> f<span class="op">&gt;</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>  function_ref<span class="op">(</span><span class="dt">nontype_t</span><span class="op">&lt;</span>f<span class="op">&gt;)</span> <span class="op">-&gt;</span> function_ref<span class="op">&lt;</span><span class="bu">std::</span>remove_pointer_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>f<span class="op">)&gt;;</span></span></code></pre></div>
<blockquote>
<p><em>Constraints:</em> <code>is_function_v&lt;f&gt;</code> is <code>true</code>.</p>
</blockquote>
<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">template</span><span class="op">&lt;</span><span class="kw">auto</span> f<span class="op">&gt;</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>  function_ref<span class="op">(</span><span class="dt">nontype_t</span><span class="op">&lt;</span>f<span class="op">&gt;,</span> <span class="kw">auto</span><span class="op">)</span> <span class="op">-&gt;</span> function_ref<span class="op">&lt;</span>see below<span class="op">&gt;;</span></span></code></pre></div>
<blockquote>
<p><em>Constraints:</em> - <code>decltype(f)</code> is of the form <code>R(G::<em>)(A...) <i>cv</i> &amp;<sub><i>opt</i></sub> noexcept(<i>E</i>)</code> for a class type <code>G</code>, or - <code>decltype(f)</code> is of the form <code>R G::</em></code> for a class type <code>G</code>, in which case let <code>A...</code> be an empty pack, or - <code>decltype(f)</code> is of the form <code>R(U, A...) noexcept(<i>E</i>)</code>.</p>
<p><em>Remarks:</em> The deduced type is <code>function_ref&lt;R(A...) noexcept(<i>E</i>)&gt;</code>.</p>
</blockquote>
<h2 id="feature-test-macro">Feature test macro</h2>
<p>We do not need a feature macro, because we intend for this paper to modify <code>std::function_ref</code> before it ships.</p>
<h2 id="other-languages">Other languages</h2>
<p>C# and the .NET family of languages provide this via <code>delegates</code> <a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a>.</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="co">// C#</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>delegate <span class="dt">void</span> some_name<span class="op">();</span></span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>some_name fr <span class="op">=</span> then<span class="op">;</span><span class="co">// the stateless free function use case</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>some_name fr <span class="op">=</span> localTaxRule<span class="op">.</span>when<span class="op">;</span><span class="co">// the stateful member function use case</span></span></code></pre></div>
<p>Borland C++ now embarcadero provides this via <code>__closure</code> <a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a>.</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="co">// Borland C++, embarcadero __closure</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span><span class="op">(</span>__closure <span class="op">*</span> fr<span class="op">)();</span></span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>fr <span class="op">=</span> localTaxRule<span class="op">.</span>when<span class="op">;</span><span class="co">// the stateful member function use case</span></span></code></pre></div>
<p><code>function_ref</code> with <code>nontype</code> constructors handles all four stateless/stateful free/member use cases. It is more feature-rich than those prior arts.</p>
<h2 id="example-implementation">Example implementation</h2>
<p>The most up-to-date implementation, created by Zhihao Yuan, is available on GitHub.<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></p>
<h2 id="acknowledgments">Acknowledgments</h2>
<p>Thanks to Arthur O’Dwyer, Tomasz Kamiński, Corentin Jabot and Zhihao Yuan for providing very valuable feedback on this proposal.</p>
<h2 id="references">References</h2>
<section class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p0792r6.html" class="uri">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p0792r6.html</a><a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p><a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/delegates/using-delegates" class="uri">https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/delegates/using-delegates</a><a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p><a href="http://docwiki.embarcadero.com/RADStudio/Sydney/en/Closure" class="uri">http://docwiki.embarcadero.com/RADStudio/Sydney/en/Closure</a><a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn4" role="doc-endnote"><p><a href="https://github.com/zhihaoy/nontype_functional/blob/main/include/std23/function_ref.h" class="uri">https://github.com/zhihaoy/nontype_functional/blob/main/include/std23/function_ref.h</a><a href="#fnref4" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</body>
</html>
