<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2393: std::function's Callable definition is broken</title>
<meta property="og:title" content="Issue 2393: std::function's Callable definition is broken">
<meta property="og:description" content="C++ library issue. Status: C++17">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2393.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#C++17">C++17</a> status.</em></p>
<h3 id="2393"><a href="lwg-defects.html#2393">2393</a>. <code>std::function</code>'s <em>Callable</em> definition is broken</h3>
<p><b>Section:</b> 22.10.17.3 <a href="https://wg21.link/func.wrap.func">[func.wrap.func]</a> <b>Status:</b> <a href="lwg-active.html#C++17">C++17</a>
 <b>Submitter:</b> Daniel Kr&uuml;gler <b>Opened:</b> 2014-06-03 <b>Last modified:</b> 2017-07-30</p>
<p><b>Priority: </b>2
</p>
<p><b>View all other</b> <a href="lwg-index.html#func.wrap.func">issues</a> in [func.wrap.func].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++17">C++17</a> status.</p>
<p><b>Discussion:</b></p>
<p>
The existing definition of <code>std::function</code>'s <em>Callable</em> requirements provided in 22.10.17.3 <a href="https://wg21.link/func.wrap.func">[func.wrap.func]</a>
p2,
</p>
<blockquote><p>
A callable object <code>f</code> of type <code>F</code> is <em>Callable</em> for argument types <code>ArgTypes</code> and return type 
<code>R</code> if the expression <code><i>INVOKE</i>(f, declval&lt;ArgTypes&gt;()..., R)</code>, considered as an unevaluated operand 
(Clause 5), is well formed (20.9.2).
</p></blockquote>
<p>
is defective in several aspects:
</p>
<ol style="list-style-type:upper-roman">
<li><p>The wording can be read to be defined in terms of callable objects, not of callable types.</p>
</li>
<li><p>Contrary to that, 22.10.17.3.6 <a href="https://wg21.link/func.wrap.func.targ">[func.wrap.func.targ]</a> p2 speaks of "<code>T</code> shall be a type that is <em>Callable</em> 
(20.9.11.2) for parameter types <code>ArgTypes</code> and return type <code>R</code>."</p>
</li>
<li><p>
The required value category of the callable object during the call expression (lvalue or rvalue) strongly depends on
an interpretation of the expression <code>f</code> and therefore needs to be specified unambiguously.
</p></li>
</ol>
<p>
The intention of original <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1402.html">proposal</a> 
(see IIIa. Relaxation of target requirements) was to refer to both types and values ("we say that the function object <code>f</code> 
(and its type <code>F</code>) is <em>Callable</em> [&hellip;]"), but that mental model is not really deducible from the
existing wording. An improved type-dependence wording would also make the sfinae-conditions specified in 22.10.17.3.2 <a href="https://wg21.link/func.wrap.func.con">[func.wrap.func.con]</a> 
p8 and p21 ("[&hellip;] shall not participate in overload resolution unless <code>f</code> is Callable (20.9.11.2)
for argument types <code>ArgTypes...</code> and return type <code>R</code>.") easier to interpret.
<p/>
My understanding always had been (see e.g. Howard's code example in the 2009-05-01 comment in LWG <a href="lwg-defects.html#815" title="std::function and reference_closure do not use perfect forwarding (Status: Resolved)">815</a><sup><a href="https://cplusplus.github.io/LWG/issue815" title="Latest snapshot">(i)</a></sup>), that 
<code>std::function</code> invokes the call operator of its target via an <b>lvalue</b>. The required value-category is relevant, 
because it allows to reflect upon whether an callable object such as
</p>
<blockquote><pre>
struct RVF 
{
  void operator()() const &amp;&amp; {}
};
</pre></blockquote>
<p>
would be a feasible target object for <code>std::function&lt;void()&gt;</code> or not.
<p/>
Clarifying the current <em>Callable</em> definition seems also wise to make a future transition to language-based concepts
easier. A local fix of the current wording is simple to achieve, e.g. by rewriting it as follows:
</p>
<blockquote><p>
A callable <del>object <code>f</code> of</del> type <ins>(22.10.3 <a href="https://wg21.link/func.def">[func.def]</a>)</ins> <code>F</code> is <em>Callable</em> 
for argument types <code>ArgTypes</code> and return type <code>R</code> if the expression <code><i>INVOKE</i>(<del>f</del><ins>declval&lt;F&amp;&gt;()</ins>, 
declval&lt;ArgTypes&gt;()..., R)</code>, considered as an unevaluated operand (Clause 5), is well formed (20.9.2).
</p></blockquote>
<p>
It seems appealing to move such a general <em>Callable</em> definition to a more "fundamental" place (e.g. as another
paragraph of 22.10.3 <a href="https://wg21.link/func.def">[func.def]</a>), but the question arises, whether such a more general concept should impose
the requirement that the call expression is invoked on an <b>lvalue</b> of the callable object &mdash; such a
special condition would also conflict with the more general definition of the <code>result_of</code> trait, which
is defined for either lvalues or rvalues of the callable type <code>Fn</code>. In this context I would like to point out that
"<em>Lvalue-Callable</em>" is not the one and only <em>Callable</em> requirement in the library. Counter examples are
<code>std::thread</code>, <code>call_once</code>, or <code>async</code>, which depend on "<em>Rvalue-Callable</em>", because they 
all act on functor rvalues, see e.g. 32.4.3.3 <a href="https://wg21.link/thread.thread.constr">[thread.thread.constr]</a>:
</p>
<blockquote><p>
[&hellip;] The new thread of execution executes <code><i>INVOKE</i>(<i>DECAY_COPY</i>(std::forward&lt;F&gt;(f)), 
<i>DECAY_COPY</i>(std::forward&lt;Args&gt;(args))...)</code> [&hellip;]
</p></blockquote>
<p>
For every callable object <code>F</code>, the result of <code><i>DECAY_COPY</i></code> is an rvalue. These implied rvalue function calls are 
no artifacts, but had been deliberately voted for by a Committee decision (see LWG <a href="lwg-defects.html#2021" title="Further incorrect usages of result_of (Status: C++14)">2021</a><sup><a href="https://cplusplus.github.io/LWG/issue2021" title="Latest snapshot">(i)</a></sup>, 2011-06-13 comment) 
and existing implementations respect these constraints correctly. Just to give an example,
</p>
<blockquote><pre>
#include &lt;thread&gt;

struct LVF 
{
  void operator()() &amp; {}
};

int main()
{
  LVF lf;
  std::thread t(lf);
  t.join();
}
</pre></blockquote>
<p>
is supposed to be rejected.
<p/>
The below presented wording changes are suggested to be minimal (still local to <code>std::function</code>), but the used approach
would simplify a future (second) conceptualization or any further generalization of <em>Callable</em> requirements of the Library.
</p>

<p><i>[2015-02 Cologne]</i></p>

<p>
Related to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4348.html">N4348</a>. Don't touch with a barge pole. 
</p>

<p><i>[2015-09 Telecon]</i></p>

<p>
N4348 not going anywhere, can now touch with or without barge poles<br/>
Ville: where is Lvalue-Callable defined?<br/>
Jonathan: this is the definition. It's replacing Callable with a new term and defining that. Understand why it's needed, hate the change.<br/>
Geoff: punt to an LWG discussion in Kona<br/>
</p>

<p><i>[2015-10 Kona]</i></p>

<p>
STL: I like this in general. But we also have an opportunity here to add a precondition. By adding static assertions, 
we can make implementations better. Accept the PR but reinstate the requirement. 
<p/>
MC: Status Review, to be moved to TR at the next telecon.
</p>

<p><i>[2015-10-28 Daniel comments and provides alternative wording]</i></p>

<p>
The wording has been changed as requested by the Kona result. But I would like to provide the following counter-argument for this
changed resolution: Currently the following program is accepted by three popular Standard libraries, Visual Studio 2015, 
gcc 6 libstdc++, and clang 3.8.0 libc++:
</p>
<blockquote><pre>
#include &lt;functional&gt;
#include &lt;iostream&gt;
#include &lt;typeinfo&gt;
#include "boost/function.hpp"

void foo(int) {}

int main() {
  std::function&lt;void(int)&gt; f(foo);
  std::cout &lt;&lt; f.target&lt;double&gt;() &lt;&lt; std::endl;
  boost::function&lt;void(int)&gt; f2(foo);
  std::cout &lt;&lt; f2.target&lt;double&gt;() &lt;&lt; std::endl;
}
</pre></blockquote>
<p>
and outputs the implementation-specific result for <b>two null pointer</b> values.
<p/>
Albeit this code is not conforming, it is probable that similar code exists in the wild. The current
<a href="http://www.boost.org/doc/libs/1_59_0/doc/html/boost/function_base.html">boost documentation</a>
does not indicate <em>any</em> precondition for calling the <code>target</code> function, so it is natural
that programmers would expect similar specification and behaviour.
<p/>
Standardizing the suggested change requires a change of all implementations and I don't see any advantage
for the user. With that change previously working code could now cause instantiation errors, I don't see how 
this could be considered as an improvement of the status quo. The result value of <code>target</code> is 
always a pointer, so a null-check by the user code is already required, therefore I really see no reason 
what kind of problem could result out of the current implementation behaviour, since the implementation 
never is required to perform a C cast to some funny type.
</p>

<p>
<strong>Previous resolution [SUPERSEDED]:</strong>
</p>
<blockquote class="note">
<p>This wording is relative to N3936.</p>

<ol>
<li><p>Change 22.10.17.3 <a href="https://wg21.link/func.wrap.func">[func.wrap.func]</a> p2 as indicated:</p>

<blockquote><p>
-2- A callable <del>object <code>f</code> of</del> type <ins>(22.10.3 <a href="https://wg21.link/func.def">[func.def]</a>)</ins> <code>F</code> is <em><ins>Lvalue-</ins>Callable</em> 
for argument types <code>ArgTypes</code> and return type <code>R</code> if the expression <code><i>INVOKE</i>(<del>f</del><ins>declval&lt;F&amp;&gt;()</ins>, 
declval&lt;ArgTypes&gt;()..., R)</code>, considered as an unevaluated operand (Clause 5), is well formed (20.9.2).
</p></blockquote>
</li>

<li><p>Change 22.10.17.3.2 <a href="https://wg21.link/func.wrap.func.con">[func.wrap.func.con]</a> p8+p21 as indicated:</p>

<blockquote>
<pre>
template&lt;class F&gt; function(F f);
template &lt;class F, class A&gt; function(allocator_arg_t, const A&amp; a, F f);
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-8- <i>Remarks</i>: These constructors shall not participate in overload resolution unless <code><del>f</del><ins>F</ins></code> is 
<code><ins>Lvalue-</ins>Callable</code> (20.9.11.2) for argument types <code>ArgTypes...</code> and return type <code>R</code>.
</p>
</blockquote>
<p>
[&hellip;]
</p>
<pre>
template&lt;class F&gt; function&amp; operator=(F&amp;&amp; f);
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-21- <i>Remarks</i>: This assignment operator shall not participate in overload resolution unless 
<code><del>declval&lt;typename decay&lt;F&gt;::type&amp;&gt;()</del><ins>decay_t&lt;F&gt;</ins></code> is 
<code><ins>Lvalue-</ins>Callable</code> (20.9.11.2) for argument types <code>ArgTypes...</code> and return type <code>R</code>.
</p>
</blockquote>

</blockquote>
</li>

<li><p>Change 22.10.17.3.6 <a href="https://wg21.link/func.wrap.func.targ">[func.wrap.func.targ]</a> p2 as indicated: [<i>Editorial comment</i>: Instead of adapting the preconditions
for the naming change I recommend to strike it completely, because the <code>target()</code> functions do not depend on it; the
corresponding wording exists since its <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1667.pdf">initial proposal</a>
and it seems without any advantage to me. Assume that some template argument <code>T</code> is provided, which does <em>not</em>
satisfy the requirements: The effect will be that the result is a null pointer value, but that case can happen in other (valid) situations
as well. &mdash; <i>end comment</i>]</p>

<blockquote><pre>
template&lt;class T&gt; T* target() noexcept;
template&lt;class T&gt; const T* target() const noexcept;
</pre>
<blockquote>
<p>
<del>-2- <i>Requires</i>: <code>T</code> shall be a type that is <code>Callable</code> (20.9.11.2) for parameter types 
<code>ArgTypes</code> and return type <code>R</code>.</del>
<p/>
-3- <i>Returns</i>: If <code>target_type() == typeid(T)</code> a pointer to the stored function target; otherwise a null
pointer.
</p>
</blockquote>
</blockquote>
</li>
</ol>
</blockquote>

<p><i>[2015-10, Kona Saturday afternoon]</i></p>

<p>GR explains the current short-comings. There's no concept in the standard that expresses rvalue member function qualification, and so, e.g. std::function cannot be forbidden from wrapping such functions. TK: Although it wouldn't currently compile.</p>
<p>GR: Implementations won't change as part of this. We're just clearing up the wording.</p>
<p>STL: I like this in general. But we also have an opportunity here to add a precondition. By adding static assertions, we can make implementations better. Accept the PR but reinstate the requirement.</p>
<p>JW: I hate the word "Lvalue-Callable". I don't have a better suggestion, but it'd be terrible to teach. AM: I like the term. I don't like that we need it, but I like it. AM wants the naming not to get in the way with future naming. MC: We'll review it.</p>
<p>TK: Why don't we also add Rvalue-Callable? STL: Because nobody consumes it.</p>
<p>Discussion whether "tentatively ready" or "review". The latter would require one more meeting. EF: We already have implementation convergence. MC: I worry about a two-meeting delay. WEB: All that being said, I'd be slightly more confident with a review since we'll have new wording, but I wouldn't object. MC: We can look at it in a telecon and move it.</p>
<p>STL reads out email to Daniel.</p>
<p>Status Review, to be moved to TR at the next telecon.</p>

<p><i>[2016-01-31, Daniel comments and suggests less controversive resolution]</i></p>

<p>
It seems that specifically the wording changes for 22.10.17.3.6 <a href="https://wg21.link/func.wrap.func.targ">[func.wrap.func.targ]</a> p2 prevent this issue
from making make progress. Therefore the separate issue LWG <a href="lwg-defects.html#2591" title="std::function's member template target() should not lead to undefined behaviour (Status: C++17)">2591</a><sup><a href="https://cplusplus.github.io/LWG/issue2591" title="Latest snapshot">(i)</a></sup> has been created, that focuses
solely on this aspect. Furtheron the current P/R of this issue has been adjusted to the minimal possible one,
where the term "Callable" has been replaced by the new term "Lvalue-Callable".
</p>

<p>
<strong>Previous resolution II [SUPERSEDED]:</strong>
</p>
<blockquote class="note">
<p>This wording is relative to N4527.</p>

<ol>
<li><p>Change 22.10.17.3 <a href="https://wg21.link/func.wrap.func">[func.wrap.func]</a> p2 as indicated:</p>

<blockquote><p>
-2- A callable <del>object <code>f</code> of</del> type <ins>(22.10.3 <a href="https://wg21.link/func.def">[func.def]</a>)</ins> <code>F</code> is <em><ins>Lvalue-</ins>Callable</em> 
for argument types <code>ArgTypes</code> and return type <code>R</code> if the expression <code><i>INVOKE</i>(<del>f</del><ins>declval&lt;F&amp;&gt;()</ins>, 
declval&lt;ArgTypes&gt;()..., R)</code>, considered as an unevaluated operand (Clause 5), is well formed (20.9.2).
</p></blockquote>
</li>

<li><p>Change 22.10.17.3.2 <a href="https://wg21.link/func.wrap.func.con">[func.wrap.func.con]</a> p8+p21 as indicated:</p>

<blockquote>
<pre>
template&lt;class F&gt; function(F f);
template &lt;class F, class A&gt; function(allocator_arg_t, const A&amp; a, F f);
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-8- <i>Remarks</i>: These constructors shall not participate in overload resolution unless <code><del>f</del><ins>F</ins></code> is 
<code><ins>Lvalue-</ins>Callable</code> (20.9.11.2) for argument types <code>ArgTypes...</code> and return type <code>R</code>.
</p>
</blockquote>
<p>
[&hellip;]
</p>
<pre>
template&lt;class F&gt; function&amp; operator=(F&amp;&amp; f);
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-21- <i>Remarks</i>: This assignment operator shall not participate in overload resolution unless 
<code><del>declval&lt;typename decay&lt;F&gt;::type&amp;&gt;()</del><ins>decay_t&lt;F&gt;</ins></code> is 
<code><ins>Lvalue-</ins>Callable</code> (20.9.11.2) for argument types <code>ArgTypes...</code> and return type <code>R</code>.
</p>
</blockquote>

</blockquote>
</li>

<li><p>Change 22.10.17.3.6 <a href="https://wg21.link/func.wrap.func.targ">[func.wrap.func.targ]</a> p2 as indicated:</p>

<blockquote><pre>
template&lt;class T&gt; T* target() noexcept;
template&lt;class T&gt; const T* target() const noexcept;
</pre>
<blockquote>
<p>
-2- <ins><i>Remarks</i>: If <code>T</code> is a type that is not <code>Lvalue-Callable</code> (20.9.11.2) for parameter types 
<code>ArgTypes</code> and return type <code>R</code>, the program is ill-formed</ins><del><i>Requires</i>: <code>T</code> shall be a type that is <code>Callable</code> (20.9.11.2) for parameter types 
<code>ArgTypes</code> and return type <code>R</code></del>.
<p/>
-3- <i>Returns</i>: If <code>target_type() == typeid(T)</code> a pointer to the stored function target; otherwise a null
pointer.
</p>
</blockquote>
</blockquote>
</li>
</ol>
</blockquote>

<p><i>[2016-03 Jacksonville]</i></p>

Move to Ready.


<p id="res-2393"><b>Proposed resolution:</b></p>
<p>This wording is relative to N4567.</p>

<ol>
<li><p>Change 22.10.17.3 <a href="https://wg21.link/func.wrap.func">[func.wrap.func]</a> p2 as indicated:</p>

<blockquote><p>
-2- A callable <del>object <code>f</code> of</del> type <ins>(22.10.3 <a href="https://wg21.link/func.def">[func.def]</a>)</ins> <code>F</code> is <em><ins>Lvalue-</ins>Callable</em> 
for argument types <code>ArgTypes</code> and return type <code>R</code> if the expression <code><i>INVOKE</i>(<del>f</del><ins>declval&lt;F&amp;&gt;()</ins>, 
declval&lt;ArgTypes&gt;()..., R)</code>, considered as an unevaluated operand (Clause 5), is well formed (20.9.2).
</p></blockquote>
</li>

<li><p>Change 22.10.17.3.2 <a href="https://wg21.link/func.wrap.func.con">[func.wrap.func.con]</a> p8+p21 as indicated:</p>

<blockquote>
<pre>
template&lt;class F&gt; function(F f);
template &lt;class F, class A&gt; function(allocator_arg_t, const A&amp; a, F f);
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-8- <i>Remarks</i>: These constructors shall not participate in overload resolution unless <code><del>f</del><ins>F</ins></code> is 
<code><ins>Lvalue-</ins>Callable</code> (22.10.17.3 <a href="https://wg21.link/func.wrap.func">[func.wrap.func]</a>) for argument types <code>ArgTypes...</code> and return type <code>R</code>.
</p>
</blockquote>
<p>
[&hellip;]
</p>
<pre>
template&lt;class F&gt; function&amp; operator=(F&amp;&amp; f);
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-21- <i>Remarks</i>: This assignment operator shall not participate in overload resolution unless 
<code><del>declval&lt;typename decay&lt;F&gt;::type&amp;&gt;()</del><ins>decay_t&lt;F&gt;</ins></code> is 
<code><ins>Lvalue-</ins>Callable</code> (22.10.17.3 <a href="https://wg21.link/func.wrap.func">[func.wrap.func]</a>) for argument types <code>ArgTypes...</code> and 
return type <code>R</code>.
</p>
</blockquote>

</blockquote>
</li>

<li><p>Change 22.10.17.3.6 <a href="https://wg21.link/func.wrap.func.targ">[func.wrap.func.targ]</a> p2 as indicated:</p>

<blockquote><pre>
template&lt;class T&gt; T* target() noexcept;
template&lt;class T&gt; const T* target() const noexcept;
</pre>
<blockquote>
<p>
-2- <i>Requires</i>: <code>T</code> shall be a type that is <code><ins>Lvalue-</ins>Callable</code> (22.10.17.3 <a href="https://wg21.link/func.wrap.func">[func.wrap.func]</a>) 
for parameter types <code>ArgTypes</code> and return type <code>R</code>.
<p/>
-3- <i>Returns</i>: If <code>target_type() == typeid(T)</code> a pointer to the stored function target; otherwise a null
pointer.
</p>
</blockquote>
</blockquote>
</li>
</ol>





</body>
</html>
