<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2048: Unnecessary mem_fn overloads</title>
<meta property="og:title" content="Issue 2048: Unnecessary mem_fn overloads">
<meta property="og:description" content="C++ library issue. Status: C++14">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2048.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="2048"><a href="lwg-defects.html#2048">2048</a>. Unnecessary <code>mem_fn</code> overloads</h3>
<p><b>Section:</b> 22.10 <a href="https://wg21.link/function.objects">[function.objects]</a>, 22.10.16 <a href="https://wg21.link/func.memfn">[func.memfn]</a> <b>Status:</b> <a href="lwg-active.html#C++14">C++14</a>
 <b>Submitter:</b> Jonathan Wakely <b>Opened:</b> 2011-04-18 <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#function.objects">issues</a> in [function.objects].</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>
The <code>mem_fn</code> overloads for member functions are redundant and misleading
and should be removed from the post-C++11 WP.
<p/>
I believe the history of the overloads is as follows:
<p/>
In TR1 and in C++0x prior to the N2798 draft, <code>mem_fn</code> was specified by
a single signature:
</p>
<blockquote><pre>
template&lt;class R, class T&gt; <i>unspecified</i> mem_fn(R T::* pm);
</pre></blockquote>
<p>
and was accompanied by the remark "Implementations may implement <code>mem_fn</code> 
as a set of overloaded function templates." This remark predates variadic templates 
and was presumably to allow implementations to provide overloads for a limited 
number of function parameters, to meet the implementation-defined limit on numbers of
template parameters.
<p/>
N2770 "Concepts for the C++0x Standard Library: Utilities" added
separate overloads for pointers to member functions, apparently so
that function parameters would require the <code>CopyConstructible</code> concept
(those overloads first appeared in N2322.) The overloads failed to
account for varargs member functions (i.e. those declared with an
ellipsis in the parameter-declaration-clause) e.g.
</p>
<blockquote><pre>
struct S {
 int f(int, ...);
};
</pre></blockquote>
<p>
Syntactically such a function would be handled by the original
<code>mem_fn(R T::* pm)</code> signature, the only minor drawback being that there
would be no <code>CopyConstructible</code> requirement on the parameter list. (Core
DR 547 clarifies that partial specializations can be written to match
cv-qualified and ref-qualified functions to support the case where <code>R T::*</code> 
matches a pointer to member function type.)
<p/>
LWG issue <a href="lwg-defects.html#920" title="Ref-qualification support in the library (Status: C++11)">920</a><sup><a href="https://cplusplus.github.io/LWG/issue920" title="Latest snapshot">(i)</a></sup> pointed out that additional overloads were missing for
member functions with ref-qualifiers. These were not strictly
necessary, because such functions are covered by the <code>mem_fn(R T::* pm)</code> signature.
<p/>
Concepts were removed from the draft and N3000 restored the original
single signature and accompanying remark.
<p/>
LWG <a href="lwg-closed.html#1230" title="mem_fn and variadic templates (Status: Dup)">1230</a><sup><a href="https://cplusplus.github.io/LWG/issue1230" title="Latest snapshot">(i)</a></sup> was opened to strike the remark again and to add an overload
for member functions (this overload was unnecessary for syntactic reasons and 
insufficient as it didn't handle member functions with cv-qualifiers and&#47;or 
ref-qualifiers.)
<p/>
<a href="lwg-defects.html#920" title="Ref-qualification support in the library (Status: C++11)">920</a><sup><a href="https://cplusplus.github.io/LWG/issue920" title="Latest snapshot">(i)</a></sup> (and <a href="lwg-closed.html#1230" title="mem_fn and variadic templates (Status: Dup)">1230</a><sup><a href="https://cplusplus.github.io/LWG/issue1230" title="Latest snapshot">(i)</a></sup>) were resolved by restoring a full set of
(non-concept-enabled) overloads for member functions with cv-qualifiers and ref-qualifiers,
but as in the concept-enabled draft there were no overloads for member functions with 
an ellipsis in the parameter-declaration-clause. This is what is present in the FDIS.
<p/>
Following the thread beginning with message c++std-lib-30675, it is my
understanding that all the <code>mem_fn</code> overloads for member functions are
unnecessary and were only ever added to allow concept requirements.
I'm not aware of any reason implementations cannot implement <code>mem_fn</code> as
a single function template. Without concepts the overloads are
redundant, and the absence of overloads for varargs functions can be
interpreted to imply that varargs functions are not intended to work
with <code>mem_fn</code>. Clarifying the intent by adding overloads for varargs
functions would expand the list of 12 redundant overloads to 24, it
would be much simpler to remove the 12 redundant overloads entirely.
</p>

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

<p>
Move to Review.
</p>

<p>
The issue and resolution appear to be correct, but there is some concern that the wording of INVOKE may be different depending on whether you pass a pointer-to-member-data or pointer-to-member-function.  That might make the current wording necessary after all, and then we might need to add the missing elipsis overloads.
</p>

<p>
There was some concern that the Remark confirming implementors had freedom to implement this as a set of overloaded functions may need to be restored if we delete the specification for these overloads.
</p>

<p><i>[2012, Kona]</i></p>

<p>
Moved to Tentatively Ready by the post-Kona issues processing subgroup.
</p>

<p><i>[2012, Portland: applied to WP]</i></p>




<p id="res-2048"><b>Proposed resolution:</b></p>

<p>This wording is relative to the FDIS.</p>

<ol>
<li><p>Change the <code>&lt;functional&gt;</code> synopsis 22.10 <a href="https://wg21.link/function.objects">[function.objects]</a> p. 2 as follows:</p>

<blockquote><pre>
namespace std {
  [&hellip;]
  // <i>[func.memfn], member function adaptors:</i>
  template&lt;class R, class T&gt; <i>unspecified</i> mem_fn(R T::*);
<del>  template&lt;class R, class T, class... Args&gt;
  <i>unspecified</i> mem_fn(R (T::*)(Args...));
  template&lt;class R, class T, class... Args&gt;
  <i>unspecified</i> mem_fn(R (T::*)(Args...) const);
  template&lt;class R, class T, class... Args&gt;
  <i>unspecified</i> mem_fn(R (T::*)(Args...) volatile);
  template&lt;class R, class T, class... Args&gt;
  <i>unspecified</i> mem_fn(R (T::*)(Args...) const volatile);
  template&lt;class R, class T, class... Args&gt;
  <i>unspecified</i> mem_fn(R (T::*)(Args...) &amp;);
  template&lt;class R, class T, class... Args&gt;
  <i>unspecified</i> mem_fn(R (T::*)(Args...) const &amp;);
  template&lt;class R, class T, class... Args&gt;
  <i>unspecified</i> mem_fn(R (T::*)(Args...) volatile &amp;);
  template&lt;class R, class T, class... Args&gt;
  <i>unspecified</i> mem_fn(R (T::*)(Args...) const volatile &amp;);
  template&lt;class R, class T, class... Args&gt;
  <i>unspecified</i> mem_fn(R (T::*)(Args...) &amp;&amp;);
  template&lt;class R, class T, class... Args&gt;
  <i>unspecified</i> mem_fn(R (T::*)(Args...) const &amp;&amp;);
  template&lt;class R, class T, class... Args&gt;
  <i>unspecified</i> mem_fn(R (T::*)(Args...) volatile &amp;&amp;);
  template&lt;class R, class T, class... Args&gt;
  <i>unspecified</i> mem_fn(R (T::*)(Args...) const volatile &amp;&amp;);</del>

  [&hellip;]
}
</pre></blockquote>
</li>

<li><p>Change 22.10.16 <a href="https://wg21.link/func.memfn">[func.memfn]</a> as follows:</p>

<blockquote><pre>
template&lt;class R, class T&gt; <i>unspecified</i> mem_fn(R T::*);
<del>template&lt;class R, class T, class... Args&gt;
<i>unspecified</i> mem_fn(R (T::*)(Args...));
template&lt;class R, class T, class... Args&gt;
<i>unspecified</i> mem_fn(R (T::*)(Args...) const);
template&lt;class R, class T, class... Args&gt;
<i>unspecified</i> mem_fn(R (T::*)(Args...) volatile);
template&lt;class R, class T, class... Args&gt;
<i>unspecified</i> mem_fn(R (T::*)(Args...) const volatile);
template&lt;class R, class T, class... Args&gt;
<i>unspecified</i> mem_fn(R (T::*)(Args...) &amp;);
template&lt;class R, class T, class... Args&gt;
<i>unspecified</i> mem_fn(R (T::*)(Args...) const &amp;);
template&lt;class R, class T, class... Args&gt;
<i>unspecified</i> mem_fn(R (T::*)(Args...) volatile &amp;);
template&lt;class R, class T, class... Args&gt;
<i>unspecified</i> mem_fn(R (T::*)(Args...) const volatile &amp;);
template&lt;class R, class T, class... Args&gt;
<i>unspecified</i> mem_fn(R (T::*)(Args...) &amp;&amp;);
template&lt;class R, class T, class... Args&gt;
<i>unspecified</i> mem_fn(R (T::*)(Args...) const &amp;&amp;);
template&lt;class R, class T, class... Args&gt;
<i>unspecified</i> mem_fn(R (T::*)(Args...) volatile &amp;&amp;);
template&lt;class R, class T, class... Args&gt;
<i>unspecified</i> mem_fn(R (T::*)(Args...) const volatile &amp;&amp;);</del>
</pre></blockquote>
</li>

</ol>






</body>
</html>
