<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2017: std::reference_wrapper makes incorrect usage of std::result_of</title>
<meta property="og:title" content="Issue 2017: std::reference_wrapper makes incorrect usage of std::result_of">
<meta property="og:description" content="C++ library issue. Status: C++11">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2017.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++11">C++11</a> status.</em></p>
<h3 id="2017"><a href="lwg-defects.html#2017">2017</a>. <code>std::reference_wrapper</code> makes incorrect usage of <code>std::result_of</code></h3>
<p><b>Section:</b> 22.10.6 <a href="https://wg21.link/refwrap">[refwrap]</a> <b>Status:</b> <a href="lwg-active.html#C++11">C++11</a>
 <b>Submitter:</b> Nikolay Ivchenkov <b>Opened:</b> 2010-11-15 <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#refwrap">issues</a> in [refwrap].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++11">C++11</a> status.</p>
<p><b>Discussion:</b></p>
<p>
<code>std::reference_wrapper</code>'s function call operator uses <em>wrong</em>
type encoding for rvalue-arguments. An rvalue-argument of type <code>T</code> must
be encoded as <code>T&amp;&amp;</code>, not as just <code>T</code>.
</p>
<blockquote><pre>
#include &lt;functional&gt;
#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;type_traits&gt;
#include &lt;utility&gt;

template &lt;class F, class... Types&gt;
     typename std::result_of&lt;F (Types...)&gt;::type
         f1(F f, Types&amp;&amp;... params)
{
     return f(std::forward&lt;Types...&gt;(params...));
}

template &lt;class F, class... Types&gt;
     typename std::result_of&lt;F (Types<b>&amp;&amp;</b>...)&gt;::type
         f2(F f, Types&amp;&amp;... params)
{
     return f(std::forward&lt;Types...&gt;(params...));
}

struct Functor
{
     template &lt;class T&gt;
         T&amp;&amp; operator()(T&amp;&amp; t) const
     {
         return static_cast&lt;T&amp;&amp;&gt;(t);
     }
};

int main()
{
     typedef std::string const Str;
     std::cout &lt;&lt; f1(Functor(), Str("1")) &lt;&lt; std::endl; // (1)
     std::cout &lt;&lt; f2(Functor(), Str("2")) &lt;&lt; std::endl; // (2)
}
</pre></blockquote>
<p>
Lets consider the function template <code>f1</code> (which is similar to
<code>std::reference_wrapper</code>'s function call operator). In the invocation
(1) <code>F</code> is deduced as '<code>Functor</code>' and <code>Types</code> is deduced as type sequence
which consists of one type '<code>std::string const</code>'. After the substitution
we have the following equivalent:
</p>
<blockquote><pre>
template &lt;&gt;
    std::result_of&lt;F (std::string const)&gt;::type
        f1&lt;Functor, std::string const&gt;(Functor f, std::string const &amp;&amp; params)
{
    return f(std::forward&lt;const std::string&gt;(params));
}
</pre></blockquote>
<p>
The top-level <i>cv</i>-qualifier in the parameter type of '<code>F (std::string const)</code>' is removed, so we have
</p>
<blockquote><pre>
template &lt;&gt;
    std::result_of&lt;F (std::string)&gt;::type
        f1&lt;Functor, std::string const&gt;(Functor f, std::string const &amp;&amp; params)
{
    return f(std::forward&lt;const std::string&gt;(params));
}
</pre></blockquote>
<p>
Let <code>r</code> be an rvalue of type '<code>std::string</code>' and <code>cr</code> be an rvalue of type
'<code>std::string const</code>'. The expression <code>Str("1")</code> is <code>cr</code>. The corresponding
return type for the invocation
</p>
<blockquote><pre>
Functor().operator()(r)
</pre></blockquote>
<p>
is '<code>std::string &amp;&amp;</code>'. The corresponding return type for the invocation
</p>
<blockquote><pre>
Functor().operator()(cr)
</pre></blockquote>
<p>
is '<code>std::string const &amp;&amp;</code>'.
<p/>
<code>std::result_of&lt;Functor (std::string)&gt;::type</code> is the same type as the
corresponding return type for the invocation <code>Functor().operator()(r)</code>,
i.e. it is '<code>std::string &amp;&amp;</code>'. As a consequence, we have wrong reference
binding in the return statement in <code>f1</code>.
<p/>
Now lets consider the invocation (2) of the function template <code>f2</code>. When
the template arguments are substituted we have the following equivalent:
</p>
<blockquote><pre>
template &lt;&gt;
    std::result_of&lt;F (std::string const &amp;&amp;)&gt;::type
        f2&lt;Functor, std::string const&gt;(Functor f, std::string const &amp;&amp; params)
{
    return f(std::forward&lt;const std::string&gt;(params));
}
</pre></blockquote>
<p>
<code>std::result_of&lt;F (std::string const &amp;&amp;)&gt;::type</code> is the same type as
'<code>std::string const &amp;&amp;</code>'. This is correct result.
</p>
<p><i>[
2010-12-07 Jonathan Wakely comments and suggests a proposed resolution
]</i></p>


<p>
I agree with the analysis and I think this is a defect in the
standard, it would be a shame if it can't be fixed.
<p/>
In the following example one would expect <code>f(Str("1"))</code> and
<code>std::ref(f)(Str("2"))</code> to be equivalent but the current wording makes
the invocation through <code>reference_wrapper</code> ill-formed:
</p>
<blockquote><pre>
#include &lt;functional&gt;
#include &lt;string&gt;

struct Functor
{
   template &lt;class T&gt;
       T&amp;&amp; operator()(T&amp;&amp; t) const
       {
           return static_cast&lt;T&amp;&amp;&gt;(t);
       }
};

int main()
{
   typedef std::string const Str;
   Functor f;
   f( Str("1") );
   std::ref(f)( Str("2") );  // error
}
</pre></blockquote>

<p><i>[
2010-12-07 Daniel comments and refines the proposed resolution
]</i></p>


<p>
There is one further defect in the usage of <code>result_of</code> within
<code>reference_wrapper</code>'s function call operator: According to 22.10.6.5 <a href="https://wg21.link/refwrap.invoke">[refwrap.invoke]</a> p. 1
the invokable entity of type <code>T</code> is provided as lvalue, but 
<code>result_of</code> is fed as if it were an rvalue. This does not only lead to
potentially incorrect result types, but it will also have the effect that
we could never use the function call operator with a function type,
because the type encoding used in <code>result_of</code> would form an invalid
function type return a function type. The following program demonstrates
this problem:
</p>
<blockquote><pre>
#include &lt;functional&gt;

void foo(int) {}

int main()
{
   std::ref(foo)(0);  // error
}
</pre></blockquote><p>
The correct solution is to ensure that <code>T</code> becomes <code>T&amp;</code>
within <code>result_of</code>, which solves both problems at once.
</p>

<p><i>[2011-02-24 Reflector discussion]</i></p>

<p>
Moved to Tentatively Ready after 5 votes.
</p> 


<p id="res-2017"><b>Proposed resolution:</b></p>
<ol>
<li>
<p>
Change the synopsis in 22.10.6 <a href="https://wg21.link/refwrap">[refwrap]</a> paragraph 1:
</p>

<blockquote><pre>
namespace std {
  template &lt;class T&gt; class reference_wrapper
  {
  public :
    [...]
    // invocation
    template &lt;class... ArgTypes&gt;
    typename result_of&lt;T<ins>&amp;</ins>(ArgTypes<ins>&amp;&amp;</ins>...)&gt;::type
    operator() (ArgTypes&amp;&amp;...) const;
  };
}
</pre></blockquote>
</li>

<li>
<p>
Change the signature in 22.10.6.5 <a href="https://wg21.link/refwrap.invoke">[refwrap.invoke]</a> before paragraph 1
</p>

<blockquote><pre>
template &lt;class... ArgTypes&gt;
typename result_of&lt;T<ins>&amp;</ins>(ArgTypes<ins>&amp;&amp;</ins>... )&gt;::type
operator()(ArgTypes&amp;&amp;... args) const;
</pre><blockquote><p>
1 <i>Returns</i>: <code>INVOKE(get(), std::forward&lt;ArgTypes&gt;(args)...)</code>. (20.8.2)
</p></blockquote></blockquote>
</li>
</ol>





</body>
</html>
