<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252" />
<title>Extending Move Semantics To *this (revised wording)</title>
<style>
p {text-align:justify}
li {text-align:justify}
ins {color:#008040; text-decoration:underline}
del {color:#FF0000; text-decoration:line-through}
tbody {font-style: italic}
</style>
</head>

<body>

<h2 align="center">Extending move semantics to *this (revised wording)</h2>
	<h3 align="center">Bronek Kozicki and Daveed Vandevoorde</h4>
&nbsp;<br />
&nbsp;<br />
<address>
	Document number: N2377=07-0237<br />
	Date: 2007-08-03<br />
	Reply-to: Bronek Kozicki <a href="mailto:brok@spamcop.net">brok@spamcop.net</a><br />
</address>
<br />
<h3>Purpose</h3>
<p>This document is a revision of
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1821.htm">N1821 
&quot;Extending Move Semantics To *this (Revision 1)&quot;</a> . The aim of this paper is 
to fix flaws discovered in the formal wording proposed in
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1821.htm">N1821</a>. 
This paper <b>does not</b> change semantics or syntax proposed in
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1821.htm">N1821</a>. 
Instead, it merely strives to implement the intent of the original proposal.</p>
<h3>Proposed wording (formal)</h3>
<p>Following refers to the current draft
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2315.pdf">N2315</a>. 
Deletions are marked like <del>this</del> and additions are marked like <ins>this</ins>.</p>
<br />
<table width="100%">
	<tbody>
	<tr>
		<td align="left">
		<h2>Chapter 8 Declarators</h2>
		</td>
		<td align="right">
		<h2>[dcl.decl]</h2>
		</td>
	</tr>
</tbody>
</table>
 
<p><b>4</b> Declarators have the syntax</p>
<blockquote>
	<pre>
<i>declarator:
    direct-declarator
    ptr-operator declarator</i>

<i>direct-declarator:
    declarator-id
    direct-declarator ( parameter-declaration-clause ) cv-qualifier-seq<sub>opt</sub> <ins>ref-qualifier<sub>opt</sub></ins> exception-specification<sub>opt</sub>
    direct-declarator [ constant-expression<sub>opt</sub> ]
    ( declarator )</i>

<i>ptr-operator:
    </i>*<i>cv-qualifier-seq<sub>opt</sub></i>
    &amp;
    &amp;&amp;
    ::<i><sub>opt</sub> nested-name-specifier</i> * <i>cv-qualifier-seq<sub>opt</sub></i>

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

<i>cv-qualifier:
    const
    volatile</i>

<ins><i>ref-qualifier:</i>
    &amp;
    &amp;&amp;</ins>
</pre>
<p>...</p>
</blockquote>
<table width="100%">
	<tbody>
	<tr>
		<td align="left">
		<h3>8.1 Type names</h3>
		</td>
		<td align="right">
		<h3>[dcl.name]</h3>
		</td>
	</tr>
</tbody>
</table>
<p><b>1</b> To specify type conversions explicitly, and as an argument of <tt>sizeof</tt>,
<tt>new</tt>, or <tt>typeid</tt>, the name of a type shall be specified. This can 
be done with a <i>type-id</i>, which is syntactically a declaration for an object 
or function of that type that omits the name of the object or function.</p>
<blockquote>
	<pre>
<i>type-id:
    type-specifier-seq abstract-declarator<sub>opt</sub>
    
type-specifier-seq:
    type-specifier type-specifier-seq<sub>opt</sub>

abstract-declarator:
    ptr-operator abstract-declarator<sub>opt</sub>
    direct-abstract-declarator</i>
    ...
<i>direct-abstract-declarator:
    direct-abstract-declarator<sub>opt</sub>
        </i>( <i>parameter-declaration-clause</i> ) <i>cv-qualifier-seq<sub>opt</sub> <ins>ref-qualifier<sub>opt</sub></ins> exception-specification<sub>opt</sub>
    direct-abstract-declarator<sub>opt</sub> </i>[<i>constant-expression<sub>opt</sub></i> ]
    ( <i>abstract-declarator</i> )
</pre>
</blockquote>
<p>It is possible to identify uniquely the location in the <i>abstract-declarator</i> 
where the identifier would appear if the construction were a declarator in a declaration. 
The named type is then the same as the type of the hypothetical identifier.</p>
<p>...</p>
 
<table width="100%">
	<tbody>
	<tr>
		<td align="left">
		<h3>8.3.5 Functions</h3>
		</td>
		<td align="right">
		<h3>[dcl.fct]</h3>
		</td>
	</tr>
</tbody>
</table>
<p><b>1</b> In a declaration <tt>T D</tt> where <tt>D</tt> has the form:</p>
<blockquote>
	<pre>
	D1 ( <i>parameter-declaration-clause</i> ) <i>cv-qualifier-seq<sub>opt</sub> <ins>ref-qualifier<sub>opt</sub></ins> exception-specification<sub>opt</sub></i></pre>
</blockquote>
<p>type of the contained declarator-id in the declaration <tt>T D1</tt> is &quot;<i>derived-declarator-type-list
<tt>T</tt></i>,&quot; the type of the <i>declarator-id</i> in <tt>D</tt> is &quot;<i>derived-declarator-type-list</i> 
function of (<i>parameter-declaration-clause</i>) <i>cv-qualifier-seq<sub>opt</sub>
<ins>ref-qualifier<sub>opt</sub></ins></i> returning T&quot;; a type of this form is 
a function type <sup>85)</sup>.</p>
<p>...</p>
 
<p><b>4</b> A <i>cv-qualifier-seq</i> shall only be part of the function type for 
a non-static member function, the function type to which a pointer to member refers, 
or the top-level function type of a function typedef declaration. The effect of 
a <i>cv-qualifier-seq</i> in a function declarator is not the same as adding cv-qualification 
on top of the function type. In the latter case, the cv-qualifiers are ignored. 
[<i>Example:</i> </p>
<blockquote>
	<pre>
typedef void F();
struct S {
	const F f;              //<i> OK: equivalent to:</i> void<i> </i>f();
};
</pre>
</blockquote>
<br />
<p><i>- end example</i>] . <ins>A <i>ref-qualifier</i> shall only be part of the function 
type for a non-static member function, the function type to which a pointer to member 
refers, or the top-level function type of a function typedef declaration.</ins> 
The return type, the parameter type list<ins>, the <i>ref-qualifier</i></ins> and 
the <i>cv-qualifier-seq</i>, but not the default arguments (8.3.6) or the exception 
specification (15.4), are part of the function type. [<i>Note:</i> function types 
are checked during the assignments and initializations of pointer-to-functions, 
reference-to-functions, and pointer-to-member-functions. <i>- end note</i> ]</p>
 
<table width="100%">
	<tbody>
	<tr>
		<td align="left">
		<h3>8.4 Function definitions</h3>
		</td>
		<td align="right">
		<h3>[dcl.fct.def]</h3>
		</td>
	</tr>
</tbody>
</table>
 
<p><b>2</b> The declarator in a <i>function-definition</i> shall have the form</p>
<blockquote>
	<pre>
	D1 ( <i>parameter-declaration-clause</i> ) cv-qualifier-seq<sub>opt</sub> <ins>ref-qualifier<sub>opt</sub></ins> exception-specification<sub>opt</sub>	</pre>
</blockquote>
<p>as described in 8.3.5. A function shall be defined only in namespace or class scope.</p>
 
<p><b>5</b> <del>A cv-qualifier-seq </del><ins>Both a <i>cv-qualifier-seq</i> and a <i>ref-qualifier</i></ins> 
can be part of a non-static member function declaration, non-static member function 
definition, or pointer to member function only <ins>(8.3.5)</ins>; see 9.3.2. <del>It is part 
of the function type.</del></p>
 
<table width="100%">
	<tbody>
	<tr>
		<td align="left">
		<h3>9.3.1 Nonstatic member functions</h3>
		</td>
		<td align="right">
		<h3>[class.mfct.non-static]</h3>
		</td>
	</tr>
</tbody>
</table>
 
<p><ins><b>5</b> A non-static member function may be declared with a <i>ref-qualifier</i> 
(8.3.5), see 13.3.1.</ins></p>
<p><del>5</del><ins><b>6</b></ins> A non-static member function may be declared
<i>virtual</i> (10.3) or <i>pure virtual</i> (10.4).</p>
 
<table width="100%">
	<tbody>
	<tr>
		<td align="left">
		<h3>10.3 Virtual functions</h3>
		</td>
		<td align="right">
		<h3>[class.virtual]</h3>
		</td>
	</tr>
</tbody>
</table>
<p><b>2</b> If a virtual member function <tt>vf</tt> is declared in a class <tt>Base</tt> and in a class <tt>Derived</tt>, derived directly or indirectly
from <tt>Base</tt>, a member function <tt>vf</tt> with the same name, parameter-type-list (8.3.5)<ins>, ref-qualifier (9.3.1) (or absence of same)</ins>, and cv-qualification as <tt>Base::vf</tt>
is declared, then <tt>Derive d::vf</tt> is also virtual (whether or not it is so declared) and it <i>overrides</i><sup>97)</sup> <tt>Base::vf</tt>. For
convenience we say that any virtual function overrides itself. Then in any well-formed class, for each virtual function
declared in that class or any of its direct or indirect base classes there is a unique <i>final overrider</i> that overrides that
function and every other overrider of that function. The rules for member lookup (10.2) are used to determine the final
overrider for a virtual function in the scope of a derived class but ignoring names introduced by <i>using-declaration</i> s.</p> 
<p>...</p>
<table width="100%">
	<tbody>
	<tr>
		<td align="left">
		<h3>12.1 Constructors</h3>
		</td>
		<td align="right">
		<h3>[class.ctor]</h3>
		</td>
	</tr>
</tbody>
</table>
 
<p><b>4</b> A constructor shall not be <tt>virtual</tt> (10.3) or <tt>static</tt> 
(9.4). A constructor can be invoked for a <tt>const</tt>, <tt>volatile</tt> or
<tt>const volatile</tt> object. A constructor shall not be declared <tt>const</tt>,
<tt>volatile</tt>, or <tt>const volatile</tt> (9.3.2). <tt>const</tt> and <tt>volatile</tt> 
semantics (7.1.5.1) are not applied on an object under construction. They come into 
effect when the constructor for the most derived object (1.8) ends. <ins>A constructor 
shall not be declared with a <i>ref-qualifier</i> (9.3.1)</ins>.</p>
 
<table width="100%">
	<tbody>
	<tr>
		<td align="left">
		<h3>12.4 Destructors</h3>
		</td>
		<td align="right">
		<h3>[class.dtor]</h3>
		</td>
	</tr>
</tbody>
</table>
 
<p><b>2</b> A destructor is used to destroy objects of its class type. A destructor 
takes no parameters, and no return type can be specified for it (not even <tt>void</tt>). 
The address of a destructor shall not be taken. A destructor shall not be <tt>static</tt>. 
A destructor can be invoked for a <tt>const</tt>, <tt>volatile</tt> or <tt>const 
volatile</tt> object. A destructor shall not be declared <tt>const</tt>, <tt>volatile</tt> 
or <tt>const volatile</tt> (9.3.2). <tt>const</tt> and <tt>volatile</tt> semantics 
(7.1.5.1) are not applied on an object under destruction. They stop being in effect 
when the destructor for the most derived object (1.8) starts. <ins>A destructor 
shall not be declared with a <i>ref-qualifier</i> (9.3.1)</ins>.</p>
 
<table width="100%">
	<tbody>
	<tr>
		<td align="left">
		<h3>13.1 Overloadable declarations</h3>
		</td>
		<td align="right">
		<h3>[over.load]</h3>
		</td>
	</tr>
</tbody>
</table>
 
<p><b>2</b> Certain function declarations cannot be overloaded: </p>
<ul>
	<li>Function declarations that differ only in the return type cannot be overloaded.
	</li>
</ul>
<ul>
	<li>Member function declarations with the same name and the same parameter types 
	cannot be overloaded if any of them is a <tt>static</tt> member function declaration 
	(9.4). Likewise, member function template declarations with the same name, the 
	same parameter-type-list, and the same template parameter lists cannot be overloaded 
	if any of them is a <tt>static</tt> member function template declaration. The 
	types of the implicit object parameters constructed for the member functions 
	for the purpose of overload resolution (13.3.1) are not considered when comparing 
	parameter-type-lists for enforcement of this rule. In contrast, if there is 
	no <tt>static</tt> member function declaration among a set of member function 
	declarations with the same name and the same parameter-type-list, then these 
	member function declarations can be overloaded if they differ in the type of 
	their implicit object parameter. [ <i>Example:</i> the following illustrates 
	this distinction:
	<blockquote>
		<pre>class X {
    static void f();
    void f();                   //<i>   ill-formed</i>
    void f() const;             //<i>   ill-formed</i>
    void f() const volatile;    //<i>   ill-formed</i>
    void g();
    void g() const;             //<i>  OK: no static </i>g
    void g() const volatile;    //<i>  OK: no static </i>g
};
</pre>
	</blockquote>
	<br />
	<i>- end example</i>] </li>
</ul>
<ul>
	<ins>
	<li>Member function declarations with the same name and the same parameter-type-list, 
	as well as member function template declarations with the same name, the same 
	parameter-type-list, and the same template parameter lists, cannot be overloaded 
	if any of them, but not all, have a <i>ref-qualifier</i> (9.3.1). [ <i>Example:</i>
	<blockquote>
		<pre>class Y {
    void h() &amp;;
    void h() const &amp;; // OK
    void h() &amp;&amp;;      // OK<i>, all declarations </i>h()<i> have a ref-qualifier</i>  
    void i() &amp;;
    void i() const;   // <i>ill-formed, prior declaration </i>i()<i> has a ref-qualifier</i>
};
</pre></blockquote>
	<i>- end example</i>] </li></ins>
</ul>
<table width="100%">
	<tbody>
	<tr>
		<td align="left">
		<h3>13.3.1 Candidate functions and argument lists</h3>
		</td>
		<td align="right">
		<h3>[over.match.funcs]</h3>
		</td>
	</tr>
</tbody>
</table>
 
<p><b>4</b> For non-static member functions, the type of the implicit object parameter 
is <del>"reference to cv X"</del></p>
<ul>
	<ins>
	<li>"lvalue-reference to <i>cv</i> <tt>X</tt>" for functions declared without 
	a <i>ref-qualifier</i> (9.3.1) or with the <tt>&amp;</tt> <i>ref-qualifier</i>
	</li>
	<li>"rvalue-reference to <i>cv</i> <tt>X</tt>" for functions declared with 
	the <tt>&amp;&amp;</tt> <i>ref-qualifier</i> </li>
	</ins>
</ul>
<p>where <tt>X</tt> is the class of which the function is a member and <i>cv</i> is 
the cv-qualification on the member function declaration. [<i>Example:</i> for a
<tt>const</tt> member function of class <tt>X</tt>, the extra parameter is assumed 
to have type &quot;reference to <tt>const X</tt>&quot;. <i>- end example</i> ] For conversion 
functions, the function is considered to be a member of the class of the implicit 
object argument for the purpose of defining the type of the implicit object parameter. 
For non-conversion functions introduced by a <i>using-declaration</i> into a derived 
class, the function is considered to be a member of the derived class for the purpose 
of defining the type of the implicit object parameter. For static member functions, 
the implicit object parameter is considered to match any object (since if the function 
is selected, the object is discarded). [<i>Note:</i> no actual type is established 
for the implicit object parameter of a static member function, and no attempt will 
be made to determine a conversion sequence for that parameter (13.3.3). <i>- end 
note</i>]</p>
<p><b>5</b> 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; and</li>
</ul>
<ul>
	<li>no user-defined conversions can be applied to achieve a type match with 
	it;<del> and</del></li>
</ul>
<p><ins>For non-static member functions declared without a <i>ref-qualifier</i> (9.3.1), 
an additional rule applies:</ins></p>
<ul>
	<li>even if the implicit object parameter is not <tt>const</tt>-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. 
	[ <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> ]
	</li>
</ul>
<table width="100%">
	<tbody>
	<tr>
		<td align="left">
		<h3>13.3.3.2 Ranking implicit conversion sequences</h3>
		</td>
		<td align="right">
		<h3>[over.ics.rank]</h3>
		</td>
	</tr>
</tbody>
</table>
 
<p><b>3</b> Two implicit conversion sequences of the same form are indistinguishable 
conversion sequences unless one of the following rules apply: </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> (4.4), 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 (4.2). [<i>Example:</i>
	<blockquote>
		<pre>int f(const int *);
int f(int *);
int i;
int j = f(&amp;i);                       //  calls  f(int *)
</pre>
	</blockquote>
	--- <i>end example</i>] or, if not that, </li>
	<li><tt>S1</tt> and <tt>S2</tt> are reference bindings (8.5.3) and neither refers 
	to an implicit object parameter <ins>of a non-static member function declared 
	without a <i>ref-qualifier</i> (9.3.1)</ins>, and either <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.
	 
	</li>
</ul>
&nbsp;<br />
&nbsp;<br />
<h3>Acknowledgments</h3>
<p>I wish to thank Jens Maurer for much needed reviews and corrections and Howard Hinnant for valuable input. Special thanks goes to my wife Malgosia for allowing me to work on this document.</p>

</body>

</html>
