<!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=iso-8859-1">

<title>Bringing result_of near to INVOKE</title>

<style type="text/css">
  p {text-align:justify}
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  blockquote.note
  {
   background-color:#E0E0E0;
   padding-left: 15px;
   padding-right: 15px;
   padding-top: 1px;
   padding-bottom: 1px;
  }
</style>
</head><body>
<address style="text-align: left;">
Document number: N3123=10-0113<br>
Date: 2010-08-20<br>
Author: Daniel Kr&uuml;gler<br>
Project: Programming Language C++, Library Working Group<br>
Reply-to: <a href="mailto:daniel.kruegler@googlemail.com">Daniel Kr&uuml;gler</a><br>
</address>
<hr>
<h1 style="text-align: center;">Bringing <tt>result_of</tt> near to <tt>INVOKE</tt></h1>

<h2><a name="Introduction"></a>Introduction</h2>
<p>
Historically, the traits template	<tt>result_of</tt> was proposed as a library component that allows
to deduce the return type of function-call like expressions depending on types <tt>F</tt> and an argument type list expansion <tt>T...</tt>
compressed into a single-type form <tt>F(T...)</tt>, as presented in <a href= "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1437.html">n1437</a> 
and <a href= "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1454.html">n1454</a>. These papers used the picture of a 
general function call expression which we can express now - due to variadic templates and <tt>decltype</tt> - as the type of the 
following expression:
<p>
<a name="SingleForm">[A]</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<tt>std::declval&lt;F&gt;()(std::declval&lt;T&gt;()...)</tt>
<p>
While the intuitive definition via <tt>decltype</tt> (which was usually named <tt>typeof</tt> during those times) concentrated mainly
on above expression, from the first proposal on, <tt>result_of</tt> was suggested to support member function types as well and this
manifested in the TR1 specification that requires the deduction of the return type from pointers to member functions. Later, with
the acceptance of LWG issue <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#520">520</a>, the pointer-to-member
support was completed by taking the yet missing pointer to data members into account as well.
<p>
In parallel to this development, <a href= "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1673.html">n1673</a> and derivatives
introduced the concept of <em>callable types</em> and a conceptual macro named <tt>INVOKE</tt>, which is defined as a more general function call 
expression as specified above. 
<p>
A callable type is either a <em>function object type</em> (including pointers to functions) or a pointer to member.
<p>
<tt>INVOKE</tt> is defined in [func.require]/1 as a switch among five call expressions relating a type <tt>F</tt> and an argument type 
list exposed as a parameter pack <tt>T</tt> which might be expandable as <tt>T1, Tr...</tt> Using the power of <tt>decltype</tt> combined 
with <tt>std::declval()</tt> these expressions can be described as follows:
<blockquote class="note"><p>
<ol>
<li><pre>(std::declval&lt;T1&gt;().*std::declval&lt;F&gt;())(std::declval&lt;Tr&gt;()...)</pre>
	when <tt>F</tt> is a pointer to a member function of a class <tt>C</tt> and <tt>T1</tt> is of object type <tt>C</tt> or a reference 
	to an object type <tt>C</tt> or a reference to an object type derived from <tt>C</tt>;
</li>
<li><pre>((*std::declval&lt;T1&gt;()).*std::declval&lt;F&gt;())(std::declval&lt;Tr&gt;()...)</pre>
	when <tt>F</tt> is a pointer to a member function of a class <tt>C</tt> and <tt>T1</tt> is not one of the types described in the previous item;
</li>
<li><pre>std::declval&lt;T1&gt;().*std::declval&lt;F&gt;()</pre>
	when <tt>F</tt> is a pointer to member data of a class <tt>C</tt> and <tt>T1</tt> is an object type <tt>C</tt> or a reference to an object type 
	<tt>C</tt> or a reference to an object type derived from <tt>C</tt>;
</li>
<li><pre>(*std::declval&lt;T1&gt;()).*std::declval&lt;F&gt;()</pre>
	when <tt>F</tt> is a pointer to member data of a class <tt>C</tt> and <tt>T1</tt> is not one of the types described in the previous item;
</li>
<li><pre>std::declval&lt;F&gt;()(std::declval&lt;T&gt;()...)</pre>
	in all other cases.
</li>
</ol>
</blockquote>
<p>
At the time of the original specification, there did not exist a good way to define <tt>INVOKE</tt> as a real entity.
With the new language facilities of <tt>C++0x</tt> (including perfect forwarding) it is quite easy to declare a function template 
that covers all five function-call expression forms shown above as a single uniform signature
<p>
<blockquote><pre>
template&lt;class F, class... T&gt;
typename result_of&lt;F(T...)&gt;::type invoke(F&amp;&amp; f, T&amp;&amp;... t);
</pre></blockquote>
<p>
provided <tt>result_of&lt;F(T...)&gt;::type</tt> is defined in terms of a switch of the five expressions. Given these expressions
each of the five different return expressions - where the parameter expansion <tt>t...</tt> is occasionally expanded as <tt>t1, tr...</tt> - 
can be simply written (using the same constraints as described above) as:
<blockquote class="note"><p>
<ol>
<li><pre>(std::forward&lt;T1&gt;(t1).*std::forward&lt;F&gt;(f))(std::forward&lt;T&gt;(tr)...)</pre>
</li>
<li><pre>((*std::forward&lt;T1&gt;(t1)).*std::forward&lt;F&gt;(f))(std::forward&lt;T&gt;(tr)...)</pre>
</li>
<li><pre>std::forward&lt;T1&gt;(t1).*std::forward&lt;F&gt;(f)</pre>
</li>
<li><pre>(*std::forward&lt;T1&gt;(t1)).*std::forward&lt;F&gt;(f)</pre>
</li>
<li><pre>std::forward&lt;F&gt;(f)(std::forward&lt;T&gt;(t)...)</pre>
</li>
</ol>
</blockquote>
<p>
The function template <tt>invoke</tt> as defined above completely covers the functionality of the conceptual macro <tt>INVOKE</tt>,
while <tt>result_of&lt;F(T...)&gt;::type</tt> describes the return type of each valid <tt>INVOKE</tt> expression.
<p>
Unfortunately, the original support for pointers to members got lost, when several LWG issues (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#904">904</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#1225">1225</a>) found defects in the wording that mimiced
the <tt>decltype</tt> semantics and in the end replaced the previous specification (that properly honored pointers to member) by the 
reduced form <a href="#SingleForm">[A]</a>.
<p>
<h2><a name="Discussion"></a>Discussion</h2>
<p>
NB comment US 102 recommends to add the missing support for pointers to member functions and pointers to data members to
the type traits <tt>result_of</tt>. Indeed this addition is needed, because otherwise the specification of several library
components that mix <tt>INVOKE</tt> and <tt>result_of</tt> is incomplete, among those the specification of:
<p>
<ul>
<li><tt>reference_wrapper</tt> [refwrap]</li>
<li><tt>bind</tt> [func.bind.bind]</li>
<li><tt>async</tt> [futures.async]</li>
</ul>
<p>
The introductory text of this paper shows that such a specification can be easily accomplished by the five different call expressions 
that are already completely described as part of the existing specification of <tt>INVOKE</tt> in [func.require]/1. The author of this 
paper could realize <tt>INVOKE</tt> by implementing a function template <tt>invoke</tt> as shown above and could define 
<tt>result_of&lt;F(T...)&gt;::type</tt> of the required extended form without any problems. 
<p>
The function template <tt>invoke</tt> is generally useful and could replace the conceptual <tt>INVOKE</tt> macro, but this paper does 
not suggest to add such a new feature to the Standard Library as part of C++0x, because of the lateness in time. Nevertheless the author 
strongly recommends to add such a functionality in the next possible update of the <tt>C++</tt> Standard, because it
<p>
<ul>
<li>provides a uniform call syntax for <em>all</em> callable types</li>
<li>is non-trivial to implement</li>
<li>is a sufficient replacement of <tt>INVOKE</tt></li>
</ul>
<p>
<h2><a name="Proposed_resolution"></a>Proposed resolution</h2>
<p>
All wording changes are relative to N3092.
<p>
<ol>
<li>Change Table 53 &mdash; Other transformations in [meta.trans.other] as indicated:
<blockquote>
<table border="1">
<caption>Table 45 &mdash; Type relationship predicates</caption>

<tbody><tr>
<th>Template</th>
<th>Condition</th>
<th>Comments</th>
</tr>

<tr>
<td><tt>template &lt;class Fn,<br> 
class... ArgTypes&gt;<br>
struct result_of&lt;Fn(ArgTypes...)&gt;;</tt></td>
<td><tt>Fn</tt> shall be a <del>function object</del><ins>callable</ins> type (<del>20.8</del><ins>[func.def]</ins>),<br> 
reference to function, or reference to <del>function object</del><ins>callable</ins> type.<br>
The expression<br>
<del><tt>decltype(declval&lt;Fn&gt;()(declval&lt;ArgTypes&gt;()...))</tt></del><br>
<ins><tt>decltype(INVOKE(declval&lt;Fn&gt;(),<br>
declval&lt;ArgTypes&gt;()...))</tt></ins><br>
shall be well formed.</td>
<td>The member typedef <tt>type</tt> shall name the type<br>
<del><tt>decltype(declval&lt;Fn&gt;()<br>
(declval&lt;ArgTypes&gt;()...))</tt></del>
<ins><tt>decltype(INVOKE(declval&lt;Fn&gt;(),<br>
	declval&lt;ArgTypes&gt;()...))</tt></ins>
</td>
</tr>

</tbody></table>
</blockquote>
</li>
<li>Change the example in [meta.trans.other]/4 as indicated (For consistency with other examples the <tt>std::</tt>
	qualifier is suggested to be removed):
<blockquote><p>
[<em>Example</em>: Given these definitions:
<pre>
  typedef bool (&amp;PF1)();
  typedef short (*PF2)(long);

  struct S {
    operator PF2() const;
    double operator()(char, int&amp;);
    <ins>void fn(long) const;</ins>
    <ins>char data;</ins>
  };
  
  <ins>typedef void (S::*PMF)(long) const;</ins>
  <ins>typedef char S::*PMD;</ins>
</pre><p>
the following assertions will hold:
<pre>
  static_assert(<del>std::</del>is_same&lt;<del>std::</del>result_of&lt;S(int)&gt;::type, short&gt;::value, "Error!");
  static_assert(<del>std::</del>is_same&lt;<del>std::</del>result_of&lt;S&amp;(unsigned char, int&amp;)&gt;::type, double&gt;::value, "Error!");
  static_assert(<del>std::</del>is_same&lt;<del>std::</del>result_of&lt;PF1()&gt;::type, bool&gt;::value, "Error!");
  <ins>static_assert(is_same&lt;result_of&lt;PMF(unique_ptr&lt;S&gt;, int)&gt;::type, void&gt;::value, "Error!");</ins>
  <ins>static_assert(is_same&lt;result_of&lt;PMD(S)&gt;::type, char&amp;&amp;&gt;::value, "Error!");</ins>
  <ins>static_assert(is_same&lt;result_of&lt;PMD(const S*)&gt;::type, const char&amp;&gt;::value, "Error!");</ins>
</pre><p>
&mdash; <em>end example</em> ]
</blockquote>
</li>
</ol>
<p>
</p>
</body></html>
