<html>
	<head>
		<title>A Proposal to Add an Enhanced Member Pointer Adaptor to the Library 
			Technical Report</title>
		<meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
		<meta http-equiv="Content-Language" content="en-us">
		<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
	</head>
	<body bgColor="#ffffff">
		<ADDRESS>Document number: N1432=03-0014</ADDRESS>
		<ADDRESS>Programming Language C++, Library Subgroup</ADDRESS>
		<ADDRESS>&nbsp;</ADDRESS>
		<ADDRESS>Peter Dimov &lt;<A href="mailto:pdimov@mmltd.net">pdimov@mmltd.net</A>&gt;</ADDRESS>
		<ADDRESS>&nbsp;</ADDRESS>
		<ADDRESS>February 28, 2003</ADDRESS>
		<h1>A Proposal to Add an Enhanced Member Pointer Adaptor to the Library Technical 
			Report</h1>
		<h2>I. Motivation</h2>
		<p>The canonical solution for storing polymorphic objects in standard library 
			containers is to use a smart pointer such as <code>shared_ptr</code> [<A href="#Dimov03a">Dimov03a</A>]. 
			Unfortunately, the standard adaptors for pointers to members described in 
			section 20.3.8 do not support smart pointers.</p>
		<P>This document proposes an enhanced member pointer adaptor, <code>mem_fn</code>, 
			that</P>
		<UL>
			<LI>
				Is a generalization of the standard adaptors <code>std::mem_fun</code> and <code>std::mem_fun_ref;</code>
			<LI>
			Supports pointers to member functions with an arbitrary number of arguments 
			(subject to implementation-imposed constraints) and pointers to data members;
			<LI>
			Returns a function object accepting a reference, a pointer, a smart pointer, or 
			an iterator as its first argument;
			<LI>
			Can be reused by standard or user-defined components to provide transparent 
			pointer to member support;
			<LI>
				Reflects existing practice [<A href="#Boost01">Boost01</A>].</LI></UL>
		<P><code>mem_fn</code> supports the familiar idiom for invoking a member function 
			on all container elements:</P>
		<PRE>    std::for_each(v.begin(), v.end(), mem_fn(&amp;Shape::draw));</PRE>
		<P>The statement works for a container that stores objects, pointers, smart 
			pointers, or iterators.</P>
		<P>This flexibility allows components that accept function objects as input to 
			offer transparent support for pointers to members by using <code>mem_fn</code> internally 
			to turn the pointer to member into a function object [<A href="#Dimov03b">Dimov03b</A>]. 
			As an example, consider this hypothetical <code>for_each</code> overload:</P>
		<PRE>template&lt;class It, class R, class T&gt; void for_each(It first, It last, R T::* pm)
{
    std::for_each(first, last, mem_fn(pm));
}
</PRE>
		<P>Scott Meyers remarks in [<A href="#Meyers01">Meyers01</A>] that</P>
		<blockquote>
			<p>In a perfect world, I'd also be able to use <code>for_each</code> to invoke <code>Widget::test</code>
				on each object in <code>vw</code>:</p>
			<pre>
for_each(vw.begin(), vw.end(), &amp;Widget::test);    // Call #2 <EM>(won't compile)</EM>
</pre>
			<p>In fact, if the world were really perfect, I'd be able to use <code>for_each</code>
				to invoke <code>Widget::test</code> on a container of <code>Widget*</code> pointers, 
				too:</p>
			<pre>
list&lt;Widget*&gt; lpw; // lpw holds pointers to widgets
for_each(lpw.begin(), lpw.end(), &amp;Widget::test);  // Call #3 <EM>(also won't compile)</EM>
</pre>
		</blockquote>
		<P>This is exactly the functionality offered by the above <code>for_each</code> overload.</P>
		<P>The hypothetical proposed text for our enhanced <code>for_each</code> can reuse 
			the <code>mem_fn</code> specification as well:</P>
		<blockquote>
			<pre>template&lt;class It, class R, class T&gt; void for_each(It first, It last, R T::* pm);</pre>
			<P><B>Effects:</B> equivalent to <code>std::for_each(first, last, mem_fn(pm));</code></P>
		</blockquote>
		<h2>II. Impact On the Standard</h2>
		<p>This proposal is almost a pure library extension. It proposes changes to an 
			existing header, <code>&lt;functional&gt;</code>, but it does not require 
			changes to any standard classes or functions and it does not require changes to 
			any of the standard requirement tables. It does not require any changes in the 
			core language, and it has been implemented in standard C++ [<A href="#Boost01">Boost01</A>]. 
			The proposal does not depend on any other library extensions.
		</p>
		<h2>III. Design Decisions</h2>
		<h3>A. Separate Function Template vs <code>std::mem_fun</code> Extension</h3>
		<p>This proposal introduces a new function template <code>mem_fn</code> and does 
			not propose changes to the existing function template <code>std::mem_fun</code> 
			in order to not impact existing code, as the return type of <code>std::mem_fun</code>
			is specified by the standard.</p>
		<h3>B. Unified Handling of Pointers and References</h3>
		<p>The function objects returned by <code>mem_fn</code> can take either an object 
			pointer or an object reference as its first argument. This allows components 
			that automatically recognize pointers to members, transparently wrapping them 
			with <code>mem_fn</code>, to accept pointers and references. As the wrapping is 
			done implicitly, the user has no way to specify one or the other.</p>
		<h3>C. Unspecified Return Type</h3>
		<p>The return type of <code>mem_fn</code> is not specified by this proposal, as it 
			is rarely needed, and can reflect implementation details. The Boost 
			implementation does not specify the return type of <code>mem_fn</code>, and 
			there have been no complaints from users.</p>
		<h3>D. <code>get_pointer(t)-&gt;*pm</code> vs ( <code>*t).*pm</code></h3>
		<p>When the argument is not an object reference, the Boost implementation uses an 
			unqualified call to <code>get_pointer</code> to obtain a pointer from the 
			argument, and the <code>-&gt;*</code> operator to perform the call. This 
			proposal dereferences the argument instead, using the <code>.*</code> operator 
			for the call. This allows <code>mem_fn</code> to support most smart pointers 
			and iterators "out of the box", without requiring explicit support in the form 
			of a <code>get_pointer</code> overload.</p>
		<h3>E. <code>result_type</code> for data members</h3>
		<p>The return type of <code>mem_fn(&amp;X::f)</code>, where <code>f</code> is a 
			member function of <code>X</code>, is always the same as the return type of <code>f</code>. 
			The return type of <code>mem_fn(&amp;X::m)</code>, where <code>m</code> is a 
			data member of <code>X</code> of type <code>M</code>, can vary depending on <code>M</code>
			and the cv-qualification of the object identified by the first argument of the 
			call. When <code>M</code> is a reference type, the return type is <code>M</code>; 
			otherwise, the return type is a reference to (possibly cv-qualified) <code>M</code>.</p>
		<P>In this proposal, implementations are allowed to define the <code>result_type</code>
			of the function object returned by <CODE>mem_fn(&amp;X::m)</CODE> as either <code>M</code>
			or <code>M const &amp;</code>. It is not possible to express the exact return 
			type in a single typedef, and neither <code>M</code> nor <code>M const &amp;</code>
			is inherently a better choice.</P>
		<h2>IV. Proposed Text</h2>
		<h3>A. Additions to header &lt;functional&gt; synopsis (20.3)</h3>
		<pre>  template&lt;class R, class T&gt; <em>unspecified</em> mem_fn(R T::* pm);
</pre>
		<h3>B. mem_fn</h3>
		<p><code>mem_fn(&amp;X::f)</code>, where <code>f</code> is a member function of <code>X</code>, 
			returns an object through which <code>&amp;X::f</code> can be called given a 
			pointer, a smart pointer, an iterator, or a reference to <code>X</code> followed 
			by the argument list required for <code>X::f</code>, if any. The returned 
			object is <code>CopyConstructible</code>, <code>Assignable</code>, its copy 
			constructor and assignment operator do not throw exceptions, and it has a 
			nested typedef <code>result_type</code> defined as the return type of <code>
				f</code>.</p>
		<p><code>mem_fn(&amp;X::m)</code>, where <code>m</code> is a data member of <code>X</code>, 
			returns an object through which a reference to <code>&amp;X::m</code> can be 
			obtained given a pointer, a smart pointer, an iterator, or a reference to <code>X</code>. 
			The returned object is <code>CopyConstructible</code>, <code>Assignable</code>, 
			its copy constructor and assignment operator do not throw exceptions, and it 
			has a nested typedef <code>result_type</code> defined as either <code>M</code>
			or <code>M const &amp;</code> where <code>M</code> is the type of <code>m</code>.</p>
		<pre>      template&lt;class R, class T&gt; <em>unspecified</em> mem_fn(R T::* pm);
</pre>
		<p><b>Returns:</b></p>
		<UL>
			<LI>
				When <code>pm</code> is a pointer to a member function taking <code>n</code> arguments, 
				a function object <code>f</code> such that the expression <code>f(t, a<SUB>1</SUB>, 
					..., a<SUB>n</SUB>)</code> is equivalent to <code>(t.*pm)(a<SUB>1</SUB>, ..., a<SUB>n</SUB>)</code>
				when <code>t</code> is an lvalue of type <code>T</code> or derived from <code>T</code>,
				<code>((*t).*pm)(a<SUB>1</SUB>, ..., a<SUB>n</SUB>)</code>
			otherwise.
			<LI>
				When <code>pm</code> is a pointer to a data member, a function object <code>f</code>
				such that the expression <code>f(t)</code> is equivalent to <code>t.*pm</code> when
				<code>t</code> is an lvalue of type <code>T</code> or derived from <code>T</code>,
				<code>(*t).*pm</code> otherwise.</LI></UL>
		<p><b>Throws:</b> nothing.</p>
		<p><b>Notes:</b> Implementations are allowed to impose an upper limit on <code>n</code>. 
			Implementations are allowed to implement <code>mem_fn</code> as a set of 
			overloaded function templates.</p>
		<h2>V. References</h2>
		<p>[<a name="Boost01">Boost01</a>] Boost mem_fn library documentation, September 
			2001. Available online at <a href="http://www.boost.org/libs/mem_fn/">http://www.boost.org/libs/mem_fn/</a></p>
		<p>[<a name="Dimov03a">Dimov03a</a>] Peter Dimov, Beman Dawes, Greg Colvin, <i>A 
				Proposal to Add General Purpose Smart Pointers to the Library Technical Report</i>, 
			C++ committee document N1431=03-0013, February 2003. Available online at <a href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1431.htm">
				http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1431.htm</a></p>
		<p>[<a name="Dimov03b">Dimov03b</a>] Peter Dimov, Douglas Gregor, Jaakko Jrvi, 
			Gary Powell, <i>A Proposal to Add an Enhanced Binder to the Library Technical 
				Report</i>, C++ committee document N1438=03-0020, February 2003. Available 
			online at <a href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1438.htm">http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1438.htm</a></p>
		<p>[<a name="Meyers01">Meyers01</a>] Scott Meyers, <i><a href="http://www.awl.com/cseng/titles/0-201-74962-9/">
					Effective STL</a></i>, Item 41, page 174, Addison-Wesley, June 2001, 
			ISBN 0-201-74962-9.</p>
		<p>&nbsp;</p>
	</body>
</html>
