<h1 id="mergedwordingforp0527r1andp1155r3">Merged wording for P0527R1 and P1155R3</h1>

<pre>Document number: P1825R0
Date: 2019-07-19
Project: Programming Language C++, Core Working Group
Reply-to: David Stone: &#x64;&#x61;&#x76;&#x69;&#x64;&#x40;&#x64;&#x6F;&#x75;&#x62;&#x6C;&#x65;&#x77;&#x69;&#x73;&#x65;&#x2E;&#x6E;&#x65;&#x74;, &#x64;&#x61;&#x76;&#x69;&#x64;&#x2E;&#x73;&#x74;&#x6F;&#x6E;&#x65;&#x40;&#x75;&#x62;&#x65;&#x72;&#x2E;&#x63;&#x6F;&#x6D;
</pre>

<p>P0527R1 ("Implicitly move from rvalue references in return statements" by David Stone) and P1155R3 ("More implicit moves" by Arthur O'Dwyer) both touch the same section of wording, including making some of the same changes. This wording accounts for all of the changes in both papers.</p>

<p>Change 11.9.5 [class.copy.elision]/3:</p>

<blockquote>
  <p><ins>An <i>implicitly movable entity</i> is a variable of automatic storage duration that is either a non-volatile object or an rvalue reference to a non-volatile object type.</ins> In the following copy-initialization contexts, a move operation might be used instead of a copy operation:</p>
  
  <ul>
  <li><p>If the expression in a <code>return</code> or <code>co_return</code> statement ([stmt.return]) is a (possibly parenthesized) <i>id-expression</i> that names <del>an object with automatic storage duration</del> <ins>an implicitly movable entity</ins> declared in the body or <i>parameter-declaration-clause</i> of the innermost enclosing function or <i>lambda-expression</i>, or</p></li>
  
  <li><p>if the operand of a <i>throw-expression</i> is <del>the name of a non-volatile automatic object (other than a function or catch-clause parameter)</del> <ins>a (possibly parenthesized) <i>id-expression</i> that names an implicitly movable entity</ins> whose scope does not extend beyond the <del>end of the innermost enclosing <i>try-block</i> (if there is one)</del> <ins><i>compound-statement</i> of the innermost <i>try-block</i> or <i>function-try-block</i> (if any) whose <i>compound-statement</i> or <i>ctor-initializer</i> encloses the <i>throw-expression</i>,</ins></p></li>
</ul>

  <p>overload resolution to select the constructor for the copy or the <code>return_value</code> overload to call is first performed as if the <del>object were designated by</del> <ins>expression or operand were</ins> an rvalue. If the first overload resolution fails or was not performed, <del>or if the type of the first parameter of the selected constructor or the <code>return_value</code> overload is not an rvalue reference to the object's type (possibly cv-qualified),</del> overload resolution is performed again, considering the <del>object</del> <ins>expression or operand</ins> as an lvalue. [ Note: This two-stage overload resolution must be performed regardless of whether copy elision will occur. It determines the constructor or the <code>return_­value</code> overload to be called if elision is not performed, and the selected constructor or <del>the</del> <code>return_­value</code> overload must be accessible even if the call is elided. — end note ]</p>
  
<ins>[ Example: <pre><code>void f() {
  T x;
  try {
    T y;
    try {g(x);}
    catch(...) {
      if(/*...*/)
        throw x;                // does not move
      throw y;                  // moves
    }
    g(y);
  } catch(...) {
    g(x);
    // g(y); // error
  }
}</code></pre> -- end example ]</ins>
</blockquote>

<p>Change Annex C.5: [diff.cpp17.class] to add an additional entry:</p>

<blockquote>
  <ins>
  <p>Affected subclauses: [class.copy.elision]</p>
  
  <p>Change: A function returning an implicitly-movable entity may invoke a constructor taking an rvalue reference to a type different from that of the returned expression. Function and catch-clause parameters can be thrown using move constructors.</p>
  
  <p>Rationale: Side-effect of making it easier to write more efficient code that takes advantage of moves.</p>
  
  <p>Effect on original feature: Valid C++17 code may become ill-formed in this International Standard. For example:</p>
  
<pre><code>
struct base {
    base();
    base(base const &);
private:
    base(base &&);
};

struct derived : base {};

base f(base b) {
    throw b;        // error: base(base &&) is private
    derived d;
    return d;       // error: base(base &&) is private
}
</code></pre>
</blockquote>

