<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 815: std::function and reference_closure do not use perfect forwarding</title>
<meta property="og:title" content="Issue 815: std::function and reference_closure do not use perfect forwarding">
<meta property="og:description" content="C++ library issue. Status: Resolved">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue815.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#Resolved">Resolved</a> status.</em></p>
<h3 id="815"><a href="lwg-defects.html#815">815</a>. <code>std::function</code> and <code>reference_closure</code> do not use perfect forwarding</h3>
<p><b>Section:</b> 22.10.17.3.5 <a href="https://wg21.link/func.wrap.func.inv">[func.wrap.func.inv]</a> <b>Status:</b> <a href="lwg-active.html#Resolved">Resolved</a>
 <b>Submitter:</b> Alisdair Meredith <b>Opened:</b> 2008-03-16 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#func.wrap.func.inv">issues</a> in [func.wrap.func.inv].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Resolved">Resolved</a> status.</p>
<p><b>Discussion:</b></p>
<p>
<code>std::function</code> and <code>reference_closure</code> should use "perfect forwarding" as
described in the rvalue core proposal.
</p>

<p><i>[
Sophia Antipolis:
]</i></p>


<blockquote><p>
According to Doug Gregor, as far as <code>std::function</code> is concerned, perfect
forwarding can not be obtained because of type erasure. Not everyone
agreed with this diagnosis of forwarding.
</p></blockquote>

<p><i>[
2009-05-01 Howard adds:
]</i></p>


<blockquote>
<p>
Sebastian Gesemann brought to my attention that the <code>CopyConstructible</code>
requirement on <code>function</code>'s <code>ArgTypes...</code> is an unnecessary
restriction.
</p>

<blockquote><pre>
template&lt;Returnable R, <b>CopyConstructible</b>... ArgTypes&gt;
class function&lt;R(ArgTypes...)&gt;
...
</pre></blockquote>

<p>
On further investigation, this complaint seemed to be the same
issue as this one.  I believe the reason <code>CopyConstructible</code> was put
on <code>ArgTypes</code> in the first place was because of the nature of the
<i>invoke</i> member:
</p>

<blockquote><pre>
template&lt;class R, class ...ArgTypes&gt;
R
function&lt;R(ArgTypes...)&gt;::operator()(ArgTypes... arg) const
{
    if (f_ == 0)
        throw bad_function_call();
    return (*f_)(arg...);
}
</pre></blockquote>

<p>
However now with rvalue-refs, "by value" no longer implies <code>CopyConstructible</code>
(as Sebastian correctly points out).  If rvalue arguments are supplied, <code>MoveConstructible</code>
is sufficient.  Furthermore, the constraint need not be applied in <code>function</code>
if I understand correctly.  Rather the client must apply the proper constraints
at the call site.  Therefore, at the very least, I recommend that <code>CopyConstructible</code>
be removed from the template class <code>function</code>.
</p>

<p>
Furthermore we need to mandate that the <i>invoker</i> is coded as:
</p>

<blockquote><pre>
template&lt;class R, class ...ArgTypes&gt;
R
function&lt;R(ArgTypes...)&gt;::operator()(ArgTypes... arg) const
{
    if (f_ == 0)
        throw bad_function_call();
    return (*f_)(<b>std::forward&lt;ArgTypes&gt;(</b>arg<b>)</b>...);
}
</pre></blockquote>

<p>
Note that <code>ArgTypes&amp;&amp;</code> (the "perfect forwarding signature") is not 
appropriate here as this is not a deduced context for <code>ArgTypes</code>.  Instead
the client's arguments must implicitly convert to the non-deduced <code>ArgType</code>
type.  Catching these arguments by value makes sense to enable decay.
</p>

<p>
Next <code>forward</code> is used to move the <code>ArgTypes</code> as efficiently as
possible, and also with minimum requirements (not <code>CopyConstructible</code>)
to the type-erased functor.  For object types, this will be a <code>move</code>.  For
reference type <code>ArgTypes</code>, this will be a copy.  The end result <em>must</em> be
that the following is a valid program:
</p>

<blockquote><pre>
#include &lt;functional&gt;
#include &lt;memory&gt;
#include &lt;cassert&gt;

std::unique_ptr&lt;int&gt;
f(std::unique_ptr&lt;int&gt; p, int&amp; i)
{
    ++i;
    return std::move(p);
}

int main()
{
    int i = 2;
    std::function&lt;std::unique_ptr&lt;int&gt;(std::unique_ptr&lt;int&gt;,
                                       int&amp;&gt; g(f);
    std::unique_ptr&lt;int&gt; p = g(std::unique_ptr&lt;int&gt;(new int(1)), i);
    assert(*p == 1);
    assert(i == 3);
}
</pre></blockquote>

<p><i>[
Tested in pre-concepts rvalue-ref-enabled compiler.
]</i></p>


<p>
In the example above, the first <code>ArgType</code> is <code>unique_ptr&lt;int&gt;</code>
and the second <code>ArgType</code> is <code>int&amp;</code>.  Both <em>must</em> work!
</p>

</blockquote>

<p><i>[
2009-05-27 Daniel adds:
]</i></p>


<blockquote>
<p>
in the 2009-05-01 comment of above mentioned issue Howard
</p>

<ol style="list-style-type:lower-alpha">
<li>
Recommends to replace the <code>CopyConstructible</code> requirement by a
<code>MoveConstructible</code> requirement
</li>
<li>
Says: "Furthermore, the constraint need not be applied in <code>function</code> if I
understand correctly. Rather the client must apply the proper constraints
at the call site"
</li>
</ol>
<p>
I'm fine with (a), but I think comment (b) is incorrect, at least in the
sense I read these sentences. Let's look at Howard's example code:
</p>

<blockquote><pre>
function&lt;R(ArgTypes...)&gt;::operator()(ArgTypes... arg) const
{
   if (f_ == 0)
       throw bad_function_call();
   return (*f_)(std::forward&lt;ArgTypes&gt;(arg)...);
}
</pre></blockquote>

<p>
In the constrained scope of this <code>operator()</code> overload the expression
"<code>(*f_)(std::forward&lt;ArgTypes&gt;(arg)...)</code>" must be valid. How can it
do so, if <code>ArgTypes</code> aren't at least <code>MoveConstructible</code>?
</p>
</blockquote>

<p><i>[
2009-07 Frankfurt:
]</i></p>


<blockquote><p>
Leave this open and wait until concepts are removed from the Working
Draft so that we know how to write the proposed resolution in terms of
diffs to otherwise stable text.
</p></blockquote>

<p><i>[
2009-10 Santa Cruz:
]</i></p>


<blockquote><p>
Leave as open. Howard to provide wording. Howard welcomes any help.
</p></blockquote>

<p><i>[
2009-12-12 Jonathan Wakely adds:
]</i></p>


<blockquote>
<p>
22.10.17.3 <a href="https://wg21.link/func.wrap.func">[func.wrap.func]</a> says
</p>

<blockquote><p>
2  A function object <code>f</code> of type <code>F</code> is Callable for argument
types <code>T1, T2, ..., TN</code> in <code>ArgTypes</code> and a return type
<code>R</code>, if, given lvalues <code>t1, t2, ..., tN</code> of types <code>T1, T2, ...,
TN</code>, respectively, <code>INVOKE (f, t1, t2, ..., tN)</code> is well formed
(20.7.2) and, if <code>R</code> is not <code>void</code>, convertible to <code>R</code>.
</p></blockquote>

<p>
N.B. lvalues, which means you can't use <code>function&lt;R(T&amp;&amp;)&gt;</code>
or <code>function&lt;R(unique_ptr&lt;T&gt;)&gt;</code>
</p>

<p>
I recently implemented rvalue arguments in GCC's <code>std::function</code>, all
that was needed was to use <code>std::forward&lt;ArgTypes&gt;</code> in a few
places. The example in issue 815 works.
</p>

<p>
I think 815 could be resolved by removing the requirement that the target
function be callable with lvalues.  Saying <code>ArgTypes</code> need to be
<code>CopyConstructible</code> is wrong, and IMHO saying <code>MoveConstructible</code>
is unnecessary, since the by-value signature implies that already, but if it is
needed it should only be on <code>operator()</code>, not the whole class (you could
in theory instantiate <code>std::function&lt;R(noncopyable)&gt;</code> as long as
you don't invoke the call operator.)
</p>

<p>
I think defining invocation in terms of <code>INVOKE</code> already implies perfect
forwarding, so we don't need to say explicitly that <code>std::forward</code> should
be used (N.B. the types that are forwarded are those in <code>ArgTypes</code>, which
can differ from the actual parameter types of the target function.  The actual
parameter types have gone via type erasure, but that's not a problem - IMHO
forwarding the arguments as <code>ArgTypes</code> is the right thing to do anyway.)
</p>

<p>
Is it sufficient to simply replace "lvalues" with "values"? or do we need to say
something like "lvalues when <code>Ti</code> is an lvalue-reference and rvalues
otherwise"?  I prefer the former, so I propose the following resolution for 815:
</p>

<p>
Edit 22.10.17.3 <a href="https://wg21.link/func.wrap.func">[func.wrap.func]</a> paragraph 2:
</p>

<blockquote><p>
2  A function object <code>f</code> of type <code>F</code> is Callable for argument
types <code>T1, T2, ..., TN</code> in <code>ArgTypes</code> and a return type
<code>R</code>, if, given <del>l</del>values <code>t1, t2, ..., tN</code> of types
<code>T1, T2, ..., TN</code>, respectively, <code>INVOKE (f, t1, t2, ..., tN)</code> is
well formed (20.7.2) and, if <code>R</code> is not <code>void</code>, convertible to
<code>R</code>.
</p></blockquote>
</blockquote>

<p><i>[
2009-12-12 Daniel adds:
]</i></p>


<blockquote><p>
I don't like the reduction to "values" and prefer the alternative solution
suggested using "lvalues when Ti is an lvalue-reference and rvalues otherwise".
The reason why I dislike the shorter version is based on different usages of
"values" as part of defining the semantics of requirement tables via
expressions. E.g. 16.4.4.2 <a href="https://wg21.link/utility.arg.requirements">[utility.arg.requirements]</a>/1 says "<code>a</code>,
<code>b</code>, and <code>c</code> are values of type <code>const T;</code>" or similar in
23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a>/4 or /14 etc. My current reading
of all these parts is that <em>both</em> rvalues and lvalues are required to be
supported, but this interpretation would violate the intention of the suggested
fix of #815, if I correctly understand Jonathan's rationale.
</p></blockquote>

<p><i>[
2009-12-12 Howard adds:
]</i></p>


<blockquote>
<blockquote><p>
"lvalues when Ti is an lvalue-reference and rvalues otherwise"
</p></blockquote>
<p>
doesn't quite work here because the <code>Ti</code> aren't deduced.  They are
specified by the <code>function</code> type.  <code>Ti</code> might be <code>const
int&amp;</code> (an lvalue reference) and a valid <code>ti</code> might be <code>2</code>
(a non-const rvalue).  I've taken another stab at the wording using
"expressions" and "bindable to".
</p>
</blockquote>

<p><i>[
2010-02-09 Wording updated by Jonathan, Ganesh and Daniel.
]</i></p>


<p><i>[
2010-02-09 Moved to Tentatively Ready after 5 positive votes on c++std-lib.
]</i></p>


<p><i>[
2010-02-10 Daniel opens to improve wording.
]</i></p>


<p><i>[
2010-02-11 This issue is now addressed by <a href="lwg-defects.html#870" title="Do unordered containers not support function pointers for predicate&#47;hasher? (Status: C++11)">870</a><sup><a href="https://cplusplus.github.io/LWG/issue870" title="Latest snapshot">(i)</a></sup>.
]</i></p>


<p><i>[
2010-02-12 Moved to Tentatively NAD Editorial after 5 positive votes on
c++std-lib.  Rationale added below.
]</i></p>




<p><b>Rationale:</b></p>
<p>
Addressed by <a href="lwg-defects.html#870" title="Do unordered containers not support function pointers for predicate&#47;hasher? (Status: C++11)">870</a><sup><a href="https://cplusplus.github.io/LWG/issue870" title="Latest snapshot">(i)</a></sup>.
</p>


<p id="res-815"><b>Proposed resolution:</b></p>
<p>
Edit 22.10.17.3 <a href="https://wg21.link/func.wrap.func">[func.wrap.func]</a> paragraph 2:
</p>

<blockquote>
<p>
2  A function object <code>f</code> of type <code>F</code> is Callable for argument
types <del><code>T1, T2, ..., TN</code> in</del> <code>ArgTypes</code> and <del>a</del>
return type <code>R</code><del>,</del> if<del>, given lvalues <code>t1, t2, ...,
tN</code> of types <code>T1, T2, ..., TN</code>, respectively,</del> <ins>the
expression</ins> <code><i>INVOKE</i>(f, <ins>declval&lt;ArgTypes&gt;()...,
R</ins><del>t1, t2, ..., tN</del>)</code><ins>, considered as an unevaluated
operand (7 <a href="https://wg21.link/expr">[expr]</a>),</ins> is well formed (20.7.2)<del> and, if
<code>R</code> is not <code>void</code>, convertible to <code>R</code></del>.
</p>

</blockquote>





</body>
</html>
