<!--This file created 9/7/04 7:53 PM by Claris Home Page version 2.0-->
<HTML>
<HEAD>
   <TITLE>rvalue reference</TITLE>
   <META NAME=GENERATOR CONTENT="Claris Home Page 2.0">
   <X-SAS-WINDOW TOP=42 BOTTOM=756 LEFT=389 RIGHT=1001>
</HEAD>
<BODY BGCOLOR="#FFFFFF">

<ADDRESS>Document number: N1690 (WG21) and 04-0130 (J16)</ADDRESS>

<ADDRESS>&nbsp;</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>Peter Dimov,
<A HREF="mailto:pdimov@mmltd.net">pdimov@mmltd.net</A></ADDRESS>

<ADDRESS>&nbsp;</ADDRESS>

<ADDRESS>September 7, 2004</ADDRESS>

<H1>A Proposal to Add an Rvalue Reference to the C++ Language</H1>

<UL>
   <LI><A HREF="#Introduction">Introduction</A>
   
   <LI><A HREF="#Summary of Rvalue-Reference Proposal">Summary of
   Rvalue-Reference Proposal</A>
   
   <LI><A HREF="#Major Applications">Major Applications</A>
   
   <UL>
      <LI><A HREF="#Move Semantics">Move Semantics</A>
      
      <LI><A HREF="#Forwarding">Forwarding</A>
      
      <LI><A HREF="#Moving and Forwarding">Moving and Forwarding</A>
   </UL>
   
   <LI><A HREF="#Minor Problems Addressed">Minor Problems
   Addressed</A>
   
   <UL>
      <LI><A HREF="#Use of Rvalue Streams">Use of Rvalue Streams</A>
      
      <LI><A HREF="#Improved shared_ptr Interface">Improved
      shared_ptr Interface</A>
      
      <LI><A HREF="#Improved random_shuffle">Improved
      random_shuffle</A>
      
      <LI><A HREF="#Improved swap Interface">Improved swap
      Interface</A>
   </UL>
   
   <LI><A HREF="#Alternative Forwarding Solution">Alternative
   Forwarding Solutions</A>
   
   <LI><A HREF="#Alternative Language Syntax for">Alternative
   Language Syntax for Move</A>
   
   <LI><A HREF="#Library-Only Move Solution">Library-Only Move
   Solution</A>
   
   <LI><A HREF="#A Minor Error in N1377">A Minor Error in N1377</A>
</UL>

<H2><A NAME="Introduction"></A>Introduction</H2>

<P>We propose a new kind of reference that binds to rvalues as well
as lvalues, even if not const qualified. This addition to the
language enables programmers to:</P>

<UL>
   <LI>Eliminate unnecessary expensive copies of user defined types
   (move semantics).
   
   <LI>Solve major usability problems with generic forwarding
   utilities (perfect forwarding).
   
   <LI>Solve usability problems in components where binding an rvalue
   to a non-const reference is not a logical error.
</UL>

<H2><A NAME="Summary of rvalue-reference Proposal"></A>Summary of
Rvalue-Reference Proposal</H2>

<P><A HREF="../2002/n1377.htm">N1377</A> introduces a new reference
termed the <I>rvalue reference</I>. An rvalue reference to <TT>A</TT>
is created with the syntax <TT>A&amp;&amp;</TT>. To distinguish it
from the existing reference (<TT>A&amp;</TT>), the existing reference
is now termed an l<I>value reference</I>. The new rvalue reference
behaves just like the existing lvalue reference except where noted.
</P>

<P>There are eight modifications/additions to the core language
proposed in <A HREF="../2002/n1377.htm">N1377</A>, and summarized
below:</P>

<OL>
   <LI><A HREF="../2002/n1377.htm#What%20is%20needed%20from%20the%20language?">A
   non-const rvalue can bind to a non-const rvalue reference</A>.
   
   <LI><A HREF="../2002/n1377.htm#More on A&&">Overload resolution
   rules prefer binding rvalues to rvalue references and lvalues to
   lvalue references</A>.
   
   <LI><A HREF="../2002/n1377.htm#More%20on%20A&&">Named rvalue
   references are treated as lvalues</A>. See N1377 for rationale.
   
   <LI><A HREF="../2002/n1377.htm#Returning%20A&&">Unnamed rvalue
   references are treated as rvalues</A>.
   
   <LI><A HREF="../2002/n1377.htm#Cast%20to%20rvalue">The result of
   casting an lvalue to an rvalue reference is treated as an
   rvalue</A>.
   
   <LI><A HREF="../2002/n1377.htm#Moving from local values">Where
   elision of copy constructor is currently allowed for function
   return values, the local object is implicitly cast to an rvalue
   reference</A>.
   

   <LI><A HREF="../2002/n1377.htm#References%20to%20References">Reference
   collapsing rules are extended from cwg issue 106</A>.
   

   <LI><A HREF="../2002/n1377.htm#Template%20Argument%20Deduction%20with%20A&&">Template
   deduction rules allow detection of rvalue/lvalue status of bound
   argument</A>.
</OL>

<H2><A NAME="Major Applications"></A>Major Applications</H2>

<H3><A NAME="Move Semantics"></A>Move Semantics</H3>

<P>The rvalue reference can be used to easily add move semantics to
an existing class. By this we mean that the copy constructor and
assignment operator can be overloaded based on whether the argument
is an lvalue or an rvalue. When the argument is an rvalue, the author
of the class knows that he has a unique reference to the argument.
</P>

<BLOCKQUOTE><P>The overload taking an rvalue can modify the argument
in whatever invariant preserving way it pleases and be guaranteed
that the rest of the program will not notice!</P></BLOCKQUOTE>

<P>For types that own resources, the ability to pilfer those
resources from rvalues can result in tremendous (order of magnitude)
performance increases. Additionally clients can cast an lvalue object
to rvalue. This enables clients to tap into move optimizations when
it is known that the lvalue source is no longer relevant in the
program logic. See <A HREF="../2002/n1377.htm">N1377</A> for several
examples of move-optimized types, and even an auto_ptr-like smart
pointer which is safe to put into containers.</P>

<P>Containers such as <TT>vector&lt;T&gt;</TT> can use <TT>T</TT>'s
move semantics internally as it inserts, erases and reallocates its
elements. Member functions such as <TT>push_back</TT> can be
overloaded on the rvalue reference so that heavy weight elements can
be moved into instead of copied into the container.</P>

<P>Sequence modifying algorithms such as <TT>remove_if</TT>,
<TT>random_shuffle</TT>, and <TT>sort</TT> can move elements around
instead of copy them around, greatly reducing the expense of
manipulating sequences of heavy weight objects.</P>

<H3><A NAME="Forwarding"></A>Forwarding</H3>

<P>Generic function adaptors such as <TT>bind1st</TT>, <TT>bind</TT>,
and <TT>function</TT> transform one function signature into another
by binding some of the parameters. Ideally those parameters left
unbound in the transformed function will behave identically to the
corresponding parameter in the original function. For example, a
const lvalue reference should bind to both lvalue and rvalue
arguments, and a non-const lvalue reference should bind to a
non-const lvalue, but refuse to bind to rvalues and const lvalues.
</P>

<P>One way to accomplish this is by overloading on the free parameter
with both const and non-const lvalue references. This is the approach
taken by <TT>binder2nd</TT> (for example) after LWG issue 109 is
applied:</P>

<BLOCKQUOTE><PRE>template &lt;class Operation&gt; 
class binder2nd 
    : public unary_function&lt;...&gt;
{ 
    ...
public:
    ...
    result_type operator()(const first_argument_type&amp; x);
    result_type operator()(      first_argument_type&amp; x);
};</PRE></BLOCKQUOTE>

<P>However, as the number of free parameters grows (as in
<TT>bind</TT> and <TT>function</TT>), this solution quickly grows
impractical. The number of overloads required increases exponentially
with the number of parameters (2<SUP>N</SUP> where N is the number of
parameters).</P>

<P>This proposal provides perfect forwarding using only one overload,
no matter how many free parameters exist. For example:</P>

<BLOCKQUOTE><PRE>template &lt;class Operation&gt; 
class binder2nd 
    : public unary_function&lt;...&gt;
{ 
    ...
public:
    ...
    result_type operator()(first_argument_type&amp;&amp; x);
};</PRE></BLOCKQUOTE>

<P>If <TT>first_argument_type</TT> is a non-const lvalue reference,
then due to the reference collapsing rules the expression
<TT>first_argument_type&amp;&amp;</TT> is also a non-const lvalue
reference, and thus will not bind to rvalues. If
<TT>first_argument_type</TT> is not a reference (i.e. pass-by-value),
then the parameter <TT>first_argument_type&amp;&amp;</TT> will bind
to rvalues.</P>

<P>Given some helper functions, forwarding and moving can be made
more self documenting. Consider:</P>

<BLOCKQUOTE><PRE>template &lt;class T&gt;
struct identity
{
    typedef T type;
};
&nbsp;
template &lt;class T&gt;
inline
T&amp;&amp;
forward(typename identity&lt;T&gt;::type&amp;&amp; t)
{
    return t;
}
&nbsp;
template &lt;class T&gt;
inline
typename remove_reference&lt;T&gt;::type&amp;&amp;
move(T&amp;&amp; t)
{
    return t;
}</PRE></BLOCKQUOTE>

<P>Now clients can specify <TT>forward&lt;T&gt;(t)</TT> or
<TT>move(t)</TT> depending on the intent of the function. The
difference is somewhat subtle, thus the library helper functions help
communicate the intent. The forward function will result in an lvalue
if T is an lvalue reference, whereas the move function will always
result in an rvalue reference. Template argument deduction is
disabled for the forward function in order to force the client to
specify the template argument. This is necessary to achieve the
correct forwarding semantics.</P>

<P>Below is an example two-parameter factory function, demonstrating
perfect forwarding:</P>

<BLOCKQUOTE><PRE>template &lt;class T, class A1, class A2&gt;
shared_ptr&lt;T&gt;
factory(A1&amp;&amp; a1, A2&amp;&amp; a2)
{
    return shared_ptr&lt;T&gt;(new T(forward&lt;A1&gt;(a1),
                               forward&lt;A2&gt;(a2)));
}
&nbsp;
struct A
{
    A(int&amp;, const double&amp;);
};
&nbsp;
int main()
{
    shared_ptr&lt;A&gt; sp1 = factory&lt;A&gt;(2, 1.414);  <FONT
COLOR="#AF0000">// does not compile</FONT>
    int i = 2;
    shared_ptr&lt;A&gt; sp2 = factory&lt;A&gt;(i, 1.414);  <FONT
COLOR="#AF0000">// ok</FONT>
}</PRE></BLOCKQUOTE>

<P>In the above example the first call to factory fails because the
rvalue "2" can not bind to the int&amp; in A's constructor. An lvalue
must be passed instead. However, rvalues can be forwarded to A's
second parameter. See <A HREF="../2002/n1385.htm#s7">N1385</A> for
details on why this works.</P>

<H3><A NAME="Moving and Forwarding"></A>Moving and Forwarding</H3>

<P>Move semantics and perfect forwarding work together
synergistically. A generic forwarding utility can forward to functors
overloaded on rvalue/lvalue. And since the rvalue/lvalue
characteristic of the client's argument is preserved, move semantics
will be respected even through such forwarding. Using the forward and
move helper functions, the following example shows how move and
forwarding can work together in a self-documenting way:</P>

<BLOCKQUOTE><PRE>template &lt;class T, class A1&gt;
inline
shared_ptr&lt;T&gt;
factory(A1&amp;&amp; a1)
{
    <FONT
COLOR="#AF0000">// If a1 is bound to an lvalue, it is forwarded as an lvalue
    // If a1 is bound to an rvalue, it is forwarded as an rvalue</FONT>
    return shared_ptr&lt;T&gt;(new T(forward&lt;A1&gt;(a1)));
}
&nbsp;
struct A
{
    ...
    A(const A&amp;);  <FONT
COLOR="#AF0000">// lvalues are copied from</FONT>
    A(A&amp;&amp;);       <FONT
COLOR="#AF0000">// rvalues are moved from</FONT>
};
&nbsp;
int main()
{
    A a;
    shared_ptr&lt;A&gt; sp1 = factory&lt;A&gt;(a);        <FONT
COLOR="#AF0000">// "a" copied from</FONT>
    shared_ptr&lt;A&gt; sp2 = factory&lt;A&gt;(move(a));  <FONT
COLOR="#AF0000">// "a" moved from</FONT>
}</PRE></BLOCKQUOTE>

<H2><A NAME="Minor Problems Addressed"></A>Minor Problems Addressed
</H2>

<P>In addition to the major applications of move semantics and
perfect forwarding, the rvalue reference also addresses several minor
usability problems in current code. Below are a few examples where
the rvalue reference can be used to improve the interface of current
objects, yet these solutions are considered to be neither move
semantics nor forwarding.</P>

<H3><A NAME="Use of Rvalue Streams"></A>Use of Rvalue Streams</H3>

<P>It is not uncommon for clients to want an easy way to open a log
file, append a message to it, and then close it again, as
conveniently as possible. Here is one possible approach:</P>

<BLOCKQUOTE><PRE>void foo()
{
    {
        std::ofstream("Log file", std::ios::app) log_file;
        log_file &lt;&lt; "Log message\n";
    }
    ...
}</PRE></BLOCKQUOTE>

<P>However users strive for something more concise. A common first
try is:</P>

<BLOCKQUOTE><PRE>void foo()
{
    std::ofstream("Log file", std::ios::app) &lt;&lt; "Log message\n";
    ...
}</PRE></BLOCKQUOTE>

<P>This compiles, but <B>does not do what the programmer
intended.</B> The inserter binds to the <I>member</I> <TT>const
void*</TT> inserter, instead of to the <I>non-member</I> <TT>const
char*</TT> inserter. And so the address of the literal is written to
the file.</P>

<BLOCKQUOTE><PRE>template &lt;class charT, class traits = char_traits&lt;charT&gt; &gt;
class basic_ostream
    : virtual public basic_ios&lt;charT,traits&gt;
{
public:
    ...
    basic_ostream&amp; operator&lt;&lt;(const void* p);
    ...
};
...
template&lt;class traits&gt;
basic_ostream&lt;char,traits&gt;&amp;
operator&lt;&lt;(basic_ostream&lt;char,traits&gt;&amp;, char);<FONT
COLOR="#AF0000"> // requires lvalue ostream</FONT></PRE>
</BLOCKQUOTE>

<P>As a workaround, many people instead code:</P>

<BLOCKQUOTE><PRE>void foo()
{
    std::ofstream("Log file", std::ios::app).flush() &lt;&lt; "Log message\n";
    ...
}</PRE></BLOCKQUOTE>

<P>The "<TT>.flush()</TT>" is a no-op that simply changes the rvalue
<TT>ofstream</TT> into an lvalue.</P>

<P>With an rvalue reference we could modify the library's non-member
<TT>const char*</TT> inserter to accept the stream by rvalue
reference instead of by lvalue reference:</P>

<BLOCKQUOTE><PRE>template&lt;class traits&gt;
basic_ostream&lt;char,traits&gt;&amp;
operator&lt;&lt;(basic_ostream&lt;char,traits&gt;&amp;&amp;, char);</PRE>
</BLOCKQUOTE>

<P>And now the common first try works as expected. There is no danger
in binding an rvalue stream to the first parameter. It is convenient
for memory based streams as well:</P>

<BLOCKQUOTE><PRE>class A {...};
std::istream&amp; operator&gt;&gt;(std::istream&amp;&amp; is, A&amp; a);
std::ostream&amp; operator&lt;&lt;(std::ostream&amp;&amp; os, const A&amp; a);</PRE>
</BLOCKQUOTE>

<P>Clients of <TT>A</TT> can now convert an <TT>A</TT> to and from
<TT>std::string</TT> with simple one-liners:</P>

<BLOCKQUOTE><PRE>A a;
std::istringstream("data for an A") &gt;&gt; a;
std::string s = (std::ostringstream() &lt;&lt; a).str();</PRE>
</BLOCKQUOTE>

<H3><A NAME="Improved shared_ptr Interface"></A>Improved shared_ptr
Interface</H3>

<P>Consider the shared_ptr constructor:</P>

<BLOCKQUOTE><PRE>template&lt;class T&gt;
template&lt;class Y, class D&gt;
shared_ptr&lt;T&gt;::shared_ptr(Y* p, D d);</PRE></BLOCKQUOTE>

<P>Currently there is a precondition that the copy constructor of D
must not throw an exception. The reason is that if it does, p is
leaked. The shared_ptr constructor is designed to agressively accept
ownership of p, and delete it (call d(p)), even if the construction
of the shared_ptr throws an exception. And requiring the copy
constructor of D not to throw is the only weak link in that design. A
superior design would not allow d to be copied before ownership of p
was fully established.</P>

<P>Here is one possible redesign:</P>

<BLOCKQUOTE><PRE>template&lt;class T&gt;
template&lt;class Y, class D&gt;
shared_ptr&lt;T&gt;::shared_ptr(Y* p, const D&amp; d);</PRE>
</BLOCKQUOTE>

<P>One problem with this is that when binding an rvalue D to the
const&amp;D parameter, the compiler may make a copy anyway, and thus
there is a chance for an exception before p can be owned. Assuming
that was fixed in the language, there is still another problem: The
expression d(p) is allowed to require a non-const d. Thus internal to
the shared_ptr constructor, one must make a copy of d before calling
d_copy(p). And so you have the same problem as the pass-by-value
solution: The copying of d may throw an exception before you can
delete the pointer.</P>

<P>Here is another possible redesign:</P>

<BLOCKQUOTE><PRE>template&lt;class T&gt;
template&lt;class Y, class D&gt;
shared_ptr&lt;T&gt;::shared_ptr(Y* p, D&amp; d);</PRE></BLOCKQUOTE>

<P>Now the shared_ptr can set up code to execute d(p) before
acquiring any internal resources, and before copying d. The only
problem with this solution is that passing an rvalue D to the
shared_ptr constructor is a very common coding pattern. But that no
longer works because that rvalue D will not bind to D&amp;.</P>

<P>A perfect solution:</P>

<BLOCKQUOTE><PRE>template&lt;class T&gt;
template&lt;class Y, class D&gt;
shared_ptr&lt;T&gt;::shared_ptr(Y* p, D&amp;&amp; d);</PRE>
</BLOCKQUOTE>

<P>Using the rvalue reference, clients can pass (non-const) lvalues
or rvalues of D into the constructor. The compiler does not make a
copy of the lvalue or rvalue when binding to the parameter. Internal
to the constructor, code is set up to execute d(p), without making a
copy of d, and prior to acquiring any resources.</P>

<H3><A NAME="Improved random_shuffle"></A>Improved random_shuffle
</H3>

<P>The current signature of std::random_shuffle is:</P>

<BLOCKQUOTE><PRE>template&lt;class RandomAccessIterator, class RandomNumberGenerator&gt;
void
random_shuffle(RandomAccessIterator first, RandomAccessIterator last,
               RandomNumberGenerator&amp; rand);</PRE></BLOCKQUOTE>

<P>The reference parameter for the generator is to allow the internal
state of the generator to propagate back to the calling program. This
is fine except for when the client builds a temporary random number
generator and does not care about its final state:</P>

<BLOCKQUOTE><PRE>random_shuffle(c.begin(), c.end(), uniform_int&lt;&gt;(0, c.size()-1));</PRE>
</BLOCKQUOTE>

<P>Declaring the third argument with an rvalue reference would allow
clients to decide for themselves if the state of the random number
generator after the shuffle is important to their program logic.</P>

<BLOCKQUOTE><PRE>template&lt;class RandomAccessIterator, class RandomNumberGenerator&gt;
void
random_shuffle(RandomAccessIterator first, RandomAccessIterator last,
               RandomNumberGenerator&amp;&amp; rand);</PRE>
</BLOCKQUOTE>

<H3><A NAME="Improved swap Interface"></A>Improved swap Interface
</H3>

<P>A well known idiom for reducing a <TT>vector</TT>'s capacity to 0
is:</P>

<BLOCKQUOTE><PRE>vector&lt;A&gt;().swap(v);</PRE></BLOCKQUOTE>

<P>But this syntax is somewhat counterintuitive. Currently the member
swap of vector is declared as:</P>

<BLOCKQUOTE><PRE>void swap(vector&amp;);</PRE></BLOCKQUOTE>

<P>However, declaring it instead as:</P>

<BLOCKQUOTE><PRE>void swap(vector&amp;&amp;);</PRE></BLOCKQUOTE>

<P>would allow clients to instead write:</P>

<BLOCKQUOTE><PRE>v.swap(vector&lt;A&gt;());</PRE></BLOCKQUOTE>

<P>Overloading the namespace scope swap with rvalue references could
also allow:</P>

<BLOCKQUOTE><PRE>swap(v, vector&lt;A&gt;());</PRE></BLOCKQUOTE>

<H2><A NAME="Alternative Forwarding Solution"></A>Alternative
Forwarding Solutions</H2>

<P><A HREF="../2002/n1385.htm">N1385</A> explores the problems
associated with generic forwarding functions such as class factories
and function binders/adaptors. Seven approaches to forwarding, both
within the current language, and with language extensions, are
analyzed in detail. Out of those seven approaches, four do not
require language changes, but one of those four is not practical as
the number of free parameters increases beyond 1 or 2. The remaining
three using the current language either disallow forwarding rvalues,
or forward them as lvalues. Two of the three approaches requiring
language modifications do allow the forwarding of rvalues, without
the danger of binding them to a non-const reference. But
<A HREF="../2002/n1385.htm#s5">one</A> of those approaches would
break existing code. The <A HREF="../2002/n1385.htm#s7">remaining
solution</A> is that proposed herein.</P>

<H2><A NAME="Alternative Language Syntax for"></A>Alternative
Language Syntax for Move</H2>

<P>Since N1377 was written, various alternative syntaxes for language
support of move semantics have been explored. One of the most
promising alternatives involved modifying the existing overload rules
between pass by value, and pass by reference. For example consider:
</P>

<BLOCKQUOTE><PRE>void foo(const A&amp;);  // 1
void foo(A);         // 2</PRE></BLOCKQUOTE>

<P>Today these overloads are ambiguous. But it was proposed that they
be made unambiguous with lvalues preferring 1, and rvalues preferring
2. One of the most disturbing aesthetically was that a move
constructor would look like:</P>

<BLOCKQUOTE><PRE>struct A
{
    A(A);  // move constructor
};</PRE></BLOCKQUOTE>

<P>Some found the idea of a copy constructor taking its argument by
value a little counter-intuitive.</P>

<P>A serious backwards compatibility issue was discovered which could
silently break existing code:</P>

<BLOCKQUOTE><PRE>struct A {};
&nbsp;
template &lt;class T&gt; void f(T&amp;);  // 1
void f(A);                      // 2
&nbsp;
int main()
{
    A a;
    f(a);  2 now, 1 with the altered overload rules
}</PRE></BLOCKQUOTE>

<P>And this alternative <B>does not address the forwarding
problem</B> at all.</P>

<H2><A NAME="Library-Only Move Solution"></A>Library-Only Move
Solution</H2>

<P>N1377 gave a simple
<A HREF="../2002/n1377.htm#string Motivation">string example</A>
which is repeated here for convenience.</P>

<BLOCKQUOTE><PRE>class string
{
public:
    <FONT COLOR="#AF0000">// copy semantics</FONT>
    string(const string&amp; s);
    string&amp; operator=(const string&amp; s);
&nbsp;
    <FONT COLOR="#AF0000">// move semantics</FONT>
    string(string&amp;&amp; s);
    string&amp; operator=(string&amp;&amp; s);
    // ...
};</PRE></BLOCKQUOTE>

<P>For clarity, only the interface is shown above. A library-only
move solution is significantly more complicated. We will focus on the
best library-only solution that has emerged since the publication of
N1377. Shown below is the interface only:</P>

<BLOCKQUOTE><PRE>class string
{
public:
    <FONT COLOR="#AF0000">// copy semantics</FONT>
    string(string&amp; a);
    template &lt;class T&gt;
    string(T&amp;, typename <FONT
COLOR="#0000AF">std::enable_if_same</FONT>&lt;T,
                        const string&gt;::type* = 0);
&nbsp;
    string&amp; operator=(string&amp; a);
    template &lt;class T&gt;
    typename <FONT COLOR="#0000AF">std::enable_if_same</FONT>
    &lt;
        T, const string,
        string&amp;
    &gt;::type
    operator=(T&amp; a);
    
    <FONT COLOR="#AF0000">// move semantics</FONT>
    string(<FONT
COLOR="#0000AF">std::rvalue_ref</FONT>&lt;string&gt; a);
    string&amp; operator=(<FONT
COLOR="#0000AF">std::rvalue_ref</FONT>&lt;string&gt; a);
&nbsp;
    operator <FONT
COLOR="#0000AF">std::rvalue_ref</FONT>&lt;string&gt;()
        {return <FONT
COLOR="#0000AF">std::rvalue_ref</FONT>&lt;string&gt;(*this);}
    // ...
};</PRE></BLOCKQUOTE>

<P>The library solution relies on a couple of helper classes that
would presumably be standardized into one of the library headers,
else they would need to be reinvented on each use. Ironically the
copy semantics portion of the string class is the most effected by
the introduction of move semantics. Separate signatures are required
for non-const lvalues and const lvalues. Each of these separate
signatures would presumably forward to common copy logic. The move
signatures use <TT>std::rvalue_ref&lt;string&gt;</TT> instead of
<TT>string&amp;&amp;</TT>, and the underlying logic of these move
operations would need to dereference a <TT>string*</TT> buried in the
<TT>rvalue_ref</TT> object. Finally an implicit conversion to
<TT>std::rvalue_ref</TT> is required.</P>

<P>In contrast, the language supported move semantics example is
essentially an add on operation when adding move semantics to an
existing class. The copy semantics of an existing class are not
effected at all. The author of string can simply add the move
signatures. And there is no extraneous conversion operator required.
In a nutshell, the syntax required for a library only solution is
daunting compared to a language supported solution.</P>

<P>In addition to the added complexity in the string interface for
construction and assignment, there is additional complexity to be
overcome in other public interface functions where you want to take
advantage of the knowledge that you're dealing with an rvalue (and so
you know you can pilfer it). For example N1377 shows how
string+string can be optimized if it is known that one of the
arguments to operator+ is an rvalue. This requires four overloads:
</P>

<BLOCKQUOTE><PRE>string operator+(const string&amp;, const string&amp;);
string&amp;&amp; operator+(string&amp;&amp;, const string&amp;);
string&amp;&amp; operator+(const string&amp;, string&amp;&amp;);
string&amp;&amp; operator+(string&amp;&amp;, string&amp;&amp;);</PRE>
</BLOCKQUOTE>

<P>However, with the library solution shown above, you have not two
possible arguments, but three: non-const lvalue, const lvalue,
rvalue. And therefore you need nine overloads to cover this
optimization:</P>

<BLOCKQUOTE><PRE>string operator+(string&amp;, string&amp;);
&nbsp;
template &lt;class T&gt;
typename <FONT COLOR="#0000AF">std::enable_if_same</FONT>
&lt;
    T, const string,
    string
&gt;::type
operator+(T&amp;, string&amp;);
&nbsp;
template &lt;class T&gt;
typename <FONT COLOR="#0000AF">std::enable_if_same</FONT>
&lt;
    T, const string,
    string
&gt;::type
operator+(string&amp;, T&amp;);
&nbsp;
template &lt;class T&gt;
typename <FONT COLOR="#0000AF">std::enable_if_same</FONT>
&lt;
    T, const string,
    string
&gt;::type
operator+(T&amp;, T&amp;);
&nbsp;
string operator+(string&amp;, <FONT
COLOR="#0000AF">std::rvalue_ref</FONT>&lt;string&gt;);
&nbsp;
string operator+(<FONT
COLOR="#0000AF">std::rvalue_ref</FONT>&lt;string&gt;, string&amp;);
&nbsp;
template &lt;class T&gt;
typename <FONT COLOR="#0000AF">std::enable_if_same</FONT>
&lt;
    T, const string,
    string
&gt;::type
operator+(<FONT
COLOR="#0000AF">std::rvalue_ref</FONT>&lt;string&gt;, T&amp;);
&nbsp;
template &lt;class T&gt;
typename <FONT COLOR="#0000AF">std::enable_if_same</FONT>
&lt;
    T, const string,
    string
&gt;::type
operator+(T&amp;, <FONT
COLOR="#0000AF">std::rvalue_ref</FONT>&lt;string&gt;);
&nbsp;
string operator+(<FONT
COLOR="#0000AF">std::rvalue_ref</FONT>&lt;string&gt;, <FONT
COLOR="#0000AF">std::rvalue_ref</FONT>&lt;string&gt;);</PRE>
</BLOCKQUOTE>

<P>This is clearly getting out of hand.</P>

<P>Finally it should be noted that <B>no library solution exists
today which can accomplish <A HREF="../2002/n1385.htm#s7">perfect
forwarding</A></B>.</P>

<P>As we move into an era where forwarding functions are increasingly
important (<TT>std::tr1::bind</TT>, <TT>std::tr1::function</TT>,
<TT>boost::lambda</TT>), the subject of perfect forwarding will also
become increasingly important.</P>

<H2><A NAME="A Minor Error in N1377"></A>A Minor Error in N1377</H2>

<P>N1377 <A HREF="../2002/n1377.htm#Returning A&&">describes a
templated helper function called move</A> which casts an lvalue to an
rvalue so that clients do not need to read or write the
<TT>A&amp;&amp;</TT> syntax:</P>

<BLOCKQUOTE><PRE>template &lt;class T&gt;
inline
T&amp;&amp;         <FONT COLOR="#AF0000">// error</FONT>
move(T&amp;&amp; x)
{
    return static_cast&lt;T&amp;&amp;&gt;(x);
}</PRE></BLOCKQUOTE>

<P>The return type of this function is incorrect. The reason is
because of the
<A HREF="../2002/n1377.htm#Template Argument Deduction with A&&">modified
template argument deduction rules</A> associated with A&amp;&amp;.
These rules state that when <TT>move()</TT> is bound to an lvalue, T
will be deduced as an lvalue reference type (e.g. A&amp;). And
because of the
<A HREF="../2002/n1377.htm#References%20to%20References">extended
reference collapsing rules</A>, the expression <TT>T&amp;&amp;</TT>,
with <TT>T</TT> being <TT>A&amp;</TT>, simplifies to <TT>A&amp;</TT>.
</P>

<P>The fix is quite easy, and relies on a type trait already voted
into TR1: <TT>remove_reference</TT> (which would of course need to be
extended to support rvalue references).</P>

<BLOCKQUOTE><PRE>template &lt;class T&gt;
inline
typename remove_reference&lt;T&gt;::type&amp;&amp;  <FONT
COLOR="#AF0000">// correct</FONT>
move(T&amp;&amp; x)
{
    return x;
}</PRE></BLOCKQUOTE>

<P>Now if <TT>T</TT> is deduced as an lvalue reference, the return
type of move takes this into account, stripping off the reference,
and only then making the return type an rvalue reference.</P>
</BODY>
</HTML>
