<!DOCTYPE html><html><head><meta charset="utf-8"><title>Untitled Document.md</title><style></style></head><body id="preview">
<p>Document number: P0527R0<br>
Date: 2017-02-05<br>
Project: Programming Language C++, Evolution Working Group<br>
Reply-to: David Stone: <a href="mailto:david@doublewise.net">david@doublewise.net</a></p>
<h1><a id="Implicitly_move_from_rvalue_references_in_return_statements_5"></a>Implicitly move from rvalue references in return statements</h1>
<h2><a id="Introduction_7"></a>Introduction</h2>
<p>A function return statement will automatically invoke a move rather than a copy in some situations. This proposal slightly extends those situations.</p>
<h2><a id="Return_Statements_12"></a>Return Statements</h2>
<p>We already have implicit moves for local values and function parameters in a return statement. The following code compiles just fine:</p>
<pre><code>    std::unique_ptr&lt;T&gt; f(std::unique_ptr&lt;T&gt; ptr) {
        return ptr;
    }
</code></pre>
<p>However, the following code does not compile</p>
<pre><code>    std::unique_ptr&lt;T&gt; f(std::unique_ptr&lt;T&gt; &amp;&amp; ptr) {
        return ptr;
    }
</code></pre>
<p>Instead, you must type</p>
<pre><code>    std::unique_ptr&lt;T&gt; f(std::unique_ptr&lt;T&gt; &amp;&amp; ptr) {
        return std::move(ptr);
    }
</code></pre>
<p>This extra typing is unnecessary and leads to possible inefficiencies. Consider the generic case:</p>
<pre><code>    auto f(args...) {
        decltype(auto) result = some_other_function();
        return std::forward&lt;decltype(result)&gt;(result);
    }
</code></pre>
<p>Now we have inhibited return-value optimization (RVO) in the case where <code>result</code> is a value and not a reference, but without the <code>std::forward</code>, the code does not compile if <code>result</code> is an rvalue reference and is move-only.</p>
<pre><code>    auto f(T &amp;&amp; value) {
        // do stuff with value
        return value;
    }
</code></pre>
<p>Using move constructors instead of copy constructors can be critical for writing high-performance C++ code. However, due to the rules of when a move is invoked in a return statement, a user who knows most (but not all) of the rules is likely to accidentally invoke a copy when they mean to invoke a move.</p>
<p>For instance, consider the following two functions:</p>
<pre><code>    std::string f(std::string x) { return x; }
    std::string g(std::string &amp;&amp; x) { return x; }
</code></pre>
<p>The function <code>f</code> will invoke the move constructor of <code>x</code>, but the function <code>g</code> will invoke the copy constructor.</p>
<p>I believe that it is more surprising to the user that a move does not occur in this situation than it would be if a move did occur. The only way to get an rvalue reference to something is if it was bound to a prvalue or if the user explicitly called <code>std::move</code> or equivalent. This means that either it is definitely safe (due to being bound to a prvalue) or the user explicitly opted in to moves at some point.</p>
<h2><a id="Throw_Expressions_57"></a>Throw Expressions</h2>
<p>Current rules also prevent the compiler from implicitly moving from function parameters in any situation for a throw expression. However, at least one production compiler (clang) does not implement this correctly and implicitly moves from function parameters. This proposal also extends these rules to throw expressions, requiring using a move instead of a copy for local variable and function parameter objects and rvalue references. This proposal also removes the restriction on implicitly moving from a catch-clause parameter in a throw expression. At least one production compiler (gcc) does not implement this correctly and implicitly moves from catch-clause parameters in throw expressions.</p>
<p>This does not cause problems with function parameters and function-scope try-blocks because there is already a rule preventing crossing try-block scope boundaries in implicit moves.</p>
<p>This proposal unifies the treatment of return statements and throw expressions.</p>
<h2><a id="Effect_On_the_Standard_Library_66"></a>Effect On the Standard Library</h2>
<p>This proposal is unlikely to have any effect on the standard library, as we typically do not describe function bodies, but rather, function signatures.</p>
<h2><a id="Specification_71"></a>Specification</h2>
<p>Update [class.copy.elision/3.1] and [class.copy.elision/3.2] to say (additions in <strong>bold</strong>)</p>
<p>(3.1)</p>
<p>If the expression in a return statement is a (possibly parenthesized) id-expression that names an object <strong>or an rvalue reference, and that entity has</strong> <s>with</s> automatic storage duration <strong>and is</strong> declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, or</p>
<p>(3.2)</p>
<p>if the operand of a throw-expression is the name of a non-volatile automatic object <strong>or rvalue reference, and the scope of that entity</strong> <s>(other than a function or catch-clause parameter) whose scope</s> does not extend beyond the end of the innermost enclosing try-block (if there is one),</p>

</body></html>