<html>

<head>

<title>Proposed wording for rvalue reference R3</title>

<style>

p {text-align:justify}

li {text-align:justify}

blockquote.note

{

    background-color:#E0E0E0;

    padding-left: 15px;

    padding-right: 15px;

    padding-top: 1px;

    padding-bottom: 1px;

}

ins {background-color:#FFFFA0}

del {background-color:#FFFFA0}

</style>

</head>



<body>



<address align=right>

Document number: N2118=06-0188<br>

<br>

<a href="mailto:hinnant@twcny.rr.com">Howard E. Hinnant</a><br>

2006-10-19

</address>

<hr>

<h1 align=center>A Proposal to Add an Rvalue Reference to the C++ Language</h1>

<h2 align=center>Proposed Wording</h2>

<h2 align=center>Revision 3</h2>



<h2>Revision 3 Summary</h2>



<p>This revision of

<a

href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1952.html">N1952</a>

reflects additional clarifications and wording changes from the CWG; there

are no substantive changes to the proposal.

</p>



<h2>Revision 2 Summary and Rationale</h2>



<p>

This revision of

<a

href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1855.html">N1855</a>

has improved wording for a few sections based on the invaluable advice of the

CWG obtained at the Mont Tremblant meeting.

</p>



<p>

The specific revisions to <a

href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1855.html">N1855</a>

are:

</p>



<ul>

<li>

Corrected numerous html errors involving "&amp;".

</li>

<li>

3.9.2p1:  Expand the definition of references to include lvalue-reference and

rvalue-reference.

</li>

<li>

5p6-7:  Reworded paragraph 6 and added paragraph 7 to both simplify and clarify

the intent.  Added an example to help clarify.

</li>

<li>

5.2.9p2:  Improved the grammar.

</li>

<li>

5.4p5:  Added "or rvalue".

</li>

<li>

6.6.3p2:  Removed the term <i>move constructor</i> from the paragraph.  Moved this

text from here to a new paragraph: 12.8p16.

</li>

<li>

7.1.3p9:  Clarified, simplified, and corrected example to match the anticipated

outcome of cwg

<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#540">540</a>.

Also corrected the example in 14.3.1p4 for the same reason.

</li>

<li>

8.3.2p1:  Improved the grammar.

</li>

<li>

8.5.3p5b2:  Improved the grammar.  Added example rd4.

</li>

<li>

12.8p2: Clarified footnote.

</li>

<li>

12.8p9:  Removed sentence beginning with "Such assignment operators..." to

synch up with working draft.

</li>

<li>

12.8p15:  Reverted (removed from this proposal).  The intent is to allow cwg

issues

<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#479">479</a>

and

<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#535">535</a>

to both better word this paragraph, generalizing it appropriately, and expanding

the applicability to  the throw statement.

</li>

<li>

Added 12.8p16 which discusses those cases when an lvalue expression may be

considered an rvalue expression for the purpose of overload resolution of the

copy operation.  

</li>

<li>

13.3.1p5:  Slight rewording in bullet 3.

</li>

<li>

13.3.3.2p3:  Simplified.

</li>

<li>

14.3.1: (lvalue or rvalue) reference -> lvalue-reference or rvalue-reference.

</li>

<li>

14.8.2.1:  Reverted p1 and placed this specification into p3.

</li>

<li>

14.8.2.5p8:  Added line for <tt>T&amp;&amp;</tt>.

</li>

</ul>



<h2>Revision 1 Summary and Rationale</h2>



<p>

This document slightly revises

<a

href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1770.html">N1770</a>

to fix a problem found in the use of rvalue stream objects.

</p>



<p>

Consider:

</p>



<blockquote><pre>

#include &lt;ostream&gt;



class A

{

public:

    A(int i) : i_(i) {}

    int get() const {return i_;}

private:

    int i_;

};



std::ostream&amp;

operator&lt;&lt; (std::ostream&amp; os, const A&amp; a)

{

    return os &lt;&lt; a.get();

}

</pre></blockquote>



<p>

This is ill formed code according to

<a

href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1770.html">N1770</a>

:

</p>



<blockquote><pre>

    return os &lt;&lt; a.get();

Error:  {lval}ostream &lt;&lt; {rval}int is ambiguous:

std::ostream::operator&lt;&lt; (int);       // #1

operator&lt;&lt;(std::ostream&amp;, const A&amp;);  // #2

</pre></blockquote>



<p>

The first overload is a member function of <tt>ostream</tt> and thus has the

following <i>pseudo-signature</i>:

</p>



<blockquote><pre>

operator&lt;&lt;(std::ostream::operator&amp;&amp;, int);     // #1

</pre></blockquote>



<p>

To match #1, the first parameter <tt>os</tt> is converted from an lvalue to

rvalue to match the implicit object parameter and the second parameter is an

exact match.

</p>



<p>

To match #2, the first parameter is an exact match, but the second parameter is

converted via the A(int) constructor.

</p>



<p>

According to 13.3.3p1, the call is ambiguous because #1 favors the second

implicit conversion sequence while #2 favors the first implicit conversion

sequence.

</p>



<p>

We believe the source of the trouble is that

<a

href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1770.html">N1770</a>

changed the type of the implicit object parameter from an lvalue-reference to an

rvalue-reference (which was motivated by eliminating one exception to the

general rules of the language).

</p>



<p>

This revision corrects that mistake by reverting the type of the implicit object

parameter to an lvalue-reference (as it is in C++03), and adding a clarification

to the special treatment that the implicit object parameter already receives

during overload resolution: An rvalue to lvalue conversion to match the implicit

object parameter does not affect overload resolution (which is also true in

C++03).

</p>



<p>

The specific revisions to

<a

href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1770.html">N1770</a>

are:

</p>



<ul>

<li>

13.3.1p4 : Revert to the current WP version.  This makes the implicit object

parameter a <tt><i>cv</i> X&amp;</tt> again.

</li>

<li>

13.3.1p5 : N1770 strikes the 3rd bullet which states that you can bind an rvalue

to the implicit object parameter even if it is a non-const lvalue-reference.

This bullet is now added back, and clarified that such binding will not impact

overload resolution.

</li>

<li>

13.3.3.1.4p3 : N1770 deleted two parenthetical phrases referring to the fact

that an rvalue can bind to the implicit object parameter.  This revision places

the phrases back in their original form.

</li>

<li>

13.3.3.2p3 : Added both normative wording and example to the N1770 proposed

bullet to stress that l/rvalue-ness does not affect rankings involving an

implicit object parameter.

</li>

</ul>



<h2>Introduction</h2>

<p>

The purpose of this document is to provide proposed wording for the <i>rvalue

reference</i> proposal documented by <a

href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1690.html">N1690</a>

and <a

href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm">N1377</a>.

</p>



<p>

The proposed wording herein avoids defining the terms <i>move constructor</i>

and <i>move assignment</i> in order to avoid possible conflict or confusion with

similar

terms which we wish to introduce into the library.  <a

href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1771.html">N1771</a>

introduces <tt>MoveConstructible</tt> and <tt>MoveAssignable</tt> requirements,

defining these concepts in terms of expressions and post-conditions, instead of

in terms of constructors or function signatures.

</p>



<h2>3.9.2 - Compound types</h2>



<p>

-1- Compound types can be constructed in the following ways:

</p>

<ul>

<li>...</li>

<li>

<i>references</i> to objects or functions of a given type, 8.3.2<del>;</del><ins>.

There are two types of references:</ins>

<ul>

<li><ins>

<i>lvalue-reference</i>

</ins></li>

<li><ins>

<i>rvalue-reference</i>

</ins></li>

</ul>

</li>

<li>...</li>

</ul>

<h2>3.10 - Lvalues and rvalues</h2>



<p>

-5- The result of calling a function that does not return <del>a reference</del>

<ins>an lvalue-reference</ins> is an rvalue. User defined operators are

functions, and whether such operators expect or yield lvalues is determined by

their parameter and return types.

</p>

<p>

-6- An expression which holds a temporary object resulting from a cast to a

<del>nonreference type</del><ins>type other than an lvalue-reference type</ins>

is an rvalue (this includes the explicit creation of an object using functional

notation (5.2.3)).

</p>



<h2>4 - Standard conversions</h2>



<p>

-3- An expression <tt>e</tt> can be <i>implicitly converted</i> to a type

<tt>T</tt> if and only if the declaration ``<tt>T t=e;</tt>'' is well-formed,

for some invented temporary variable <tt>t</tt> (dcl.init). The effect of the

implicit conversion is the same as performing the declaration and initialization

and then using the temporary variable as the result of the conversion. The

result is an lvalue if <tt>T</tt> is <del>a reference</del> <ins>an

lvalue-reference</ins> type (dcl.ref), and an rvalue otherwise. The expression

<tt>e</tt> is used as an lvalue if and only if the initialization uses it as an

lvalue.

</p>



<h2>5 - Expressions</h2>



<p>

-6- If an expression initially has the type ``<ins>lvalue-</ins>reference to <tt>T</tt>''

(dcl.ref, dcl.init.ref), the type is adjusted to ``<tt>T</tt>'' prior to any

further analysis, the expression designates the object

or function denoted by the <ins>lvalue-</ins>reference, and the expression is an lvalue.

</p>



<p>

<ins>-7- If an expression initially has the type ``<ins>rvalue-</ins>reference to <tt>T</tt>''

(dcl.ref, dcl.init.ref), the type is adjusted to ``<tt>T</tt>'' prior to any

further analysis, and the expression designates the object

or function denoted by the rvalue-reference.  If the expression is the result of

calling a function, whether implicitly or explicitly, it is an rvalue;

otherwise, it is an lvalue.  [<i>Note:</i> In general, the effect of this

rule is that named rvalue references are treated as lvalues and unnamed

rvalue references are treated as rvalues. &#8212;<i>end note</i>]<br>

[<i>Example:</i></ins>

</p>



<blockquote><pre><ins>

struct A {};

A&amp;&amp; operator+(A,A);

A&amp;&amp; f();

...

A a;

A&amp;&amp; ar = a;

</ins></pre></blockquote>



<p><ins>

The expressions <tt>f()</tt> and <tt>a + a</tt> are rvalues of type

<tt>A</tt>.  The expression

<tt>ar</tt> is an lvalue of type <tt>A</tt>.<br>

--<i>end example</i>]

</ins></p>



<h2>5.2.2 - Function call</h2>



<p>

-10- A function call is an lvalue if and only if the result type is <del>a

reference</del> <ins>an lvalue-reference</ins>.

</p>



<h2>5.2.7 - Dynamic cast</h2>



<p>

-2- If <tt>T</tt> is a pointer type, <tt>v</tt> shall be an rvalue of a pointer

to complete class type, and the result is an rvalue of type <tt>T</tt>. If

<tt>T</tt> is <del>a reference</del><ins>an lvalue-reference</ins> type,

<tt>v</tt> shall be an lvalue of a complete class type, and the result is an

lvalue of the type referred to by <tt>T</tt>.  <ins>If <tt>T</tt> is an

rvalue-reference type, <tt>v</tt> shall be an expression having a complete class

type, and the result is an rvalue of the type referred to by <tt>T</tt>.</ins>

</p>



<p>

-5- If <tt>T</tt> is ``pointer to <tt><i>cv1</i> B</tt>'' and <tt>v</tt> has

type ``pointer to <tt><i>cv2</i> D</tt>'' such that <tt>B</tt> is a base class

of <tt>D</tt>, the result is a pointer to the unique <tt>B</tt> sub-object of

the <tt>D</tt> object pointed to by <tt>v</tt>. Similarly, if <tt>T</tt> is

``reference to <tt><i>cv1</i> B</tt>'' and <tt>v</tt> has type ``<tt><i>cv2</i>

D</tt>'' such that <tt>B</tt> is a base class of <tt>D</tt>, the result is

<del>an lvalue for</del> the unique <tt>B</tt> sub-object of the <tt>D</tt>

object referred to by <tt>v</tt>.  <ins>The result is an lvalue if <tt>T</tt> is

an lvalue-reference, or an rvalue if <tt>T</tt> is an rvalue-reference.</ins>

</p>

<blockquote>...</blockquote>



<h2>5.2.9 - Static cast</h2>



<p>

-1- The result of the expression <tt>static_cast&lt;T&gt;(v)</tt> is the result

of converting the expression <tt>v</tt> to type <tt>T</tt>. If <tt>T</tt> is

<del>a reference</del> <ins>an lvalue-reference</ins> type, the result is an

lvalue; otherwise, the result is an rvalue. Types shall not be defined in a

<tt>static_cast</tt>. The <tt>static_cast</tt> operator shall not cast away

constness (expr.const.cast).

</p>



<p>

-2- An lvalue of type ``<tt><i>cv1</i> B</tt>'', where <tt>B</tt> is a class

type, can be cast to type ``reference to <tt><i>cv2</i> D</tt>'', where

<tt>D</tt> is a class derived (clause class.derived) from <tt>B</tt>, if a valid

standard conversion from ``pointer to <tt>D</tt>'' to ``pointer to <tt>B</tt>''

exists (conv.ptr), <tt><i>cv2</i></tt> is the same cv-qualification as, or

greater cv-qualification than, <tt><i>cv1</i></tt>, and <tt>B</tt> is not a

virtual base class of <tt>D</tt>.



The result <del>is an lvalue of</del> <ins>has</ins> type

``<tt><i>cv2</i> D</tt><del>.</del>'' <ins> and is an lvalue if

the type cast to is an

lvalue-reference; otherwise the result is an rvalue. </ins>



<ins>An rvalue of type

``<tt><i>cv1</i> B</tt>'' can be cast to type ``rvalue-reference to

<tt><i>cv2</i> D</tt>'' with the same constraints as noted for the lvalue of

type ``<tt><i>cv1</i> B</tt>,'' resulting in an rvalue.</ins> If the

<del>lvalue</del> <ins>object</ins> of type ``<tt><i>cv1</i> B</tt>'' is

actually a sub-object of an object of type <tt>D</tt>, the <del>lvalue</del>

<ins>result</ins> refers to the enclosing object of type <tt>D</tt>. Otherwise,

the result of the cast is undefined.

</p>



<blockquote>...</blockquote>



<p>

-3- Otherwise, an expression <tt>e</tt> can be explicitly converted to a type

<tt>T</tt> using a <tt>static_cast</tt> of the form

<tt>static_cast&lt;T&gt;(e)</tt> if the declaration ``<tt>T t(e);</tt>'' is

well-formed, for some invented temporary variable <tt>t</tt> (dcl.init). The

effect of such an explicit conversion is the same as performing the declaration

and initialization and then using the temporary variable as the result of the

conversion. The result is an lvalue if <tt>T</tt> is <del>a reference</del>

<ins>an lvalue-reference</ins> type (dcl.ref), and an rvalue otherwise. The

expression <tt>e</tt> is used as an lvalue if and only if the initialization

uses it as an lvalue.

</p>



<h2>5.2.10 - Reinterpret cast</h2>



<p>

-1- The result of the expression <tt>reinterpret_cast&lt;T&gt;(v)</tt> is the

result of converting the expression <tt>v</tt> to type <tt>T</tt>. If <tt>T</tt>

is <del>a reference</del> <ins>an lvalue-reference</ins> type, the result is an

lvalue; otherwise, the result is an rvalue and the lvalue-to-rvalue (conv.lval),

array-to-pointer (conv.array), and function-to-pointer (conv.func) standard

conversions are performed on the the expression <tt>v</tt>. Types shall not be

defined in a <tt>reinterpret_cast</tt>. Conversions that can be performed

explicitly using <tt>reinterpret_cast</tt> are listed below. No other conversion

can be performed explicitly using <tt>reinterpret_cast</tt>.

</p>



<p>

-11- An lvalue expression of type <tt>T1</tt> can be cast to the type

``reference to <tt>T2</tt>'' if an expression of type ``pointer to <tt>T1</tt>''

can be explicitly converted to the type ``pointer to <tt>T2</tt>'' using a

<tt>reinterpret_cast</tt>. That is, a reference cast

<tt>reinterpret_cast&lt;T&amp;&gt;(x)</tt> has the same effect as the conversion

<tt>*reinterpret_cast&lt;T*&gt;(&amp;x)</tt> with the built-in <tt>&amp;</tt> and

<tt>*</tt> operators <ins>(and similarly for

<tt>reinterpret_cast&lt;T&amp;&amp;&gt;(x)</tt>)</ins>.   The result <del>is an

lvalue that</del> refers to the same

object as the source lvalue, but with a different type. <ins>The result is an

lvalue for lvalue-references or an rvalue for rvalue-references.</ins> No

temporary is created, no copy is made, and constructors (class.ctor) or

conversion functions (class.conv) are not called.

</p>



<h2>5.2.11 - Const cast</h2>



<p>

-1- The result of the expression <tt>const_cast&lt;T&gt;(v)</tt> is of type

<tt>T</tt>. If <tt>T</tt> is <del>a reference</del> <ins>an

lvalue-reference</ins> type, the result is an lvalue; otherwise, the result is

an rvalue and, the lvalue-to-rvalue (conv.lval), array-to-pointer (conv.array),

and function-to-pointer (conv.func) standard conversions are performed on the

expression <tt>v</tt>. Types shall not be defined in a <tt>const_cast</tt>.

Conversions that can be performed explicitly using <tt>const_cast</tt> are

listed below. No other conversion shall be performed explicitly using

<tt>const_cast</tt>.

</p>



<p>

-4- An lvalue of type <tt>T1</tt> can be explicitly converted to an lvalue of

type <tt>T2</tt> using the cast <tt>const_cast&lt;T2&amp;&gt;</tt> (where

<tt>T1</tt> and <tt>T2</tt> are object types) if a pointer to <tt>T1</tt> can be

explicitly converted to the type pointer to <tt>T2</tt> using a const_cast.

<ins>Similarly, an expression of type <tt>T1</tt> can be explicitly converted to

an rvalue of type <tt>T2</tt> using the cast <tt>const_cast&lt;T2&amp;&amp;&gt;</tt>

(where <tt>T1</tt> and <tt>T2</tt> are object types) if a pointer to <tt>T1</tt>

can be explicitly converted to the type pointer to <tt>T2</tt> using a

<tt>const_cast</tt>.</ins> The result of a reference <tt>const_cast</tt> refers

to the original object.

</p>



<h2>5.4 - Explicit type conversion (cast notation)</h2>



<p>

-1- The result of the expression <tt>(T)</tt> <i>cast-expression</i> is of type

<tt>T</tt>. The result is an lvalue if <tt>T</tt> is <del>a reference</del>

<ins>an lvalue-reference</ins> type, otherwise the result is an rvalue. [Note:

if <tt>T</tt> is a non-class type that is cv-qualified, the cv-qualifiers are

ignored when determining the type of the resulting rvalue; see basic.lval. ]

</p>



<p>

-5- The conversions performed by

</p>



<ul>

<li>a <tt>const_cast</tt> (5.2.11),</li>

<li>a <tt>static_cast</tt> (5.2.9),</li>

<li>a <tt>static_cast</tt> followed by a <tt>const_cast</tt>,</li>

<li>a <tt>reinterpret_cast</tt> (5.2.10), or</li>

<li>a <tt>reinterpret_cast</tt> followed by a <tt>const_cast</tt>,</li>

</ul>



<p>

can be performed using the cast notation of explicit type conversion. The same

semantic restrictions and behaviors apply, with the exception that in performing

a <tt>static_cast</tt> in the following situations the conversion is valid even

if the base class is inaccessible:

</p>



<ul>

<li>

a pointer to an object of derived class type or an lvalue <ins>or rvalue</ins>

of derived class type may be explicitly converted to a pointer or reference to

an unambiguous base class type, respectively;

</li>

<li>

a pointer to member of derived class type may be explicitly converted to a

pointer to member of an unambiguous non-virtual base class type;

</li>

<li>

a pointer to an object of an unambiguous non-virtual base class type, an lvalue

<ins>or rvalue</ins> of an unambiguous non-virtual base class type, or a pointer

to member of an unambiguous non-virtual base class type may be explicitly

converted to a pointer, a reference, or a pointer to member of a derived class

type, respectively.

</li>

</ul>



<p>...</p>



<h2>5.16 - Conditional operator</h2>



<p>

-3- Otherwise, if the second and third operand have different types ...

</p>



<ul>

<li>

If <tt>E2</tt> is an lvalue: <tt>E1</tt> can be converted to match <tt>E2</tt>

if <tt>E1</tt> can be implicitly converted (clause conv) to the type

``<ins>lvalue-</ins>reference to <tt>T2</tt>'', subject to the constraint that

in the conversion the reference must bind directly (dcl.init.ref) to

<tt>E1</tt>.

</li>

<li>...</li>

</ul>



<h2>6.6.3 - The return statement</h2>



<p>

-2- A return statement without an expression can be used only in functions that

do not return a value, that is, a function with the return type <tt>void</tt>, a

constructor (class.ctor), or a destructor (class.dtor). A return statement with

an expression of non-void type can be used only in functions returning a value;

the value of the expression is returned to the caller of the function. The

expression is implicitly converted to the return type of the function in which

it appears. A return statement can involve the construction and copy of a

temporary object (class.temporary).

<ins>[<i>Note:</i>A copy operation associated with a

return statement may be elided or considered as an rvalue for the purpose of

overload resolution in selecting a constructor (12.8).

&#8212;<i>end note</i>]</ins>

Flowing off the end of a function is

equivalent to a <tt>return</tt> with no value; this results in undefined

behavior in a value-returning function.

</p>



<h2>7.1.3 - The typedef specifier</h2>



<p>

-9- If a typedef <tt>TD</tt> names a type <del>``reference to <tt><i>cv1</i> S</tt>''</del>

<ins>that is a reference to a type <tt>T</tt></ins>,

an attempt to create the type <del>``reference to <tt><i>cv2</i> TD</tt>''</del>

<ins>``lvalue-reference to <tt><i>cv</i> TD</tt>''</ins> creates the

type  <del>``reference to <tt><i>cv12</i> S</tt>'', where <tt><i>cv12</i></tt> is the

union of the cv-qualifiers <tt><i>cv1</i></tt> and <tt><i>cv2</i></tt>. 

Redundant qualifiers are ignored</del> <ins>``lvalue-reference to <tt>T</tt>'',

while an attempt to create the type ``rvalue-reference to <tt><i>cv</i> TD</tt>''

creates the type <tt>TD</tt></ins>. <br> [<i>Example:</i>

</p>



<blockquote><pre><del>

int i;

typedef int &amp; RI;

RI &amp; r1 = i; / / r1 has the type int&amp;

const RI &amp; r2 = i; / / r2 has the type const int&amp;

</del>

<ins>

int i;

typedef int&amp;  LRI;

typedef int&amp;&amp; RRI;

LRI&amp; r1 = i;            // r1 has the type int&amp;

const LRI&amp; r2 = i;      // r2 has the type int&amp;

const LRI&amp;&amp; r3 = i;     // r3 has the type int&amp;

RRI&amp; r4 = i;            // r4 has the type int&amp;

RRI&amp;&amp; r5 = i;           // r5 has the type int&amp;&amp;

</ins></pre></blockquote>

<p>

--<i>end example</i>]

</p>



<h2>8 - Declarators</h2>



<p>-4- Declarators have the syntax</p>



<blockquote><pre>

declarator:

    direct-declarator

    ptr-operator declarator



direct-declarator:

    declarator-id

    direct-declarator ( parameter-declaration-clause ) cv-qualifier-seq<sub>opt</sub> exception-specification<sub>opt</sub>

    direct-declarator [ constant-expression<sub>opt</sub> ]

    ( declarator )



ptr-operator:

    * cv-qualifier-seq<sub>opt</sub>

    &amp;

    <ins>&amp;&amp;</ins>

    ::<sub>opt</sub> nested-name-specifier * cv-qualifier-seq<sub>opt</sub>



cv-qualifier-seq:

    cv-qualifier cv-qualifier-seq<sub>opt</sub>

...

</pre></blockquote>



<h2>8.3.2 - References</h2>



<p>

-1- In a declaration <tt>T D</tt> where <tt>D</tt> has <ins>either of</ins>

the form<ins>s</ins>

</p>



<blockquote><pre>

&amp;  D1

<ins>&amp;&amp; D1</ins>

</pre></blockquote>



<p>

and the type of the identifier in the declaration <tt>T D1</tt> is

<i>``derived-declarator-type-list</i> <tt>T</tt>,'' then the type of the

identifier of <tt>D</tt> is <i>``derived-declarator-type-list</i> reference to

<tt>T</tt>.'' Cv-qualified references are ill-formed except when the

cv-qualifiers are introduced through the use of a typedef (dcl.typedef) or of a

template type argument (temp.arg), in which case the cv-qualifiers are ignored.

[<i>Example:</i> in

</p>



<blockquote><pre>

typedef int&amp; A;

const A aref = 3;               //  ill-formed;

                //  non-const  reference initialized with rvalue

</pre></blockquote>



<p>

the type of <tt>aref</tt> is ``reference to <tt>int</tt>'', not ``<tt>const</tt>

reference to int''.] [<i>Note:</i> a reference can be thought of as a name of an

object. ] A declarator that specifies the type ``reference to cv void'' is

ill-formed.

</p>



<p><ins>

A reference type that is declared using <tt>&amp;</tt> is called an

<i>lvalue-reference</i>, and a reference type that is declared using <tt>&amp;&amp;</tt> is

called an <i>rvalue-reference</i>. Lvalue-references and rvalue-references are distinct

types. Except where explicitly noted, they are semantically equivalent and

commonly referred to as references.

</ins></p>



<h2>8.5.3 - References</h2>



<p>

<i>Note: The changes proposed for core issue 391 are reflected in the "old" text

below.</i>

</p>



<p>

-1- A variable declared to be a <tt>T&amp;</tt> <ins>or <tt>T&amp;&amp;</tt></ins>, that is

``reference to type <tt>T</tt>'' (dcl.ref), shall be initialized by an object,

or function, of type <tt>T</tt> or by an object that can be converted into a

<tt>T</tt>.

</p>



<p>

-5- A reference to type ``<tt><i>cv1</i> T1</tt>'' is initialized by an

expression of type ``<tt><i>cv2</i> T2</tt>'' as follows:

</p>

<ul>

<li>If the initializer expression

<ul>

<li>

is an lvalue (but is not a bit-field), and ``<tt><i>cv1</i> T1</tt>'' is

reference-compatible with ``<tt><i>cv2</i> T2</tt>,'' or

</li>

<li>

has a class type (i.e., <tt>T2</tt> is a class type) and can be implicitly

converted to an lvalue of type ``<tt><i>cv3</i> T3</tt>,'' where

``<tt><i>cv1</i> T1</tt>'' is reference-compatible with ``<tt><i>cv3</i>

T3</tt>'' *

<blockquote>

[Footnote: This requires a conversion function (class.conv.fct) returning a

reference type. --- end foonote] </blockquote> (this conversion is selected by

enumerating the applicable conversion functions (over.match.ref) and choosing

the best one through overload resolution (over.match)), </li> </ul>  then the

reference is bound directly to the initializer expression lvalue in the first

case, and the reference is bound to the lvalue result of the conversion in the

second case. In these cases the reference is said to <i>bind directly</i> to the

initializer expression. [<i>Note:</i> the usual lvalue-to-rvalue (conv.lval),

array-to-pointer (conv.array), and function-to-pointer (conv.func) standard

conversions are not needed, and therefore are suppressed, when such direct

bindings to lvalues are done. ]<br> [<i>Example:</i>

<blockquote><pre>

double d = 2.0;

double&amp; rd = d;                  // rd <i>refers to</i> d

const double&amp; rcd = d;           // rcd <i>refers to</i> d



struct A { };

struct B : public A { } b;

A&amp; ra = b;                       // ra <i>refers to</i> A <i>sub-object in</i> b

const A&amp; rca = b;                // rca <i>refers to</i> A <i>sub-object in</i> b

</pre></blockquote>

-- <i>end example</i>]

</li>

<li>

Otherwise, the reference shall be <ins>an lvalue-reference</ins> to a

non-volatile const type (i.e., <tt><i>cv1</i></tt>

shall be <tt>const</tt>)<ins>, or shall be an rvalue-reference</ins>. [<i>Example:</i>

<blockquote><pre>

double&amp; rd2 = 2.0;    // <i>error: not an lvalue and reference not</i> const

int  i = 2;

double&amp; rd3 = i;      // <i>error: type mismatch and reference not</i> const

<ins>double&amp;&amp; rd4 = i;     // <i>OK, reference bound to temporary double</i></ins>

</pre></blockquote>

-- <i>end example</i>]

<ul>

<li>

If the initializer expression is an rvalue, with <tt>T2</tt> a class type, and

``<tt><i>cv1</i> T1</tt>" is reference-compatible with ``<tt><i>cv2</i>

T2</tt>," the reference is bound to the object represented by the rvalue (see

basic.lval) or to a sub-object within that object. [<i>Example:</i>

<blockquote><pre>

struct A { };

struct B : public A { } b;

extern B f();

const A&amp; rca = f();        // <i>Bound to the </i>A<i> sub-object of the </i>B<i> rvalue</i>

<ins>A&amp;&amp; rcb = f();             // <i>Same as above</i></ins>

</pre></blockquote>

-- <i>end example</i>]

</li>

<li>

Otherwise, a temporary of type ``<tt><i>cv1</i> T1</tt>" is created and

initialized from the initializer expression using the rules for a non-reference

copy initialization (dcl.init). The reference is then bound to the temporary. If

<tt>T1</tt> is reference-related to <tt>T2</tt>, <tt><i>cv1</i></tt> must be the

same cv-qualification as, or greater cvqualification than, <tt><i>cv2</i></tt>;

otherwise, the program is ill-formed.  [<i>Example:</i>

<blockquote><pre>

const double&amp; rcd2 = 2;        // rcd2 <i>refers to temporary with value</i> 2.0

<ins>double&amp;&amp; rcd3 = 2;             // rcd3 <i>refers to temporary with value</i> 2.0</ins>

const volatile int cvi = 1;

const int&amp; r = cvi;            // <i>error: type qualifiers dropped</i>

</pre></blockquote>

-- <i>end example</i>] </li> </ul>

</li>

</ul>



<h2>12.8 - Copying class objects</h2>



<p>

-2- A non-template constructor for class <tt>X</tt> is a <i>copy</i> constructor

if its first parameter is of type <tt>X&amp;</tt>, <tt>const X&amp;</tt>, <tt>volatile

X&amp;</tt> or <tt>const volatile X&amp;</tt>, and either there are no other parameters

or else all other parameters have default arguments (dcl.fct.default).*

</p>



<blockquote><p>

[Footnote: Because a template constructor <ins>or a constructor whose first

parameter is an rvalue-reference</ins> is never a copy constructor, the

presence of such a <del>template</del> <ins>constructor</ins> does not suppress

the implicit declaration of a copy constructor.

<del>Template</del> <ins>Such</ins> constructors participate in overload

resolution with other constructors, including copy constructors, and<ins>, if

selected, will</ins> <del>a template

constructor may</del> be used to copy an

object if it provides a better match than other constructors. --- end

foonote]

</p></blockquote>



<p>

[<i>Example:</i> <tt>X::X(const X&amp;)</tt> and <tt>X::X(X&amp;, int=1)</tt> are copy

constructors.

</p>



<blockquote><pre>

class X {

    //  ...

public:

    X(int);

    X(const X&amp;, int = 1);

};

X a(1);                         //  calls  X(int);

X b(a, 0);                      //  calls  X(const   X&amp;,   int);

X c = b;                        //  calls  X(const   X&amp;,   int);

</pre></blockquote>



<p>

--- end example] [<i>Note:</i> all forms of copy constructor may be declared for

a class. [<i>Example:</i>

</p>



<blockquote><pre>

class X {

        //  ...

public:

        X(const X&amp;);

        X(X&amp;);                  //  OK

};

</pre></blockquote>



<p>

--- end example]<br> --- end note] [<i>Note:</i> if a class <tt>X</tt> only has

a copy constructor with a parameter of type <tt>X&amp;</tt>, an initializer of type

<tt>const X</tt> or <tt>volatile X</tt> cannot initialize an object of type

(possibily cv-qualified) <tt>X</tt>. [<i>Example:</i>

</p>



<blockquote><pre>

struct X {

        X();                    //  default constructor

        X(X&amp;);                  //  copy constructor with a nonconst parameter

};

const X cx;

X x = cx;                       //  error -  X::X(X&amp;)  cannot copy  cx  into  x

</pre></blockquote>



<p>

--- end example]<br> --- end note]

</p>



<p>

-9- A user-declared <i>copy</i> assignment operator <tt>X::operator=</tt> is a

non-static non-template member function of class <tt>X</tt> with exactly one

parameter of type <tt>X</tt>, <tt>X&amp;</tt>, <tt>const X&amp;</tt>, <tt>volatile

X&amp;</tt> or <tt>const volatile X&amp;</tt>.*

</p>



<blockquote><p>

[Footnote: Because a template assignment operator <ins>or an assignment operator

taking an rvalue reference parameter</ins> is never a copy assignment operator,

the presence of such <del>a template</del> <ins>an assignment operator</ins>

does not suppress the implicit declaration of a copy assignment operator.

<del>Template</del><ins>Such</ins> assignment operators participate in overload

resolution with other assignment operators, including copy assignment operators,

and<ins>, if selected will</ins> <del>a template assignment operator may</del>

be used to assign an object <del>if it provides a better match than other

assignment operators</del>. --- end foonote]

</p></blockquote>



<p>

[<i>Note:</i> an overloaded assignment operator must be declared to have only

one parameter; see over.ass. ] [<i>Note:</i> more than one form of copy

assignment operator may be declared for a class. ] [<i>Note:</i> if a class

<tt>X</tt> only has a copy assignment operator with a parameter of type

<tt>X&amp;</tt>, an expression of type <tt>const X</tt> cannot be assigned to an

object of type <tt>X</tt>. [<i>Example:</i>

</p>



<blockquote><pre>

struct X {

        X();

        X&amp; operator=(X&amp;);

};

const X cx;

X x;

void f() {

        x = cx;                 //  error:

                                //   X::operator=(X&amp;)  cannot assign  cx  into  x

}

</pre></blockquote>



<p>

--- end example]<br> --- end note]

</p>



<p>

-15- When certain criteria are met ...

</p>



<p><ins>

-16- When the criteria for elision of a copy operation are met and the

object to be copied is designated by an lvalue, overload resolution to

select the constructor for the copy is first performed as if the object

were designated by an rvalue.  If overload resolution fails, or if the

type of the first parameter of the selected constructor is not an

rvalue-reference to the object's type (possibly cv-qualified),

overload resolution is performed again, considering the object as

an lvalue.  [<i>Note:</i> This two-stage overload resolution must be

performed regardless of whether copy elision will occur.  It determines

the constructor to be called if elision is not performed, and the

selected constructor must be accessible even if the call is elided.

&#8212;<i>end note</i>]

</ins></p>



<p><ins>[<i>Example:</i></ins></p>



<blockquote><pre><ins>

class Thing {

public:

    Thing();

    ~Thing();

    Thing(Thing&amp;&amp;);

private:

    Thing(const Thing&amp;);

};



Thing f(bool b) {

    Thing t;

    if (b)

        throw t; // <i>OK, Thing(Thing&amp;&amp;) used (or elided) to throw t</i>

    return t;    // <i>OK, Thing(Thing&amp;&amp;) used (or elided) to return t</i>

}



Thing t2 = f();  // <i>OK, Thing(Thing&amp;&amp;) used (or elided) for construction of t2</i>

</ins></pre></blockquote>



<p><ins>--- end example]</ins></p>



<h2>13.3.1 - Candidate functions and argument lists</h2>



<p>

-5- During overload resolution, the implied object argument is indistinguishable

from other arguments. The implicit object parameter, however, retains its

identity since conversions on the corresponding argument shall obey these

additional rules:

</p>

<ul>

<li>

no temporary object can be introduced to hold the argument for the implicit

object parameter;<ins> and</ins>

</li>

<li>

no user-defined conversions can be applied to achieve a type match with it;

and

</li>

<li>

even if the implicit object parameter is not const-qualified, an rvalue

temporary can be bound to the parameter as long as in all other respects the

temporary can be converted to the type of the implicit object parameter.

<ins>[<i>Note:</i> The fact that such a temporary is an rvalue does not affect

the ranking of implicit conversion sequences (13.3.3.2). <i>-- end note</i>]</ins>

</li>

</ul>



<h2>13.3.1.4 - Copy-initialization of class by user-defined conversion</h2>



<p>

-1- Under the conditions specified in dcl.init, as part of a copy-initialization

of an object of class type, a user-defined conversion can be invoked to convert

an initializer expression to the type of the object being initialized. Overload

resolution is used to select the user-defined conversion to be invoked. Assuming

that ``<tt><i>cv1</i> T</tt>'' is the type of the object being initialized, with

<tt>T</tt> a class type, the candidate functions are selected as follows:

</p>



<ul>

<li>

The converting constructors (class.conv.ctor) of <tt>T</tt> are candidate

functions.

</li>

<li>

When the type of the initializer expression is a class type ``<tt><i>cv</i>

S</tt>'', the conversion functions of <tt>S</tt> and its base classes are

considered. Those that are not hidden within <tt>S</tt> and yield a type whose

cv-unqualified version is the same type as <tt>T</tt> or is a derived class

thereof are candidate functions. Conversion functions that return ``reference to

<tt>X</tt>'' return lvalues <ins>or rvalues (depending upon the type of

reference)</ins> of type <tt>X</tt> and are therefore considered to yield

<tt>X</tt> for this process of selecting candidate functions.

</li>

</ul>



<h2>13.3.1.5 - Initialization by conversion function</h2>



<p>

-1- Under the conditions specified in dcl.init, as part of an initialization of

an object of nonclass type, a conversion function can be invoked to convert an

initializer expression of class type to the type of the object being

initialized. Overload resolution is used to select the conversion function to be

invoked. Assuming that ``<tt><i>cv1</i> T</tt>'' is the type of the object being

initialized, and ``<tt><i>cv</i> S</tt>'' is the type of the initializer

expression, with <tt>S</tt> a class type, the candidate functions are selected

as follows:

</p>



<ul>

<li>

The conversion functions of <tt>S</tt> and its base classes are considered.

Those that are not hidden within <tt>S</tt> and yield type <tt>T</tt> or a type

that can be converted to type <tt>T</tt> via a standard conversion sequence

(over.ics.scs) are candidate functions. Conversion functions that return a

cv-qualified type are considered to yield the cv-unqualified version of that

type for this process of selecting candidate functions. Conversion functions

that return ``reference to <tt><i>cv2</i> X</tt>'' return lvalues <ins>or

rvalues (depending upon the type of reference)</ins> of type ``<tt><i>cv2</i>

X</tt>'' and are therefore considered to yield <tt>X</tt> for this process of

selecting candidate functions.

</li>

</ul>



<h2>13.3.1.6 Initialization by conversion function for direct reference binding</h2>

<p>

-1- Under the conditions specified in dcl.init.ref, a reference can be bound

directly to an lvalue that is the result of applying a conversion function to an

initializer expression. Overload resolution is used to select the conversion

function to be invoked. Assuming that ``<i>cv1</i> <tt>T</tt>'' is the

underlying type of the reference being initialized, and ``<i>cv</i> <tt>S</tt>''

is the type of the initializer expression, with <tt>S</tt> a class type, the

candidate functions are selected as follows:

</p>

<ul>

<li>

The conversion functions of <tt>S</tt> and its base classes are considered.

Those that are not hidden within <tt>S</tt> and yield type

``<ins>lvalue-</ins>reference to <i>cv2</i> <tt>T2</tt>'', where ``<i>cv1</i>

<tt>T</tt>'' is reference-compatible (dcl.init.ref) with ``<i>cv2</i>

<tt>T2</tt>'', are candidate functions.

</li>

</ul>



<h2>13.3.3.1.4 - Reference binding</h2>



<p>

-3- A standard conversion sequence cannot be formed if it requires binding

<del>a reference</del> <ins>an lvalue-reference</ins> to non-const to an rvalue

(except when binding an implicit object parameter; see the special rules for

that case in over.match.funcs). [<i>Note:</i> this means, for example, that a

candidate function cannot be a viable function if it has a non-const

<ins>lvalue-</ins>reference parameter (other than the implicit object parameter)

and the corresponding argument is a temporary or would require one to be created

to initialize the <ins>lvalue-</ins>reference (see dcl.init.ref). ]

</p>



<p>

-4- Other restrictions on binding a reference to a particular argument do not

affect the formation of a standard conversion sequence, however.

[<i>Example:</i> a function with a ``<ins>lvalue-</ins>reference to

<tt>int</tt>'' parameter can be a viable candidate even if the corresponding

argument is an <tt>int</tt> bit-field. The formation of implicit conversion

sequences treats the <tt>int</tt> bit-field as an <tt>int</tt> lvalue and finds

an exact match with the parameter. If the function is selected by overload

resolution, the call will nonetheless be ill-formed because of the prohibition

on binding a non-const <ins>lvalue-</ins>reference to a bit-field

(dcl.init.ref). ]

</p>



<h2>13.3.3.2 Ranking implicit conversion sequences</h2>



<p>

-3- Two implicit conversion sequences of the same form are indistinguishable

conversion sequences unless one of the following rules apply:

</p>

<p>...</p>

<ul>

<li>

<tt>S1</tt> and <tt>S2</tt> differ only in their qualification conversion and

yield similar types <tt>T1</tt> and <tt>T2</tt> (conv.qual), respectively, and

the cv-qualification signature of type <tt>T1</tt> is a proper subset of the

cv-qualification signature of type <tt>T2</tt>, and <tt>S1</tt> is not the

deprecated string literal array-to-pointer conversion (conv.array).

[<i>Example:</i>

<blockquote><pre>

int f(const int *);

int f(int *);

int i;

int j = f(&amp;i);                  //  Calls  f(int   *)

</pre></blockquote>

--- end example] or, if not that,

</li>



<li><ins>

<tt>S1</tt> and <tt>S2</tt> are reference bindings (dcl.init.ref) and neither

refers to an implicit object parameter, and <tt>S1</tt> binds an

lvalue-reference to an lvalue and <tt>S2</tt> binds an rvalue-reference

or <tt>S1</tt> binds an rvalue-reference to an rvalue and <tt>S2</tt> binds an

lvalue-reference.<br> [<i>Example:</i>

</ins><blockquote><pre><ins>

int i;

int f();

int g(const int &amp;);

int g(const int &amp;&amp;);

int j = g(i);                  //  Calls  g(const int &amp;)

int k = g(f());                //  Calls  g(const int &amp;&amp;)



struct A {A&amp; operator&lt;&lt;(int);};

A&amp; operator&lt;&lt;(A&amp;&amp;, char);

A() &lt;&lt; 1;                      // Calls A::operator&lt;&lt;(int)

A() &lt;&lt; 'c';                    // Calls operator&lt;&lt;(A&amp;&amp;, char)

A a;

a &lt;&lt; 1;                        // Calls A::operator&lt;&lt;(int)

a &lt;&lt; 'c';                      // Calls operator&lt;&lt;(A&amp;&amp;, char)

</ins></pre></blockquote><ins>

--- <i>end example</i>] or, if not that,

</ins></li>

<li><tt>S1</tt> and <tt>S2</tt> are reference bindings...</li>

</ul>



<h2>14.3.1 - Template type arguments</h2>



<p>

-4- If a <i>template-argument</i> for a <i>template-parameter</i> <tt>T</tt>

names a type <del>``reference to <tt><i>cv1</i> S</tt>''</del> <ins>that is a

reference to a type <tt>A</tt></ins>, an attempt to

create the type <del>``reference to <tt><i>cv2</i> T</tt>''</del> 

<ins>``lvalue-reference to <tt><i>cv</i> T</tt>''</ins> creates the type 

<del>``reference to <tt><i>cv12</i> S</tt>'', where <tt><i>cv12</i></tt> is the

union of the cv-qualifiers <tt><i>cv1</i></tt> and <tt><i>cv2</i></tt>. Redundant

cv-qualifiers are ignored</del> <ins>``lvalue-reference to <tt>A</tt>'', while

an attempt to create the type ``rvalue-reference to <tt><i>cv</i> T</tt>''

creates the type <tt>T</tt></ins>. [<i>Example:</i>

</p>



<blockquote><pre>

template &lt;class T&gt; class X {

    f(const T&amp;);

    <ins>g(T&amp;&amp;);</ins>

    /* ... */

};

X&lt;int&amp;&gt; x1;         // X&lt;int&amp;&gt;::f has the parameter type <del>const</del> int&amp;

<ins>                    // X&lt;int&amp;&gt;::g has the parameter type int&amp;

X&lt;const int&amp;&amp;&gt; x2;  // X&lt;const int&amp;&amp;&gt;::f has the parameter type const int&amp;

                    // X&lt;const int&amp;&amp;&gt;::g has the parameter type const int&amp;&amp;

</ins></pre></blockquote>

<p>--<i>end example</i>]

</p>



<h2>14.8.2.1 - Deducing template arguments from a function call</h2>



<p>

-3- If <tt>P</tt> is a cv-qualified type, the top level cv-qualifiers of

<tt>P</tt>'s type are ignored for type deduction. If <tt>P</tt> is a reference

type, the type referred to by <tt>P</tt> is used for type deduction.

<ins>If <tt>P</tt> is an rvalue-reference type and the argument is an lvalue,

the type <tt>A&amp;</tt> is used in place of <tt>A</tt> for type deduction.

[<i>Example:</i></ins>

</p>



<blockquote><pre><ins>

template&lt;typename T&gt; int f(T&amp;&amp;);

int i;

int j = f(i);    // calls f&lt;int&amp;&gt;(i)

</ins></pre></blockquote>

<p><ins>

--- <i>end example</i>]  [<i>Note:</i> The effect of this rule for lvalue

arguments and rvalue-reference parameters is that deduction in such cases

will fail unless the function parameter is of the form

<tt><i>cv</i> T&amp;&amp;</tt> (14.8.2.5). &#8212;<i>end note</i>]

</ins></p>



<h2>14.8.2.5 - Deducing template arguments from a type</h2>



<p>

-8- A template type argument <tt>T</tt>, a template template argument <tt>TT</tt>

or a template non-type argument <tt>i</tt> can be deduced if <tt>P</tt> 

and <tt>A</tt> have one of the following forms:

</p>



<blockquote><pre>

T

<i>cv-list</i> T

T*

T&amp;

<ins>T&amp;&amp;</ins>

T[<i>integer-constant</i>]

...

</pre></blockquote>



<h2>Acknowledgments</h2>



<p>

Many thanks to William M. (Mike) Miller, Edison Design Group, Inc, for the

excellent review and suggestions.

</p>



</body>

</html>

