<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
	<head>
		<title>The Forwarding Problem: Arguments</title>
		<meta content="Microsoft Visual Studio.NET 7.0" name="GENERATOR">
		<meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
	</head>
	<body>
		<ADDRESS>Document number: N1385=02-0043</ADDRESS>
		<ADDRESS>Programming Language C++</ADDRESS>
		<ADDRESS>&nbsp;</ADDRESS>
		<ADDRESS>Peter Dimov, <A href="mailto:pdimov@mmltd.net">pdimov@mmltd.net</A></ADDRESS>
		<ADDRESS>Howard E. Hinnant, <A href="mailto:hinnant@twcny.rr.com">hinnant@twcny.rr.com</A></ADDRESS>
		<ADDRESS>Dave Abrahams, <A href="mailto:dave@boost-consulting.com">dave@boost-consulting.com</A></ADDRESS>
		<ADDRESS>&nbsp;</ADDRESS>
		<ADDRESS>September 09, 2002</ADDRESS>
		<H1>The Forwarding Problem: Arguments</H1>
		<H2>Problem Statement</H2>
		<P>The general form of the <STRONG>forwarding problem</STRONG> is that in the 
			current language,</P>
		<P><EM>For a given expression <STRONG>E(a<SUB>1</SUB>, a<SUB>2</SUB>, ..., a<SUB>n</SUB>)</STRONG>
				that depends on the (generic) parameters <STRONG>a<SUB>1</SUB></STRONG>, <STRONG>a<SUB>2</SUB></STRONG>, 
				..., <STRONG>a<SUB>n</SUB></STRONG>, it is not possible to write a function 
				(object) <STRONG>f</STRONG> such that <STRONG>f(a<SUB>1</SUB>, a<SUB>2</SUB>, ..., 
					a<SUB>n</SUB>)</STRONG> is equivalent to <STRONG>E(a<SUB>1</SUB>, a<SUB>2</SUB>, 
					..., a<SUB>n</SUB>)</STRONG>.</EM></P>
		<P>The problem has two sides: first, <STRONG>f</STRONG> must be able to accept an 
			arbitrary argument list and forward it to <STRONG>E</STRONG> (relatively) 
			unmodified, so that the meaning of <STRONG>E</STRONG> does not change as a 
			result, and second, <STRONG>f</STRONG> must be able to return the result of <STRONG>
				E</STRONG> back to its caller.</P>
		<P>This paper concentrates on the first aspect, argument forwarding.</P>
		<H2>Motivating Examples</H2>
		<H3>Generic wrapper classes</H3>
		<P>It is sometimes necessary to wrap an instance of an arbitrary type <STRONG>T</STRONG>
			in a wrapper class, as shown:</P>
		<PRE>template&lt;class T&gt; class wrapper: public wrapper_base
{
private:

    T t_;

public:

    // forwarding constructors

    wrapper(): t_() {}
    wrapper(<EM><STRONG>a<SUB>1</SUB></STRONG></EM>): t_(<EM><STRONG>a<SUB>1</SUB></STRONG></EM>) {}
    wrapper(<EM><STRONG>a<SUB>1</SUB></STRONG></EM>, <EM><STRONG>a<SUB>2</SUB></STRONG></EM>): t_(<EM><STRONG>a<SUB>1</SUB></STRONG></EM>, <EM><STRONG>a<SUB>2</SUB></STRONG></EM>) {}
    // ...

};</PRE>
		<P>The goal might be, for example, to treat the wrapped instances polymorphically 
			through <STRONG>wrapper_base</STRONG>.</P>
		<P>It is clear that the constructors of <STRONG>wrapper</STRONG> need to forward an 
			arbitrary list of arguments to <STRONG>T</STRONG>'s constructor.</P>
		<P>The <STRONG>Boost.Python</STRONG> library <A href="#r5">[5]</A> uses this 
			technique.</P>
		<H3>Generic factory functions</H3>
		<P>The expression <STRONG>new T(a<SUB>1</SUB>, a<SUB>2</SUB>, ..., a<SUB>n</SUB>)</STRONG>
			returns a plain pointer of type <STRONG>T*</STRONG>. This is a common source of 
			resource leaks, especially in the presence of exceptions, so the usual advice 
			is to use factory functions returning a smart pointer. Writing class-specific 
			factory functions quickly becomes tedious, and the solution is to employ a 
			generic factory function that mirrors the semantics of <STRONG>new T(a<SUB>1</SUB>, 
				a<SUB>2</SUB>, ..., a<SUB>n</SUB>)</STRONG> but returns a smart pointer, <STRONG>
				std::auto_ptr</STRONG> for example:</P>
		<PRE>template&lt;class T&gt; std::auto_ptr&lt;T&gt; auto_new()
{
    return std::auto_ptr&lt;T&gt;(new T());
}

template&lt;class T&gt; std::auto_ptr&lt;T&gt; auto_new(<EM><STRONG>a<SUB>1</SUB></STRONG></EM>)
{
    return std::auto_ptr&lt;T&gt;(new T(<EM><STRONG>a<SUB>1</SUB></STRONG></EM>));
}

template&lt;class T&gt; std::auto_ptr&lt;T&gt; auto_new(<EM><STRONG>a<SUB>1</SUB></STRONG></EM>, <EM><STRONG>a<SUB>2</SUB></STRONG></EM>)
{
    return std::auto_ptr&lt;T&gt;(new T(<EM><STRONG>a<SUB>1</SUB></STRONG></EM>, <EM><STRONG>a<SUB>2</SUB></STRONG></EM>));
}

// ...
</PRE>
		<P>Client code now uses <STRONG>auto_new&lt;T&gt;(a<SUB>1</SUB>, a<SUB>2</SUB>, ..., a<SUB>n</SUB>)</STRONG>
			to defend against resource leaks. Again, the need to forward an arbitrary 
			argument list to <STRONG>T</STRONG>'s constructor is obvious from the example 
			code.</P>
		<H3>Boost.Bind</H3>
		<P>The <STRONG>Boost.Bind</STRONG> library <A href="#r1">[1]</A>, a generalization 
			of the standard binders, is able to take a function object as an argument, and 
			create a derivative function object that calls the original. For example, the 
			expression <STRONG>boost::bind(f, _2, _1)</STRONG> creates a function object <STRONG>
				g</STRONG> such that <STRONG>g(x, y)</STRONG> invokes <STRONG>f(y, x)</STRONG>, 
			and the expression <STRONG>boost::bind(f, 1, _1)</STRONG> creates a function 
			object <STRONG>h</STRONG> such that <STRONG>h(x)</STRONG> invokes <STRONG>f(1, x)</STRONG>.</P>
		<P>The ability to forward arguments from the function object generated by <STRONG>boost::bind</STRONG>
			to the original function object is essential for the library to operate.</P>
		<H3>Boost.Lambda</H3>
		<P><STRONG>Boost.Lambda</STRONG> <A href="#r2">[2]</A>, a superset of <STRONG>Boost.Bind</STRONG>, 
			is an even more elaborate "function object factory". As such, it encounters the 
			same problem.</P>
		<P>As an example, the <STRONG>Boost.Lambda</STRONG> expression <STRONG>_1 &lt;&lt; _2</STRONG>
			generates a function object <STRONG>f</STRONG> such that <STRONG>f(x, y)</STRONG>
			is equivalent to <STRONG>x &lt;&lt; y</STRONG>. Note that the first argument 
			can be the integral constant <STRONG>5</STRONG>, or it can be <STRONG>std::cout</STRONG>.</P>
		<H2>Criteria for Evaluating Solutions</H2>
		<P>Assuming a forwarding function <STRONG>f(a<SUB>1</SUB>, a<SUB>2</SUB>, ..., a<SUB>n</SUB>)</STRONG>
			that calls <STRONG>g(a<SUB>1</SUB>, a<SUB>2</SUB>, ..., a<SUB>n</SUB>)</STRONG>, 
			a general solution must have the following three properties:</P>
		<UL>
			<LI>
				<STRONG><a name="c1">(C1)</a></STRONG> Most (preferably all) valid <STRONG><STRONG>g(a<SUB>1</SUB>, 
						a<SUB>2</SUB>, ..., a<SUB>n</SUB>)</STRONG></STRONG> uses must be valid 
				uses of <STRONG>f(a<SUB>1</SUB>, a<SUB>2</SUB>, ..., a<SUB>n</SUB>)</STRONG>, 
			too.
			<LI>
				<STRONG><a name="c2">(C2)</a></STRONG> Most invalid <STRONG><STRONG>g(a<SUB>1</SUB>, a<SUB>2</SUB>, 
						..., a<SUB>n</SUB>)</STRONG></STRONG> uses should not be valid uses of <STRONG>
					f(a<SUB>1</SUB>, a<SUB>2</SUB>, ..., a<SUB>n</SUB>)</STRONG>; valid uses of <STRONG>
					f</STRONG> that aren't valid uses of <STRONG>g</STRONG>
			should not invoke undefined behavior.
			<LI>
				<STRONG><a name="c3">(C3)</a></STRONG> The amount of work necessary to 
				implement <STRONG>f</STRONG> should scale (at most) linearly with <STRONG>n</STRONG>.</LI></UL>
		<H2>Current Solutions</H2>
		<P>This section presents some of the (partial) solutions to the problem within the 
			current language semantics. The examples used to illustrate the methods assume 
			that we need to write a forwarding function <STRONG>f(a<SUB>1</SUB>, a<SUB>2</SUB>, 
				a<SUB>3</SUB>)</STRONG> that calls <STRONG>g(a<SUB>1</SUB>, a<SUB>2</SUB>, a<SUB>3</SUB>)</STRONG>.</P>
		<H3><a name="s1">#1:</a> Non-const reference</H3>
		<P>This is the method currently employed by <STRONG>Boost.Bind</STRONG> and <STRONG>Boost.Lambda</STRONG>:</P>
		<pre>template&lt;class A1, class A2, class A3&gt; void f(A1 &amp; a1, A2 &amp; a2, A3 &amp; a3)
{
    return g(a1, a2, a3);
}
</pre>
		<P>Its main deficiency is that it cannot forward a non-const rvalue. The argument 
			deduction creates a non-const reference, and the reference cannot bind to the 
			argument. This makes innocent examples as</P>
		<pre>int main()
{
    f(1, 2, 3);
}
</pre>
		<P>fail (violates <A href="#c1">C1</A>).</P>
		<P>As function objects typically take their arguments by dereferencing iterators, 
			this approach works relatively well for <STRONG>Bind</STRONG> and <STRONG>Lambda</STRONG>; 
			still, it is not a general solution, and some real-world iterators return an 
			rvalue when derefenced (the <STRONG>Boost.Graph</STRONG> library <A href="#r3">[3]</A>
			has such iterators, and the incompatibility between <STRONG>Bind</STRONG> and <STRONG>
				Graph</STRONG> has been reported as a problem in real code).</P>
		<H3><a name="s2">#2:</a> Const reference</H3>
		<P>The problem with non-const rvalues can be solved by forwarding by const 
			reference:</P>
		<pre>template&lt;class A1, class A2, class A3&gt; void f(A1 const &amp; a1, A2 const &amp; a2, A3 const &amp; a3)
{
    return g(a1, a2, a3);
}
</pre>
		<P>This method accepts and forwards arbitrary arguments, at the cost of always 
			treating the argument as const. It is clear that this is not a general 
			solution; when <STRONG>g</STRONG> accepts some of its arguments by a non-const 
			reference, the forwarding will fail (violates <A href="#c1">C1</A> ). As an 
			example consider the <STRONG>Lambda</STRONG> function object <STRONG>_1 &lt;&lt; _2</STRONG>
			mentioned above, when its first argument is <STRONG>std::cout</STRONG>.</P>
		<P>This solution is typically used for constructor arguments; even then, some 
			constructors take arguments by non-const reference.</P>
		<P>An esoteric problem with this approach is that it is not possible to form a 
			const reference to a function type, but this will be addressed by Core Issue <A href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#295">
				295</A>.</P>
		<H3><a name="s3">#3:</a> Const + Non-const reference</H3>
		<P>For single argument forwarders, it is possible to use a combined approach, 
			providing both overloads:</P>
		<pre>template&lt;class A1&gt; void f(A1 &amp; a1)
{
    return g(a1);
}

template&lt;class A1&gt; void f(A1 const &amp; a1)
{
    return g(a1);
}
</pre>
		<P>Compilers have had their disagreements about this overloading example for some 
			time, sometimes claiming ambiguity, but the latest generation seems to have 
			reached a consensus that the second template is more specialized than the first 
			according to the partial ordering rules. Unfortunately, the much bigger issue 
			with this approach is that the <STRONG>N</STRONG>-argument case would require <STRONG>
				2<SUP>N</SUP></STRONG> overloads, immediately discounting this as a general 
			solution (violates <A href="#c3">C3</A>). Our three-argument case is shown 
			below.</P>
		<pre>template&lt;class A1, class A2, class A3&gt; void f(A1 const &amp; a1, A2 const &amp; a2, A3 const &amp; a3)
{
    return g(a1, a2, a3);
}

template&lt;class A1, class A2, class A3&gt; void f(A1 &amp; a1, A2 const &amp; a2, A3 const &amp; a3)
{
    return g(a1, a2, a3);
}

template&lt;class A1, class A2, class A3&gt; void f(A1 const &amp; a1, A2 &amp; a2, A3 const &amp; a3)
{
    return g(a1, a2, a3);
}

template&lt;class A1, class A2, class A3&gt; void f(A1 &amp; a1, A2 &amp; a2, A3 const &amp; a3)
{
    return g(a1, a2, a3);
}

template&lt;class A1, class A2, class A3&gt; void f(A1 const &amp; a1, A2 const &amp; a2, A3 &amp; a3)
{
    return g(a1, a2, a3);
}

template&lt;class A1, class A2, class A3&gt; void f(A1 &amp; a1, A2 const &amp; a2, A3 &amp; a3)
{
    return g(a1, a2, a3);
}

template&lt;class A1, class A2, class A3&gt; void f(A1 const &amp; a1, A2 &amp; a2, A3 &amp; a3)
{
    return g(a1, a2, a3);
}

template&lt;class A1, class A2, class A3&gt; void f(A1 &amp; a1, A2 &amp; a2, A3 &amp; a3)
{
    return g(a1, a2, a3);
}
</pre>
		<H3><a name="s4">#4:</a> Const reference + const_cast</H3>
		<P>Another attempt to combine the good aspects of the two approaches is for <STRONG>f</STRONG>
			to take arguments by const reference, but pass them to <STRONG>g</STRONG> as 
			non-const using <STRONG>const_cast</STRONG>:</P>
		<pre>template&lt;class A1, class A2, class A3&gt; void f(A1 const &amp; a1, A2 const &amp; a2, A3 const &amp; a3)
{
    return g(const_cast&lt;A1 &amp;&gt;(a1), const_cast&lt;A2 &amp;&gt;(a2), const_cast&lt;A3 &amp;&gt;(a3));
}
</pre>
		<P>This method allows all valid <STRONG>g(a<SUB>1</SUB>, a<SUB>2</SUB>, a<SUB>3</SUB>)</STRONG>
			uses to work through <STRONG>f</STRONG>, too. Unfortunately, due to the way it 
			discards the argument constness, it allows many <STRONG>invalid</STRONG> uses 
			to work as well. For example, it allows a function <STRONG>g</STRONG> that 
			takes a non-const reference to operate on const l- and rvalues, potentially 
			attempting to modify them, invoking undefined behavior - a serious violation of <A href="#c2">
				C2</A>.</P>
		<P><STRONG>Boost.Lambda</STRONG> allows this as an option.</P>
		<P>In our opinion, the fact that library writers have to resort to such measures is 
			an indication that the problem needs to be taken seriously.</P>
		<H2>Future Solutions</H2>
		<P>The main problem of the current "non-const reference" forwarding method is that 
			non-const rvalues cannot bind to the deduced non-const reference. There are two 
			possible language changes that can fix that: either make the reference bind to 
			the argument, or deduce a const reference. This section enumerates the 
			solutions that take advantage of these changes.</P>
		<H3><a name="s5">#5:</a> Non-const reference + modified argument deduction</H3>
		<P>With a relatively small change to 14.8.2.1, it is possible to make <STRONG>A1</STRONG>
			in the following snippet:</P>
		<pre>template&lt;class A1&gt; void f(A1 &amp; a1)
{
}

int main()
{
    f(5);
}
</pre>
		<P>to be deduced as <STRONG>int const</STRONG>, and not plain <STRONG>int</STRONG>. 
			As a side effect, solution <A href="#s1">#1</A> now will (const-correctly) work 
			for all argument types.</P>
		<P>The upside of this approach are that it requires a small, isolated language 
			change, that is relatively independent of the rest of the language, including 
			the move proposal <A href="#r4">[4]</A>.</P>
		<P>One downside is that the change breaks existing code:</P>
		<pre>template&lt;class A1&gt; void f(A1 &amp; a1)
{
    std::cout &lt;&lt; 1 &lt;&lt; std::endl;
}

void f(long const &amp;)
{
    std::cout &lt;&lt; 2 &lt;&lt; std::endl;
}

int main()
{
    f(5);              // prints 2 under the current rules, 1 after the change
    int const n(5);
    f(n);              // 1 in both cases
}
</pre>
		<P>It is difficult to evaluate the impact of the proposed change. Overload sets 
			that rely on the fact that <STRONG>A1 &amp;</STRONG> will not bind to non-const 
			rvalues are too fragile to be useful, as any other input is accepted. One might 
			argue that the example code is already broken - the overload set <STRONG>f</STRONG>
			has different behavior for the literal <STRONG>5</STRONG> and for the constant <STRONG>
				n</STRONG>, and it is considered good programming style to avoid using 
			unnamed literals as "magic constants". (Microsoft Visual C++ 6.0, a widely used 
			compiler, actually prints <STRONG>1</STRONG> in response to the <STRONG>f(5)</STRONG>
			call, since literals are considered const-qualified.)</P>
		<P>On the other hand, it is possible to accidentally create such an overload set in 
			a program; combined with a proxy-based container, this leads to the following 
			example:</P>
		<pre>// helper function in a header

template&lt;class T&gt; void something(T &amp; t) // #1
{
    t.something();
}

// source

#include &lt;vector&gt;

void something(bool) // #2
{
}

int main()
{
    std::vector&lt;bool&gt; v(5);
    something(v[0]); // resolves to #2 under the current rules, #1 after the change
}
</pre>
		<P>that we consider dangerously close to being typical. Do not be distracted by the 
			side question of whether <STRONG>vector&lt;bool&gt;</STRONG> is a <STRONG>std::vector</STRONG>, 
			or a standard container at all. <STRONG>vector&lt;bool&gt;</STRONG> is just a 
			well-known example that uses proxy references for lazy evaluation, a technique 
			that is being used in real world C++ code.</P>
		<P>This kind of conflict can arise whenever a deduced non-const reference is used 
			as an argument, a construct that is more widespread than most people think. As 
			an example taken from the standard library, consider <STRONG>std::advance</STRONG>:</P>
		<pre>template&lt;class InputIterator, class DistanceType&gt; void advance(InputIterator &amp; it, DistanceType dist);</pre>
		<P>Another downside is that rvalues are forwarded as lvalues (a common trait of all 
			presented solutions except <A href="#s7">#7</A>). In the current language this 
			is rarely a problem, but in an extended language that features the ability to 
			overload on "rvalueness" - required to support move semantics <A href="#r4">[4]</A>
			- this forwarding solution may prove less than perfect (<A href="#c1">C1</A>). 
			Still, it would work in most cases, definitely a step forward from what we have 
			now.</P>
		<H3><a name="s6">#6:</a> Rvalue reference</H3>
		<P>The proposal to add move semantics to C++ <A href="#r4">[4]</A> includes the 
			concept of an rvalue reference to <STRONG>T</STRONG>, spelled <STRONG>T &amp;&amp;</STRONG>. 
			A key property of this reference is its ability to bind to rvalues.</P>
		<P>Using this new tool, we can invent yet another forwarding method:</P>
		<pre>template&lt;class A1, class A2, class A3&gt; void f(A1 &amp;&amp; a1, A2 &amp;&amp; a2, A3 &amp;&amp; a3)
{
    return g(a1, a2, a3);
}
</pre>
		<P>This approach is nearly identical to the previous solution, except that it 
			forwards a non-const rvalue as a non-const lvalue to <STRONG>g</STRONG>. This 
			enables some invalid uses of <STRONG>g</STRONG> to sneak through <STRONG>f</STRONG>, 
			as a non-const reference in <STRONG>g</STRONG> can now bind to the rvalue 
			passed to <STRONG>f</STRONG>. Non-const references are not allowed to bind to 
			rvalues for a reason, as the absence of this rule leads to mistakes:</P>
		<pre>void incr(long &amp; l)
{
    ++l;
}

void f()
{
    int i(5);
    incr(i);
}
</pre>
		<P>The programmer expects <STRONG>i</STRONG> to have value 6 after the call to <STRONG>incr</STRONG>, 
			but <STRONG>incr</STRONG> operates on a temporary rvalue of type <STRONG>long</STRONG>, 
			and the changes are discarded.</P>
		<P>The situation in our case is not that bad, as in the forwarding version of the 
			problematic example shown below</P>
		<pre>void incr(long &amp; l)
{
    ++l;
}

template&lt;class A1&gt; void fwd(A1 &amp;&amp; a1)
{
    incr(a1);
}

void f()
{
    int i(5);
    fwd(i);    // correctly fails to compile
    fwd(1L);   // compiles, but shouldn't
}
</pre>
		<P>the <STRONG>incr(a1)</STRONG> call fails to compile when <STRONG>fwd(i)</STRONG> 
			is invoked, as <STRONG>a1</STRONG> is an lvalue of type <STRONG>int</STRONG>. 
			However, <STRONG>fwd(1L)</STRONG> works, since <STRONG>a1</STRONG> is an lvalue 
			of type <STRONG>long</STRONG>. Many still consider forwarding an rvalue where 
			it otherwise would be rejected unacceptable (<A href="#c2">C2</A>), but this is 
			still better than the options we have under the current language semantics.</P>
		<H3><a name="s7">#7:</a> Rvalue reference + modified argument deduction</H3>
		<P>A perfect forwarding function would forward rvalue arguments as rvalues; none of 
			the methods described so far achieve this, since it is not possible to 
			determine from within a function whether an argument was an l- or an rvalue.</P>
		<P>Let us first consider the rvalue reference type, <STRONG>T &amp;&amp;</STRONG>, 
			in more detail in the context of the C++ type system. What if <STRONG>T</STRONG>
			is itself a reference type? Template libraries have been known to create 
			reference to reference types via typedefs or type manipulations. According to 
			the proposed resolution to Core Defect Report <A href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/cwg_defects.html#106">
				106</A> , ordinary references obey the equality <STRONG>T <EM>cv1</EM> &amp; <EM>cv2</EM>
				&amp;</STRONG> == <STRONG>T <EM>cv12</EM> &amp;</STRONG>, where <STRONG><EM>cv12</EM></STRONG>
			is the union of <STRONG><EM>cv1</EM></STRONG> and <STRONG><EM>cv2</EM></STRONG>. 
			A similar reasoning can be applied to collapse two rvalue references into one: <STRONG>
				T <EM>cv1</EM> &amp;&amp; <EM>cv2</EM> &amp;&amp;</STRONG> == <STRONG>T <EM>cv12</EM>
				&amp;&amp;</STRONG>.</P>
		<P>But what about the mixed cases? What is the meaning of <STRONG>T <EM>cv1</EM> &amp; <EM>cv2</EM>
				&amp;&amp;</STRONG> (an rvalue of reference type)? One possibility is to 
			consider an "rvalue of reference type" an lvalue, and this leads us to <STRONG>T <EM>cv1</EM>
				&amp; <EM>cv2</EM> &amp;&amp;</STRONG> == <STRONG>T <EM>cv12</EM> &amp;</STRONG>.</P>
		<P>The next step is to modify the argument deduction to retain information about 
			the "rvalueness" of the argument: when deducing against a template parameter of 
			the form <STRONG>A1 &amp;&amp;</STRONG>, deduce <STRONG>A1</STRONG> as a 
			reference type when the argument is an lvalue, and a non-reference type 
			otherwise. According to our <STRONG>T <EM>cv1</EM> &amp; <EM>cv2</EM> &amp;&amp;</STRONG>
			== <STRONG>T <EM>cv12</EM> &amp;</STRONG> rule, this effectively means that the 
			type of the argument will be <STRONG>A1 &amp;</STRONG> when the argument is an 
			lvalue, and <STRONG>A1 &amp;&amp;</STRONG> otherwise.</P>
		<P>The final link in the chain is that, according to the move proposal, <STRONG>static_cast&lt;A1 
				&amp;&amp;&gt;</STRONG> creates an unnamed rvalue reference that is treated 
			as an rvalue by the language.</P>
		<P>Putting it all together, we have (one argument case shown for brevity):</P>
		<pre>template&lt;class A1&gt; void f(A1 &amp;&amp; a1)
{
    return g(static_cast&lt;A1 &amp;&amp;&gt;(a1));
}
</pre>
		<P>When <STRONG>f</STRONG> is invoked with an lvalue of type <STRONG>X</STRONG>, <STRONG>
				A1</STRONG> is deduced as <STRONG>X &amp;</STRONG>, and <STRONG>g</STRONG> receives
			<STRONG>static_cast&lt;X &amp;&gt;(a1)</STRONG>, i.e. an lvalue of type <STRONG>X</STRONG>. 
			When the argument is an rvalue of type <STRONG>X</STRONG>, <STRONG>A1</STRONG> is 
			deduced as <STRONG>X</STRONG>, <STRONG>g</STRONG> receives <STRONG>static_cast&lt;X 
				&amp;&amp;&gt;(a1)</STRONG>, an rvalue of type <STRONG>X</STRONG>. Perfect 
			forwarding.</P>
		<H2>Summary</H2>
		<P>The table below summarizes the various approaches. The four middle columns 
			contain the argument type received by our forwarded-to function <STRONG>g</STRONG>, 
			given that the forwarding function <STRONG>f</STRONG> receives an argument type 
			listed in the header.</P>
		<P>
			<TABLE id="Table1" cellSpacing="1" cellPadding="1" border="1">
				<TR>
					<TD><STRONG>Forwarding method</STRONG></TD>
					<TD><STRONG>Non-const lvalue</STRONG></TD>
					<TD><STRONG>Const lvalue</STRONG></TD>
					<TD><STRONG>Non-const rvalue</STRONG></TD>
					<TD><STRONG>Const rvalue</STRONG></TD>
					<TD><STRONG>Problems</STRONG></TD>
					<TD><STRONG>Language Change</STRONG></TD>
					<TD><STRONG>Notes</STRONG></TD>
				</TR>
				<TR>
					<TD><A href="#s1">#1</A>: Non-const reference</TD>
					<TD>Non-const lvalue</TD>
					<TD>Const lvalue</TD>
					<TD><FONT color="red">(fails)</FONT></TD>
					<TD>Const lvalue</TD>
					<TD>Fails for f(rvalue) to g(A), f(rvalue) to g(A const &amp;)</TD>
					<TD>No</TD>
					<TD>Limited applicability; the best we can do currently</TD>
				</TR>
				<TR>
					<TD><A href="#s2">#2</A>: Const reference</TD>
					<TD>Const lvalue</TD>
					<TD>Const lvalue</TD>
					<TD>Const lvalue</TD>
					<TD>Const lvalue</TD>
					<TD>Fails for f(lvalue) to g(A &amp;)</TD>
					<TD>No</TD>
					<TD>Limited applicability</TD>
				</TR>
				<TR>
					<TD><A href="#s3">#3</A>: Const + non-const reference</TD>
					<TD>Non-const lvalue</TD>
					<TD>Const lvalue</TD>
					<TD>Const lvalue</TD>
					<TD>Const lvalue</TD>
					<TD>Requires exponential number of overloads</TD>
					<TD>No</TD>
					<TD>Not a practical solution</TD>
				</TR>
				<TR>
					<TD><A href="#s4">#4</A>: Const reference + const_cast</TD>
					<TD>Non-const lvalue</TD>
					<TD>Non-const lvalue</TD>
					<TD>Non-const lvalue</TD>
					<TD>Non-const lvalue</TD>
					<TD>Allows f(const lvalue) to g(A &amp;), f(rvalue) to g(A &amp;), f(const rvalue) 
						to g(A &amp;)</TD>
					<TD>No</TD>
					<TD>Works, but very unsafe</TD>
				</TR>
				<TR>
					<TD><A href="#s5">#5</A>: Non-const reference + modified argument deduction</TD>
					<TD>Non-const lvalue</TD>
					<TD>Const lvalue</TD>
					<TD>Const lvalue</TD>
					<TD>Const lvalue</TD>
					<TD>Language change breaks existing code</TD>
					<TD>Yes</TD>
					<TD>Near-perfect forwarding in the absence of move semantics, adequate forwarding 
						otherwise</TD>
				</TR>
				<TR>
					<TD><A href="#s6">#6</A>: Rvalue reference</TD>
					<TD>Non-const lvalue</TD>
					<TD>Const lvalue</TD>
					<TD>Non-const lvalue</TD>
					<TD>Const lvalue</TD>
					<TD>Allows f(rvalue) to g(A &amp;)</TD>
					<TD>Yes</TD>
					<TD>Slightly inferior forwarding compared to #5</TD>
				</TR>
				<TR>
					<TD><A href="#s7">#7</A>: Rvalue reference + modified argument deduction</TD>
					<TD>Non-const lvalue</TD>
					<TD>Const lvalue</TD>
					<TD>Non-const rvalue</TD>
					<TD>Const rvalue</TD>
					<TD>None known</TD>
					<TD>Yes</TD>
					<TD>Perfect</TD>
				</TR>
			</TABLE>
		</P>
		<H2>Conclusion</H2>
		<P>The practical problem of forwarding arbitrary argument lists has no good 
			solution in the current language. The main obstacle is the inability to bind a 
			non-const reference to a non-const rvalue, an issue that is addressed by the 
			proposal to add support for move semantics to C++. This makes the two problems 
			closely related, and the best solution to the forwarding problem depends on 
			whether, and to what extent, the changes required to support move are 
			incorporated into C++.</P>
		<P>If the move proposal is accepted, the preferred approach to address forwarding 
			is #7, followed by #6 and #5, in that order. Otherwise, #5 remains the only 
			possibility.</P>
		<H2>References</H2>
		<P><a name="r1">[1]</a> Boost.Bind library, Peter Dimov, <A href="http://www.boost.org/libs/bind/bind.html">
				http://www.boost.org/libs/bind/bind.html</A></P>
		<P><a name="r2">[2]</a> Boost.Lambda library, Jaakko Jrvi, Gary Powell, <A href="http://www.boost.org/libs/lambda/doc/">
				http://www.boost.org/libs/lambda/doc/</A></P>
		<P><a name="r3">[3]</a> Boost.Graph library, Jeremy Siek, Lie-Quan Lee, Andrew 
			Lumsdaine, <A href="http://www.boost.org/libs/graph/doc/">http://www.boost.org/libs/graph/doc/</A></P>
		<P><a name="r4">[4]</a> A Proposal to Add Move Semantics Support to the C++ 
			Language, Howard Hinnant et al, document number <A href="n1377.htm">N1377=02-0035</A></P>
		<P><a name="r5">[5]</a> Boost.Python library, Dave Abrahams et al, <A href="http://www.boost.org/libs/python/doc/">
				http://www.boost.org/libs/python/doc/</A></P>
		<P><EM>--- end ---</EM></P>
		</CODE></CODE></CODE></CODE></CODE></CODE>
	</body>
</html>
