<!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>
<table>
<tbody>
<tr class="odd">
<td>Document number</td>
<td>P2472R1</td>
</tr>
<tr class="even">
<td>Date</td>
<td>2022-01-31</td>
</tr>
<tr class="odd">
<td>Reply-to</td>
<td>Jarrad J. Waterloo &lt;<a href="mailto:descender76@gmail.com" class="email">descender76@gmail.com</a>&gt;</td>
</tr>
<tr class="even">
<td>Audience</td>
<td>Library Evolution Working Group (LEWG)</td>
</tr>
</tbody>
</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="#abstract">Abstract</a></li>
<li><a href="#motivating-examples">Motivating examples</a></li>
<li><a href="#solution">Solution</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="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 supports type erasing the <code>this</code> pointer, its free/member function pointer constructors does NOT 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> cat <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> walk<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>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> leap<span class="op">(</span>cat<span class="op">&amp;</span> c<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> catwalk<span class="op">(</span>cat<span class="op">&amp;</span> c<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    c<span class="op">.</span>walk<span class="op">();</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> callback <span class="op">{</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    cat<span class="op">*</span> c<span class="op">;</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span> <span class="op">(*</span>f<span class="op">)(</span>cat<span class="op">&amp;);</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a>cat c<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 its users to create a unnecessary temporary functor likely with std::bind_front or a <code>stateful</code>/capturing lambda which the developer hopes the optimizer elides.</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>c<span class="op">,</span> <span class="op">[](</span>cat<span class="op">&amp;</span> c<span class="op">){</span>c<span class="op">.</span>walk<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>c<span class="op">,</span> catwalk<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 needed 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>c<span class="op">](){</span>c<span class="op">.</span>walk<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>c<span class="op">](){</span>c<span class="op">.</span>walk<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>cat<span class="op">::</span>walk<span class="op">&gt;,</span> c<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>c<span class="op">,</span> <span class="op">[](</span>cat<span class="op">&amp;</span> c<span class="op">){</span>leap<span class="op">(</span>c<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>c<span class="op">,</span> leap<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 needed 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>c<span class="op">](){</span>leap<span class="op">(</span>c<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>c<span class="op">](){</span>leap<span class="op">(</span>c<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>leap<span class="op">&gt;,</span> c<span class="op">}</span></span></code></pre></div>
</td>
</tr>
</table>
<p>This has numerous disadvantages when compared to what can currently be performed in the C/C++ core language. It is not easy to use, it is inefficient and at times unsafe to use.</p>
<h5 id="not-easy-to-use">Not easy to use</h5>
<ul>
<li>Unlike the consistent direct initialization of the C/C++ core language example, the initialization of <code>function_ref</code> is <code>bifurcated</code> among passing it directly as a function argument or using 2 step initialization by first creating a named temporary. Direct initialization of function_ref to a variable would be welcomed if the same function_ref is passed to multiple arguments on either the same but more likely different functions. This leads to immediate dangling which must be resolved with an additional line of code. Getting in the habit of only passing <code>function_ref</code> as a argument to a function results in users duplicating lambdas when needed to be used more than once, again needless increasing the volume of code. In both the C/C++ core language and the proposed revision, initialization is consistantly the same and safe regardless of whether <code>function_ref</code> is first assigned to a variable.</li>
<li>Why should a <code>stateful</code> lambda even be needed when the signature is compatible?
<ul>
<li>The C/C++ core language example works with a <code>stateless</code> lambda. By requiring a <code>stateful</code> lambda, a new anonymous type gets created which has state. 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. In the C/C++ core language example, the syntax can get even simpler when the function already exists because in that case the function pointer is passed to the <code>callback</code> struct because the function signature is compatible.</li>
</ul></li>
</ul>
<h5 id="inefficient">Inefficient</h5>
<ul>
<li>By requiring a <code>stateful</code> lambda, a new type is created with a lifetime that must be managed. <code>function_ref</code> is a reference to a <code>stateful</code> 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 run time, granted it is more likely with free functions instead of member functions.</li>
</ul>
<h5 id="unsafe">Unsafe</h5>
<ul>
<li>Direct initialization of function_ref outside of a function argument immediately dangles. Some would say that this is no different than other standardized types such as string_view. 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>c<span class="op">](){</span>c<span class="op">.</span>walk<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>c<span class="op">](){</span>leap<span class="op">(</span>c<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>cat<span class="op">::</span>walk<span class="op">&gt;,</span> c<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>leap<span class="op">&gt;,</span> c<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>c</code> is the state that the user wants to type erase and <code>function_ref</code> would not dangle if <code>c</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>walk</code> or the free function <code>leap</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 function with type erasure are common use cases! <code>member function with type erasure</code> is used by delegates/events in object oriented programming languages and <code>free function with type erasure</code> are common with callbacks in procedural/functional programming languages.</p>
<h4 id="member-function-without-type-erasure">member function without type erasure</h4>
<p>The fact that users do not expect <code>stateless</code> 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 (cat::*mf)() = &amp;cat::walk;</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>cat<span class="op">::</span>walk<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>cat<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>cat<span class="op">::</span>walk<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>cat<span class="op">&amp;)&gt;</span> fr <span class="op">=</span> <span class="op">{</span>nontype<span class="op">&lt;&amp;</span>cat<span class="op">::</span>walk<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 <code>expected</code> behavior is for <code>function_ref</code> referenced state to be unused/<code>nullptr</code>, as <code>ALL</code> of the arguments has to be forwarded since <code>NONE</code> are being type erased. As such dangling is <code>NEVER</code> expected and 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 of use, efficiency and safety due to the superfluous lambda/functor and two step initialization. Further if the size of <code>function_ref</code> is increased beyond 2 pointers to just make the original proposal work for member function pointers, when it is not needed since only a reference to state and a pointer to a trampoline function is needed, then all use cases are pessimistically increased in size.</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 with respect to ease of use, efficiency and safety for the free function without type erasure use case. While the proposed <code>nontype</code> example is slightly more wordy because of using 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 have to know when to do one versus the other i.e. less bifurcation. 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>cat<span class="op">&amp;)</span> <span class="op">=</span> leap<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>cat<span class="op">&amp;)&gt;</span> fr <span class="op">=</span> leap<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>cat<span class="op">&amp;)&gt;</span> fr <span class="op">=</span> <span class="op">{</span>nontype<span class="op">&lt;</span>leap<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>With the overlap in functionality with the free function without type erasure use case, should the existing free function constructor be removed? NO. Initializing a <code>function_ref</code> from a function pointer instead of function pointer initialization statement is still usable in the most runtime of libraries such as runtime dynamic library linking where a function pointer is looked up by a string or some other identifier. It is just not the general case, where users work with declarations found in header files and modules.</p>
<h2 id="solution">Solution</h2>
<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">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 class="kw">class</span> function_ref<span class="op">&lt;</span>R<span class="op">(</span>ArgTypes<span class="op">...)</span> cv <span class="kw">noexcept</span><span class="op">(</span>noex<span class="op">)&gt;</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// MFP is a member function pointer initialization statement</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">// I is an instance of the type that house the member function pointed to by MFP</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> MFP<span class="op">,</span> <span class="kw">class</span> I<span class="op">&gt;</span> function_ref<span class="op">(</span>nontype<span class="op">&lt;</span>MFP<span class="op">&gt;,</span> I<span class="op">*)</span> <span class="kw">noexcept</span><span class="op">;</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// MFP is a member function pointer initialization statement</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span> MFP<span class="op">&gt;</span> function_ref<span class="op">(</span>nontype<span class="op">&lt;</span>MFP<span class="op">&gt;)</span> <span class="kw">noexcept</span><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="co">// FP is a free function pointer initialization statement</span></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">// FST is the type of the first parameter of the free function pointed to by FP</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span> FP<span class="op">,</span> <span class="kw">class</span> FST<span class="op">&gt;</span> function_ref<span class="op">(</span>nontype<span class="op">&lt;</span>FP<span class="op">&gt;,</span> FST<span class="op">*)</span> <span class="kw">noexcept</span><span class="op">;</span></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// FP is a free function pointer initialization statement</span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">auto</span> FP<span class="op">&gt;</span> function_ref<span class="op">(</span>nontype<span class="op">&lt;</span>FP<span class="op">&gt;)</span> <span class="kw">noexcept</span><span class="op">;</span></span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
<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 std::function_ref 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="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="co">// C#</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>delegate <span class="dt">void</span> some_name<span class="op">();</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>some_name fr <span class="op">=</span> leap<span class="op">;</span><span class="co">// the stateless free function use case</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>some_name fr <span class="op">=</span> c<span class="op">.</span>walk<span class="op">;</span><span class="co">// the stateful member function use case</span></span></code></pre></div>
<p>Borland C++ now embarcadero provide 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="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="co">// Borland C++, embarcadero __closure</span></span>
<span id="cb19-2"><a href="#cb19-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="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>fr <span class="op">=</span> leap<span class="op">;</span><span class="co">// the stateless free function use case</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>fr <span class="op">=</span> c<span class="op">.</span>walk<span class="op">;</span><span class="co">// the stateful member function use case</span></span></code></pre></div>
<p>Since <code>nontype function_ref</code> handles all 4 stateless/stateful free/member use cases, it is more feature rich than either of the above.</p>
<h2 id="example-implementation">Example implementation</h2>
<p>The most up-to-date implementation, created by Zhihao Yuan, is available on <code>Github</code> <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>
