<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2021: Further incorrect usages of result_of</title>
<meta property="og:title" content="Issue 2021: Further incorrect usages of result_of">
<meta property="og:description" content="C++ library issue. Status: C++14">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2021.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++14">C++14</a> status.</em></p>
<h3 id="2021"><a href="lwg-defects.html#2021">2021</a>. Further incorrect usages of <code>result_of</code></h3>
<p><b>Section:</b> 22.10.15.4 <a href="https://wg21.link/func.bind.bind">[func.bind.bind]</a>, 32.10.1 <a href="https://wg21.link/futures.overview">[futures.overview]</a>, 32.10.9 <a href="https://wg21.link/futures.async">[futures.async]</a> <b>Status:</b> <a href="lwg-active.html#C++14">C++14</a>
 <b>Submitter:</b> Daniel Kr&uuml;gler <b>Opened:</b> 2010-12-07 <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.bind.bind">issues</a> in [func.bind.bind].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++14">C++14</a> status.</p>
<p><b>Discussion:</b></p>
<p>
Issue <a href="lwg-defects.html#2017" title="std::reference_wrapper makes incorrect usage of std::result_of (Status: C++11)">2017</a><sup><a href="https://cplusplus.github.io/LWG/issue2017" title="Latest snapshot">(i)</a></sup> points out some incorrect usages of <code>result_of</code> in the
declaration of the function call operator overload of <code>reference_wrapper</code>,
but there are more such specification defects:
</p>
<ol>
<li>According to 22.10.15.4 <a href="https://wg21.link/func.bind.bind">[func.bind.bind]</a> p. 3: 
<blockquote><p>
[..] The effect of <code>g(u1, u2, ..., uM)</code> shall be <code>INVOKE(fd, v1, v2, ..., vN, result_of&lt;FD cv (V1, V2, ..., VN)&gt;::type)</code> [..]
</p></blockquote>
<p>
but <code>fd</code> is defined as &quot;an lvalue of type <code>FD</code> constructed from <code>std::forward&lt;F&gt;(f)</code>&quot;. This means that
the above usage must refer to <code>result_of&lt;FD cv <strong>&amp;</strong> (V1, V2, ..., VN)&gt;</code> instead.
</p>
</li>
<li><p>
Similar in 22.10.15.4 <a href="https://wg21.link/func.bind.bind">[func.bind.bind]</a> p. 10 bullet 2 we have:
</p>
<blockquote><p>
if the value of <code>is_bind_expression&lt;TiD&gt;::value</code> is true, the argument is <code>tid(std::forward&lt;Uj&gt;(uj)...)</code>
and its type <code>Vi</code> is <code>result_of&lt;TiD cv (Uj...)&gt;::type</code>
</p></blockquote>
<p>
Again, <code>tid</code> is defined as &quot;lvalue of type <code>TiD</code> constructed from <code>std::forward&lt;Ti&gt;(ti)</code>&quot;. This means that
the above usage must refer to <code>result_of&lt;TiD cv <strong>&amp;</strong> (Uj...)&gt;</code> instead. We also have similar defect as in
<a href="lwg-defects.html#2017" title="std::reference_wrapper makes incorrect usage of std::result_of (Status: C++11)">2017</a><sup><a href="https://cplusplus.github.io/LWG/issue2017" title="Latest snapshot">(i)</a></sup> in regard to the argument types, this leads us to the further corrected form 
<code>result_of&lt;TiD cv <strong>&amp;</strong> (Uj<strong>&amp;&amp;</strong>...)&gt;</code>. This is not the end: Since the <code>Vi</code>
are similar sensitive to the argument problem, the last part must say: 
<p/>
&quot;[..] its type <code>Vi</code> is <code>result_of&lt;TiD cv <strong>&amp;</strong> (Uj<strong>&amp;&amp;</strong>...)&gt;::type <strong>&amp;&amp;</strong>&quot;</code>
<p/>
(The bound arguments <code>Vi</code> can never be <code>void</code> types, therefore we don't need 
to use the more defensive <code>std::add_rvalue_reference</code> type trait)
</p>
</li>
<li><p>The function template <code>async</code> is declared as follows (the other overload has the same problem):</p>
<blockquote><pre>
template &lt;class F, class... Args&gt;
future&lt;typename result_of&lt;F(Args...)&gt;::type&gt;
async(F&amp;&amp; f, Args&amp;&amp;... args);
</pre></blockquote><p>
This usage has the some same problems as we have found in <code>reference_wrapper</code> (<a href="lwg-defects.html#2017" title="std::reference_wrapper makes incorrect usage of std::result_of (Status: C++11)">2017</a><sup><a href="https://cplusplus.github.io/LWG/issue2017" title="Latest snapshot">(i)</a></sup>) and more: According to
the specification in 32.10.9 <a href="https://wg21.link/futures.async">[futures.async]</a> the effective result type is that of the call of
</p><blockquote><pre>
INVOKE(decay_copy(std::forward&lt;F&gt;(f)), decay_copy(std::forward&lt;Args&gt;(args))...)
</pre></blockquote><p>
First, <code>decay_copy</code> potentially modifies the effective types to <code>decay&lt;F&gt;::type</code> and <code>decay&lt;Args&gt;::type...</code>.
Second, the current specification is not really clear, what the value category of callable type or the arguments shall be: According
to the second bullet of 32.10.9 <a href="https://wg21.link/futures.async">[futures.async]</a> p. 3:
</p>
<blockquote><p>
Invocation of the deferred function evaluates <code>INVOKE(g, xyz)</code> where <code>g</code> is the stored value of 
<code>decay_copy(std::forward&lt;F&gt;(f))</code> and <code>xyz</code> is the stored copy of 
<code>decay_copy(std::forward&lt;Args&gt;(args))...</code>.
</p></blockquote><p>
This seems to imply that lvalues are provided in contrast to the direct call expression of 32.10.9 <a href="https://wg21.link/futures.async">[futures.async]</a> p. 2
which implies rvalues instead. The specification needs to be clarified.
</p>
</li>
</ol>

<p><i>[2011-06-13: Daniel comments and refines the proposed wording changes]</i></p>


<p>The feedback obtained following message c++std-lib-30745  and follow-ups point to the intention, that 
the implied provision of lvalues due to named variables in <code>async</code> should be provided as rvalues to support
move-only types, but the functor type should be forwarded as lvalue in <code>bind</code>.
<p/>
If <code>bind</code> were newly invented, the value strategy could be improved, because now we have a preference of
<i>ref</i> <code>&amp;</code> qualified function call operator overloads. But such a change seems to be too late now.
User-code that needs to bind a callable object with an <i>ref</i> <code>&amp;&amp;</code> qualified function call
operator (or conversion function to function pointer) needs to use a corresponding wrapper similar to <code>reference_wrapper</code>
that forwards the reference as rvalue-reference instead.
<p/>
The wording has been adapted to honor these observations and to fit to FDIS numbering as well.
</p>

<p><i>[Bloomington, 2011]</i></p>

<p>
Move to Ready
</p>



<p id="res-2021"><b>Proposed resolution:</b></p>
<p>
The suggested wording changes are against the FDIS.
</p>
<ol>
<li>
<p>Change 22.10.15.4 <a href="https://wg21.link/func.bind.bind">[func.bind.bind]</a> p. 3 as indicated:</p>

<blockquote><pre>
template&lt;class F, class... BoundArgs&gt;
  <i>unspecified</i> bind(F&amp;&amp; f, BoundArgs&amp;&amp;... bound_args);
</pre><blockquote><p>
-2- <i>Requires</i>: <code>is_constructible&lt;FD, F&gt;::value</code> shall be true. For each <code>Ti</code> in <code>BoundArgs</code>, 
<code>is_constructible&lt;TiD, Ti&gt;::value</code> shall be true. <code><i>INVOKE</i>(fd, w1, w2, ..., wN)</code> (20.8.2) shall 
be a valid expression for some values <code>w1</code>, <code>w2</code>, ..., <code>wN</code>, where <code>N == sizeof...(bound_args)</code>.
<p/>
-3- <i>Returns</i>: A forwarding call wrapper <code>g</code> with a weak result type (20.8.2). The effect of 
<code>g(u1, u2, ..., uM)</code> shall be <code>INVOKE(fd, <ins>std::forward&lt;V1&gt;(</ins>v1<ins>)</ins>, 
<ins>std::forward&lt;V2&gt;(</ins>v2<ins>)</ins>, ..., <ins>std::forward&lt;VN&gt;(</ins>vN<ins>)</ins>, 
result_of&lt;FD <i>cv</i> <ins>&amp;</ins> (V1, V2, ..., VN)&gt;::type)</code>, where <i>cv</i> represents 
the <i>cv</i>-qualifiers of <code>g</code> and the values and types of the bound arguments <code>v1</code>, 
<code>v2</code>, ..., <code>vN</code> are determined as specified below. [&hellip;]
</p></blockquote></blockquote>

</li>

<li>
<p>Change 22.10.15.4 <a href="https://wg21.link/func.bind.bind">[func.bind.bind]</a> p. 7 as indicated:</p>

<blockquote><pre>
template&lt;class R, class F, class... BoundArgs&gt;
   <i>unspecified</i> bind(F&amp;&amp; f, BoundArgs&amp;&amp;... bound_args);
</pre><blockquote><p>
-6- <i>Requires</i>: <code>is_constructible&lt;FD, F&gt;::value</code> shall be true. For each <code>Ti</code> in <code>BoundArgs</code>, 
<code>is_constructible&lt;TiD, Ti&gt;::value</code> shall be true. <code><i>INVOKE</i>(fd, w1, w2, ..., wN)</code> shall be a valid 
expression for some values <code>w1</code>, <code>w2</code>, ..., <code>wN</code>, where <code>N == sizeof...(bound_args)</code>.
<p/>
-7- <i>Returns</i>: A forwarding call wrapper <code>g</code> with a nested type <code>result_type</code> defined as a synonym for
<code>R</code>. The effect of <code>g(u1, u2, ..., uM)</code> shall be <code>INVOKE(fd, <ins>std::forward&lt;V1&gt;(</ins>v1<ins>)</ins>, 
<ins>std::forward&lt;V2&gt;(</ins>v2<ins>)</ins>, ..., <ins>std::forward&lt;VN&gt;(</ins>vN<ins>)</ins>, R)</code>, where 
the values and types of the bound arguments <code>v1</code>, <code>v2</code>, ..., <code>vN</code> are determined as specified below. [&hellip;]
</p></blockquote></blockquote>

</li>

<li>
<p>Change 22.10.15.4 <a href="https://wg21.link/func.bind.bind">[func.bind.bind]</a> p. 10 as indicated:</p>

<blockquote><p>
-10- The values of the <i>bound arguments</i> <code>v1</code>, <code>v2</code>, ..., <code>vN</code> and their corresponding types <code>V1</code>, 
<code>V2</code>, ..., <code>VN</code> depend on the types <code>TiD</code> derived from the call to bind and the <i>cv</i>-qualifiers 
<i>cv</i> of the call wrapper <code>g</code> as follows:</p>
<ul>
<li>if <code>TiD</code> is <code>reference_wrapper&lt;T&gt;</code>, the argument is <code>tid.get()</code> and its type <code>Vi</code> 
is <code>T&amp;</code>;</li>
<li>if the value of <code>is_bind_expression&lt;TiD&gt;::value</code> is <code>true</code>, the argument is 
<code>tid(std::forward&lt;Uj&gt;(uj)...)</code> and its type <code>Vi</code> is 
<code>result_of&lt;TiD <i>cv</i> <ins>&amp;</ins> (Uj<ins>&amp;&amp;</ins>...)&gt;::type<ins>&amp;&amp;</ins></code>;</li>
<li>if the value <code>j</code> of <code>is_placeholder&lt;TiD&gt;::value</code> is not zero, the argument is 
<code>std::forward&lt;Uj&gt;(uj)</code> and its type <code>Vi</code> is <code>Uj&amp;&amp;</code>;</li>
<li>otherwise, the value is <code>tid</code> and its type <code>Vi</code> is <code>TiD <i>cv</i> &amp;</code>.</li>
</ul>
</blockquote>

</li>

<li>
<p>
This resolution assumes that the wording of 32.10.9 <a href="https://wg21.link/futures.async">[futures.async]</a> is intended to provide rvalues
as arguments of <code>INVOKE</code>.
</p>

<p>
Change the function signatures in header <code>&lt;future&gt;</code> synopsis 32.10.1 <a href="https://wg21.link/futures.overview">[futures.overview]</a> p. 1
and in 32.10.9 <a href="https://wg21.link/futures.async">[futures.async]</a> p. 1 as indicated:
</p>

<blockquote><pre>
template &lt;class F, class... Args&gt;
future&lt;typename result_of&lt;<ins>typename decay&lt;</ins>F<ins>&gt;::type</ins>(<ins>typename decay&lt;</ins>Args<ins>&gt;::type</ins>...)&gt;::type&gt;
async(F&amp;&amp; f, Args&amp;&amp;... args);
template &lt;class F, class... Args>
future&lt;typename result_of&lt;<ins>typename decay&lt;</ins>F<ins>&gt;::type</ins>(<ins>typename decay&lt;</ins>Args<ins>&gt;::type</ins>...)&gt;::type&gt;
async(launch policy, F&amp;&amp; f, Args&amp;&amp;... args);
</pre></blockquote>
</li>

<li>
<p>Change 32.10.9 <a href="https://wg21.link/futures.async">[futures.async]</a> as indicated: (Remark: There is also a tiny editorial correction 
in p. 4 that completes one <code>::</code> scope specifier)
</p>

<blockquote><p>
-3- <i>Effects</i>: [&hellip;]
</p>
<ul>
<li>[&hellip;]</li>
<li>if <code>policy &amp; launch::deferred</code> is non-zero &mdash; Stores <code><i>DECAY_COPY</i>(std::forward&lt;F&gt;(f))</code> 
and <code><i>DECAY_COPY</i>(std::forward&lt;Args&gt;(args))...</code> in the shared state. These copies of <code>f</code> and 
<code>args</code> constitute a <i>deferred function</i>. Invocation of the deferred function evaluates 
<code><i>INVOKE</i>(<ins>std::move(</ins>g<ins>)</ins>, <ins>std::move(</ins>xyz<ins>)</ins>)</code>
where <code>g</code> is the stored value of <code><i>DECAY_COPY</i>(std::forward&lt;F&gt;(f))</code> and <code>xyz</code> is the 
stored copy of <code><i>DECAY_COPY</i>(std::forward&lt;Args&gt;(args))...</code>. The shared state is not made ready 
until the function has completed. The first call to a non-timed waiting function (30.6.4) on an asynchronous
return object referring to this shared state shall invoke the deferred function in the thread that
called the waiting function. Once evaluation of <code><i>INVOKE</i>(<ins>std::move(</ins>g<ins>)</ins>, 
<ins>std::move(</ins>xyz<ins>)</ins>)</code> begins, the function is no longer considered deferred. [ <i>Note</i>: If 
this policy is specified together with other policies, such as when using a <code>policy</code> value of 
<code>launch::async | launch::deferred</code>, implementations should defer invocation or the selection of 
the policy when no more concurrency can be effectively exploited. &mdash; <i>end note</i> ]</li>
</ul>
</blockquote>

<blockquote><p>
-4- <i>Returns</i>: an object of type 
<code>future&lt;typename result_of&lt;<ins>typename decay&lt;</ins>F<ins>&gt;::type</ins>(<ins>typename decay&lt;</ins>Args<ins>&gt;::type</ins>...)&gt;:<ins>:</ins>type&gt;</code> 
that refers to the associated asynchronous state created by this call to <code>async</code>.
</p></blockquote>
</li>
</ol>





</body>
</html>
