<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<style type="text/css">
pre {margin-left:20pt; }
pre > i {
  font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
code > i {
  font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
pre > em {
  font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
code > em {
  font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
body { color: #000000; background-color: #FFFFFF; }
del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }

p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
  border: 1px solid #E1E28E; }

p.function { }
.attribute { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;
  padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

blockquote.std { color: #000000; background-color: #F1F1F1;
  border: 1px solid #D1D1D1;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stddel { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC;
  padding-left: 0.5empadding-right: 0.5em; ; }

blockquote.stdins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3; padding: 0.5em; }

table.header { border: 0px; border-spacing: 0;
  margin-left: 0px; font-style: normal; }

table { border: 1px solid black; border-spacing: 0px;
  margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;
  padding-left: 0.4em; border: none; 
  padding-right: 0.4em; border: none; }
td { text-align: left; vertical-align: top;
  padding-left: 0.4em; border: none;
  padding-right: 0.4em; border: none; }
</style>

<title>A proposal to add invoke function template (Revision 1)</title>
</head>

<body>

<table class="header"><tbody>
  <tr>
    <th>Document number:&nbsp;&nbsp;</th><th> </th><td>N4169</td>
  </tr>
  <tr>
    <th>Date:&nbsp;&nbsp;</th><th> </th><td>2014-08-22</td>
  </tr>
  <tr>
    <th>Project:&nbsp;&nbsp;</th><th> </th><td>Programming Language C++, Library Evolution Working Group</td>
  </tr>
  <tr>
    <th>Reply-to:&nbsp;&nbsp;</th><th> </th><td><address>Tomasz Kamiński &lt;tomaszkam at gmail dot com&gt;</address></td>
  </tr>
</tbody></table>

<h1><a name="title">A proposal to add invoke function template (Revision 1)</a></h1>

<h2><a name="intro">Introduction</a></h2>

<p>The aim of this proposal is to introduce the function template <code>invoke</code> that provide uniform semantics for invoking all C++
callable types which includes: function pointers, member pointers and functors. 
The behaviour of the function is defined in terms of <code><em>INVOKE</em></code> expression.</p>

<!--h2><a name="toc">Table of contents</a></h2-->

<h2><a name="revision">Revision history</a></h2>

<p>Changes since <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3727.html">N3727</a>:</p>
<ul>
  <li>Removed version with explicitly specified return type (<code>invoke&lt;R&gt;</code>).</li>
  <li>Changed Introduction and Motivation and Scope sections.</li>
  <li>Changed the paragraph numbers to match newest working draft.</li>
</ul>

<h2><a name="motivation">Motivation and Scope</a></h2>

<p>The functional components defined introduced in the C++11 has native support for member pointers, that means that these types
can be directly used with <code>std::function</code> or <code>std::bind</code>, without need to use wrappers like <code>std::mem_fun</code>,
<code>std::mem_fun_ref</code> or <code>std::mem_fn</code>. This uniform support was achieved by introduction of <code><em>INVOKE</em></code>
expression.</p>

<p>On the other side, there is no standard component, that will provide uniform syntax for calling any callable object with given arguments,
so when generic component is developed, the programmer has two options: implement separate handling for member pointers (auto boxing with
<code>std::mem_fn</code>) or support only function types. Because of additional implementation burden and relatively small popularity
of this feature the second approach is preferred. Most notably the <code>apply</code> function from <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4082.pdf">Library Fundamentals TS</a>
lacks of support for member pointers.</p>

<h3><a name="motivation.deref-example">Simple call wrapper example</a></h3>

<p>As example, please consider the <code>deref_fn</code> wrapper, that should accept any callable object <code>f</code> and return a functor
that invokes provided callable and dereferences the result.</p>

<p>Using existing C++14 standard facilities <code>deref_fn</code> function may be implemented as:</p>
<pre>  template&lt;typename F, std::enable_if_t&lt;!std::is_member_pointer&lt;std::decay_t&lt;F&gt;&gt;{}, int&gt; = 0&gt;
  auto deref_fn(F&amp;&amp; f) 
  { 
    return [f](auto&amp;&amp;... args) { return *f(std::forward&lt;decltype(args)&gt;(args)...); };
  } 

  template&lt;typename F, std::enable_if_t&lt;std::is_member_pointer&lt;std::decay_t&lt;F&gt;&gt;{}, int&gt; = 0&gt;
  auto deref_fn(F&amp;&amp; f)
  { 
    return [mf = std::mem_fn(f)](auto&amp;&amp;... args) { return *mf(std::forward&lt;decltype(args)&gt;(args)...); };
  }
</pre>

<p>Proposed <code>invoke</code> function allows simpler implementation, that does not resort to use of SFINAE function overloading:</p>
<pre>  template&lt;typename F&gt;
  auto deref_fn(F&amp;&amp; f) 
  { 
    return [f](auto&amp;&amp;... args) { return *std::invoke(f, std::forward&lt;decltype(args)&gt;(args)...); };
  }
</pre>

<h2><a name="design">Design Decisions</a></h2>

<h3><a name="design.constexpr"><code>constexpr</code> implementation</a></h3>

<p>Although there is possibility to implement standard conforming <code>invoke</code> function template as a <code>constexpr</code> function, 
the proposed wording does not require such implementation. The main reason is to left it consistent with existing standard function objects, 
that could have such definition, like <code>std::mem_fn</code>, <code>std::reference_wrapper</code> and operator wrappers. 
Furthermore imposing such requirement will block the implementation of <code>invoke</code> that refers to <code>std::mem_fn</code>.</p>

<p>This proposal assumes that <code>constexpr</code> addition to the <code>&lt;functional&gt;</code> header would be applied consistently by a separate proposal.</p>

<p>Both <code>constexpr</code> and standard library based implementation are presented in <a href="#implementability">Implementability</a> section of the proposal.</p>

<h3><a name="design.replace_invoke">Replacing <code><em>INVOKE</em></code> expression</a></h3>

<p>The wording of this proposal may also be specified by moving the requirements of the <code><em>INVOKE</em></code> expression to definition of the <code>invoke</code> 
function template and replacing all existing references to the <code><em>INVOKE</em></code> expression by corresponding <code>invoke</code> function invocation.</p>

<p>The approach described above is not used in this proposal, primarily to give implementation freedom to the standard library providers (e.g., 
whether <code>invoke</code> should be defined in terms of <code>mem_fn</code> or vice versa). In addition such approach will require changes in existing 
implementations of standard function objects, without providing any real benefit from the library user perspective.</p> 

<h3><a name="design.explicit_return">Overload with explicit return type</a></h3>

<p>First revision of the paper definied second overload of the proposed function (<code>invoke&lt;R&gt;(args...)</code>), mapped to <code><em>INVOKE</em></code> 
expression with explicit specification of return type (<code><em>INVOKE</em>(args..., R)</code>). Mentioned version is leftover from TR1 implementation,
were result type was determined using <code>result_of</code> protocol or has to be specified at call side and, after the introduction of type interference
in C++11, it becomes obsolete.</p>

<h2><a name="standard">Impact On The Standard</a></h2>

<p>This proposal has no dependencies beyond a C++11 compiler and Standard Library implementation. (It depends on perfect forwarding, varidatic templates, 
<code>decltype</code> and trailing return types.)</p>

<p>Nothing depends on this proposal.</p>

<h2><a name="wording">Proposed wording</a></h2>

<p>After the declaration of <code>binary_function</code> in the section 20.9 [function.objects]/2 (Header <code>&lt;functional&gt;</code> synopsis), add:

</p><blockquote class="stdins"> 
<pre>  // 20.9.3, <em>invoke</em>
  template &lt;class F, class... Args&gt; result_of_t&lt;F&amp;&amp;(Args&amp;&amp;...)&gt; invoke(F&amp;&amp; f, Args&amp;&amp;... args);
</pre>
 
</blockquote>

<p>After paragraph 20.9.2 Requirements [func.require], insert a new paragraph. (Chapter [refwrap] (Class template <code>reference_wrapper</code>) becomes 20.9.?)</p>
  
<blockquote class="stdins"> 
<h4><a name="invoke">20.9.3 Function template <code>invoke</code> <span style="float:right">[func.invoke]</span></a></h4>

<pre>  template &lt;class F, class... Args&gt;
    result_of_t&lt;F&amp;&amp;(Args&amp;&amp;...)&gt; invoke(F&amp;&amp; f, Args&amp;&amp;... args);
</pre>
  <dl class="attribute">
    <dt>Returns:</dt> <dd><p><code><em>INVOKE</em>(std::forward&lt;F&gt;(f), std::forward&lt;Args&gt;(args)...)</code> ([func.require] 20.9.2).</p> </dd>
  </dl>

</blockquote>

<h2><a name="implementability">Implementability</a></h2>

<p>Proposed <code>invoke</code> function template may be implemented in terms of existing C++11 standard library components:</p>
<pre>  template&lt;typename Functor, typename... Args&gt;
  typename std::enable_if&lt;
    std::is_member_pointer&lt;typename std::decay&lt;Functor&gt;::type&gt;::value,
    typename std::result_of&lt;Functor&amp;&amp;(Args&amp;&amp;...)&gt;::type
  &gt;::type invoke(Functor&amp;&amp; f, Args&amp;&amp;... args)
  { 
    return std::mem_fn(f)(std::forward&lt;Args&gt;(args)...); 
  }
   
  template&lt;typename Functor, typename... Args&gt;
  typename std::enable_if&lt;
    !std::is_member_pointer&lt;typename std::decay&lt;Functor&gt;::type&gt;::value,
    typename std::result_of&lt;Functor&amp;&amp;(Args&amp;&amp;...)&gt;::type
  &gt;::type invoke(Functor&amp;&amp; f, Args&amp;&amp;... args)
  { 
    return std::forward&lt;Functor&gt;(f)(std::forward&lt;Args&gt;(args)...); 
  }
</pre>

<p>An <code>constexpr</code> implemenatation may be found at: <a href="https://github.com/tomaszkam/proposals/blob/master/invoke/invoke_cpp11.hpp">https://github.com/tomaszkam/proposals/blob/master/invoke/invoke_cpp11.hpp</a>.</p>

<h2><a name="acknowledgements">Acknowledgements</a></h2>

<p>Joe Gottman originally proposed <code>invoke</code> function in discussion group <a href="https://groups.google.com/a/isocpp.org/forum/?fromgroups#%21topic/std-proposals/InJClAiLXcI">ISO C++ Standard - Future Proposals</a>.</p>
<p>Andrzej Krzemieński offered many useful suggestions and corrections to the proposal.</p>

<h2><a name="literature">References</a></h2>

<ol>
  <li>Jeffrey Yasskin, "Working Draft, C++ Extensions for Library Fundamentals" (N3421, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4082.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4082.pdf</a>)</li>
  <li>Tomasz Kamiński, Implementation of invoke function (<a href="https://github.com/tomaszkam/proposals/blob/master/invoke/invoke_cpp11.hpp">https://github.com/tomaszkam/proposals/blob/master/invoke/invoke_cpp11.hpp</a>)</li>
</ol>


</body></html>
