220 36349 <d5b5434c-6300-4f82-92b4-a439696d6020@isocpp.org> article
Path: news.gmane.org!.POSTED!not-for-mail
From: Nicol Bolas <jmckesson@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Treating local variables as rvalues in return statements
Date: Mon, 25 Dec 2017 19:17:11 -0800 (PST)
Lines: 388
Approved: news@gmane.org
Message-ID: <d5b5434c-6300-4f82-92b4-a439696d6020@isocpp.org>
References: <4ff5fe2d-0945-491f-9888-479b8e866ace@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_17373_1149245851.1514258232100"
X-Trace: blaine.gmane.org 1514258116 16999 195.159.176.226 (26 Dec 2017 03:15:16 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Tue, 26 Dec 2017 03:15:16 +0000 (UTC)
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBCEKFTV6ZUMBBOP6Q3JAKGQEAHQLDCQ@isocpp.org Tue Dec 26 04:15:12 2017
Return-path: <std-proposals+bncBCEKFTV6ZUMBBOP6Q3JAKGQEAHQLDCQ@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-vk0-f71.google.com ([209.85.213.71])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBCEKFTV6ZUMBBOP6Q3JAKGQEAHQLDCQ@isocpp.org>)
	id 1eTfhv-00044Y-O5
	for gclcip-std-proposals@m.gmane.org; Tue, 26 Dec 2017 04:15:12 +0100
Original-Received: by mail-vk0-f71.google.com with SMTP id u143sf14714494vkb.0
        for <gclcip-std-proposals@m.gmane.org>; Mon, 25 Dec 2017 19:17:14 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=date:from:to:message-id:in-reply-to:references:subject:mime-version
         :x-original-sender:reply-to:precedence:mailing-list:list-id
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=wtUnsS4mD+8kmEQBWyzWUhXuc09hB0LWJzf2GLKjwQ4=;
        b=QfcFN0nOxLRbtePKItfrJsksjokP7mVYk9JCCM2CZXCwKPoEOqgzv64uQ0wFYAAy0F
         wELpsGk9LABg2fedQTWt/fbcwOXLVyF1ZWEGmp+5QE+c0vY1l6UKB5r0+UHILIi1tEdT
         6ZXAPNzCbVwIOmgzNGHvT666MvR+oLqgL3TQvwee3PXCJrfGtjH4adD/WMSufILQkBHt
         rcAwY0gPqQBSuBKmCMqmc/db9zr/uexhbWS/VV1f6hl1oJk1nwOMBzR6QaJ1p2AcgmN7
         TuxuNlKqyxTe7DpeiWfPQFcmgr7RNNxH/WyqoQN5j+Yxbwb9UEq6/arvOSO60f06UyjI
         vsMA==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20161025;
        h=date:from:to:message-id:in-reply-to:references:subject:mime-version
         :x-original-sender:reply-to:precedence:mailing-list:list-id
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=wtUnsS4mD+8kmEQBWyzWUhXuc09hB0LWJzf2GLKjwQ4=;
        b=aN7lzMvc/yFViaawW9ojHk68Q15cy2+9lEqbf3EDLzI9nSPjphRDEwg4UKLa/4UsrG
         5uD2378VMlPcTmiBdqGXFQA6R9n0gcaLTzzzCbb5Oj0gEOW/BtfvJ9oHGrbj/YcGM9ho
         l9GEe+AYSsVzA6TJJkgB2Z1me6KRplFgP8/qcu8i1OS4dc8n6ACkMmm6KblIxedwRSmF
         K2xwMETx/i22iiIfhOVQZIe3R1lGGbW6rK1TuKIPwUZDJgHsXmp9sgIzVRbfva+zLNOr
         pRwlOoS42LLh42VK/N+QlJifqPJ/0wO0aaFwhOpItQ2jfNCoy0YCVrR5wWbwin5dd0/l
         sVsg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:date:from:to:message-id:in-reply-to:references
         :subject:mime-version:x-original-sender:reply-to:precedence
         :mailing-list:list-id:x-spam-checked-in-group:list-post:list-help
         :list-archive:list-subscribe:list-unsubscribe;
        bh=wtUnsS4mD+8kmEQBWyzWUhXuc09hB0LWJzf2GLKjwQ4=;
        b=rm+pi//dGq2B1I0E3sD9R7rLhTeRjKDerJM4+4j5rSfUhrpancF2IGxliTE0pc6mtl
         VsGhetV2vK63yVJUYUpQQbSRxl00Vi7ykS7/SYNsSuja0S9yG3cwCatzK99AVKQah/4v
         4JK6a9AHNl/pfpf1br5ZUEkamQ7KF2v8xLoHXgncyviIp5WpyJl4vlWTw0xxC/eE4Y2h
         q+WkjvLNb+yp3xNd6UTfGmTE0gwO6dRPLZVOh4B3D73LKVXM+LoIVYA+brYTm3iaDQyX
         DiNv4xY7bX7OtCpkzEtIpTiKheorUDw3ihBYjXtR5Zqs1+ksWxLw5naFKg2yX+/D4w52
         qFFg==
X-Gm-Message-State: AKGB3mI55rDp7B0PUHUN7pNFdATN/WmlLmYm15J9QIhTZXZ8n90O8909
	hdmWWLOM1r6PaKW19hpyU2v9IQ==
X-Google-Smtp-Source: ACJfBos3PskKlh39pyP7yG4gKx7ZPThy+OBa25kKImFdbR/NzWZ6xe8u4xSRKQQf5+1l4m0Z+4TPWA==
X-Received: by 10.31.191.1 with SMTP id p1mr11044701vkf.73.1514258234224;
        Mon, 25 Dec 2017 19:17:14 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.159.43.69 with SMTP id q5ls2834435uaj.17.gmail; Mon, 25 Dec
 2017 19:17:12 -0800 (PST)
X-Received: by 10.31.61.149 with SMTP id k143mr2233449vka.7.1514258232636;
        Mon, 25 Dec 2017 19:17:12 -0800 (PST)
In-Reply-To: <4ff5fe2d-0945-491f-9888-479b8e866ace@isocpp.org>
X-Original-Sender: jmckesson@gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Spam-Checked-In-Group: std-proposals@isocpp.org
X-Google-Group-Id: 399137483710
List-Post: <https://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <https://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <https://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:36349
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/36349>

------=_Part_17373_1149245851.1514258232100
Content-Type: multipart/alternative; 
	boundary="----=_Part_17374_1602619044.1514258232100"

------=_Part_17374_1602619044.1514258232100
Content-Type: text/plain; charset="UTF-8"

On Monday, December 25, 2017 at 9:10:02 PM UTC-5, jgot...@gmail.com wrote:
>
> Since C++11, if a function returns a local variable it will move from from 
> that variable.
>
> std::string foo(){
>  std::string output{"Hello world"};
>  return output; // output is treated as an rvalue and moved from.
> }
>
> However, if foo's return statement were something like  
> return my_function(output);
> then output would be treated as an lvalue, even though it is a local 
> variable that is about to go out of scope.  I think it could be a major 
> improvement if the local variable could be treated as an rvalue in this 
> case as well.  For example, P0408r3 
> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0408r3.pdf> proposes 
> adding an rvalue overload to std::ostringstream's str() method that moves 
> instead of copies from the ostringstream's internal buffer.  Most functions 
> that use ostringstreams look like the following:
>
> std::string to_string(const MyType &myType) {
>    std::ostringstream os;
>     // output the fields of myType to os.
>    return os.str();
> }
>
> Even if P0408r3 were accepted, this function would call the lvalue 
> overload of ostringstream::str().  In order to get the rvalue overload, the 
> user would have to return std::move(os).str(), which is not very intuitive.
>

The sooner people learn to use `std::move` when they want to move things, 
the better. "Intuitive" or not, it's better off in the long run to make 
moving explicit.

I think that naturally treating os as an rvalue in this case could result 
> in faster code without programmers having to worry about where to put a 
> move statement.
>

It would also result in breaking lots of stuff.

The reason why `return variablename;` can be treated as an rvalue is 
because it is a simple expression: one which does nothing more than name an 
automatic object. Once you allow this to involve anything more complicated 
than that, it now becomes possible to implicitly move from an lvalue and 
still access the moved-from object later.

That's bad. Consider the following:

std::string str = ...;
auto str2 = str + compute(str);
return str2;

That code should be equivalent to:

std::string str = ...;
return str + compute(str);

But with your proposal, it isn't. If `compute(str)` has an rvalue overload 
or an overload that takes a `string` by value, then these two pieces of 
code will have fundamentally different behavior. Specifically, it will have* 
undefined* behavior, since `str` will have been moved from by the time 
`operator+` gets called on it.

Stopping things like this is* precisely why* `std::move` exists. If you 
have an lvalue, you are explicitly required to use `std::move` on it if you 
want to move it. Otherwise, it gets copied.

`return variablename;` (and `throw variablename`) is the only case of 
implicit moving from an lvalue. And this case is the only one because it is 
guaranteed by the language that you cannot do anything with `variablename` 
after the move takes place.

If you allow an arbitrary expression, that guarantee goes away.

And lets' not forget: the meaning of `return str + compute(str);` is already* 
well defined* in C++ right now. If you change its meaning, you are breaking 
people's existing code. Code that worked fine in C++98.

-- 
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/d5b5434c-6300-4f82-92b4-a439696d6020%40isocpp.org.

------=_Part_17374_1602619044.1514258232100
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Monday, December 25, 2017 at 9:10:02 PM UTC-5, jgot...@=
gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt=
r">Since C++11, if a function returns a local variable it will move from fr=
om that variable.<div><br></div><div><div style=3D"background-color:rgb(250=
,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px=
;word-wrap:break-word"><code><div><span style=3D"color:#000">std</span><spa=
n style=3D"color:#660">::</span><span style=3D"color:#008">string</span><sp=
an style=3D"color:#000"> foo</span><span style=3D"color:#660">(){</span><sp=
an style=3D"color:#000"><br>=C2=A0std</span><span style=3D"color:#660">::</=
span><span style=3D"color:#008">string</span><span style=3D"color:#000"> ou=
tput</span><span style=3D"color:#660">{</span><span style=3D"color:#080">&q=
uot;Hello world&quot;</span><span style=3D"color:#660">};</span><font color=
=3D"#000000"><span style=3D"color:#000"><br>=C2=A0</span><span style=3D"col=
or:#008">return</span><span style=3D"color:#000"> output</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#800">// output is treated as an rvalue and moved from.</span><span st=
yle=3D"color:#000"><br></span><span style=3D"color:#660">}</span></font></d=
iv></code></div><br>However, if foo&#39;s return statement were something l=
ike=C2=A0=C2=A0<div style=3D"background-color:rgb(250,250,250);border-color=
:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break-word"=
><code><div><font color=3D"#660066"><span style=3D"color:#008">return</span=
><span style=3D"color:#000"> my_function</span><span style=3D"color:#660">(=
</span><span style=3D"color:#000">output</span><span style=3D"color:#660">)=
;</span></font></div></code></div>then output would be treated as an lvalue=
, even though it is a local variable that is about to go out of scope.=C2=
=A0 I think it could be a major improvement if the local variable could be =
treated as an rvalue in this case as well.=C2=A0 For example,=C2=A0<a onmou=
sedown=3D"this.href=3D&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.=
open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2017%2Fp0408r3.pdf\x26s=
a\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGbQSTAcF7Rw1pCBV081Mg96khyCw&#39;;retur=
n true;" onclick=3D"this.href=3D&#39;http://www.google.com/url?q\x3dhttp%3A=
%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2017%2Fp0408r=
3.pdf\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGbQSTAcF7Rw1pCBV081Mg96khyCw&=
#39;;return true;" href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/pape=
rs/2017/p0408r3.pdf" target=3D"_blank" rel=3D"nofollow">P0408r3</a>=C2=A0pr=
oposes adding an rvalue overload to std::ostringstream&#39;s str() method t=
hat moves instead of copies from the ostringstream&#39;s internal buffer.=
=C2=A0 Most functions that use ostringstreams look like the following:</div=
><div><br></div><div><div style=3D"background-color:rgb(250,250,250);border=
-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break=
-word"><code><div><span style=3D"color:#000">std</span><span style=3D"color=
:#660">::</span><span style=3D"color:#008">string</span><span style=3D"colo=
r:#000"> to_string</span><span style=3D"color:#660">(</span><span style=3D"=
color:#008">const</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#606">MyType</span><font color=3D"#666600"><span style=3D"color:#000">=
 </span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000">m=
yType</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> =
</span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0std</span><span style=3D"color:#660">::</span><span style=3D"c=
olor:#000">ostringstream os</span><span style=3D"color:#660">;</span><span =
style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#800">//=
 output the fields of myType to os.</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0</span><span style=3D"color:#008">return</span><span style=3D"=
color:#000"> os</span><span style=3D"color:#660">.</span><span style=3D"col=
or:#000">str</span><span style=3D"color:#660">();</span><span style=3D"colo=
r:#000"><br></span><span style=3D"color:#660">}</span></font></div></code><=
/div><br>Even if P0408r3 were accepted, this function would call the lvalue=
 overload of ostringstream::str().=C2=A0 In order to get the rvalue overloa=
d, the user would have to return std::move(os).str(), which is not very int=
uitive.</div></div></blockquote><div><br></div><div>The sooner people learn=
 to use `std::move` when they want to move things, the better. &quot;Intuit=
ive&quot; or not, it&#39;s better off in the long run to make moving explic=
it.</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div d=
ir=3D"ltr"><div>I think that naturally treating os as an rvalue in this cas=
e could result in faster code without programmers having to worry about whe=
re to put a move statement.</div></div></blockquote><div><br></div><div>It =
would also result in breaking lots of stuff.</div><div><br></div><div>The r=
eason why `return variablename;` can be treated as an rvalue is because it =
is a simple expression: one which does nothing more than name an automatic =
object. Once you allow this to involve anything more complicated than that,=
 it now becomes possible to implicitly move from an lvalue and still access=
 the moved-from object later.</div><div><br></div><div>That&#39;s bad. Cons=
ider the following:</div><div><br></div><div class=3D"prettyprint" style=3D=
"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; background-co=
lor: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subpret=
typrint"><span class=3D"styled-by-prettify" style=3D"color: #000;">std</spa=
n><span class=3D"styled-by-prettify" style=3D"color: #660;">::</span><span =
class=3D"styled-by-prettify" style=3D"color: #008;">string</span><span clas=
s=3D"styled-by-prettify" style=3D"color: #000;"> str </span><span class=3D"=
styled-by-prettify" style=3D"color: #660;">=3D</span><span class=3D"styled-=
by-prettify" style=3D"color: #000;"> </span><span class=3D"styled-by-pretti=
fy" style=3D"color: #660;">...;</span><span class=3D"styled-by-prettify" st=
yle=3D"color: #000;"><br></span><span class=3D"styled-by-prettify" style=3D=
"color: #008;">auto</span><span class=3D"styled-by-prettify" style=3D"color=
: #000;"> str2 </span><span class=3D"styled-by-prettify" style=3D"color: #6=
60;">=3D</span><span class=3D"styled-by-prettify" style=3D"color: #000;"> s=
tr </span><span class=3D"styled-by-prettify" style=3D"color: #660;">+</span=
><span class=3D"styled-by-prettify" style=3D"color: #000;"> compute</span><=
span class=3D"styled-by-prettify" style=3D"color: #660;">(</span><span clas=
s=3D"styled-by-prettify" style=3D"color: #000;">str</span><span class=3D"st=
yled-by-prettify" style=3D"color: #660;">);</span><span class=3D"styled-by-=
prettify" style=3D"color: #000;"><br></span><span class=3D"styled-by-pretti=
fy" style=3D"color: #008;">return</span><span class=3D"styled-by-prettify" =
style=3D"color: #000;"> str2</span><span class=3D"styled-by-prettify" style=
=3D"color: #660;">;</span></div></code></div><div><br></div><div>That code =
should be equivalent to:</div><div><br></div><div><div class=3D"prettyprint=
" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; bac=
kground-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=
=3D"subprettyprint"><span class=3D"styled-by-prettify" style=3D"color: #000=
;">std</span><span class=3D"styled-by-prettify" style=3D"color: #660;">::</=
span><span class=3D"styled-by-prettify" style=3D"color: #008;">string</span=
><span class=3D"styled-by-prettify" style=3D"color: #000;"> str </span><spa=
n class=3D"styled-by-prettify" style=3D"color: #660;">=3D</span><span class=
=3D"styled-by-prettify" style=3D"color: #000;"> </span><span class=3D"style=
d-by-prettify" style=3D"color: #660;">...;</span><span class=3D"styled-by-p=
rettify" style=3D"color: #000;"><br></span><span class=3D"styled-by-prettif=
y" style=3D"color: #008;">return</span><span class=3D"styled-by-prettify" s=
tyle=3D"color: #000;"> str </span><span class=3D"styled-by-prettify" style=
=3D"color: #660;">+</span><span class=3D"styled-by-prettify" style=3D"color=
: #000;"> compute</span><span class=3D"styled-by-prettify" style=3D"color: =
#660;">(</span><span class=3D"styled-by-prettify" style=3D"color: #000;">st=
r</span><span class=3D"styled-by-prettify" style=3D"color: #660;">);</span>=
</div></code></div><div style=3D"background-color: transparent; border-bott=
om-color: rgb(34, 34, 34); border-bottom-style: none; border-bottom-width: =
0px; border-image-outset: 0; border-image-repeat: stretch; border-image-sli=
ce: 100%; border-image-source: none; border-image-width: 1; border-left-col=
or: rgb(34, 34, 34); border-left-style: none; border-left-width: 0px; borde=
r-right-color: rgb(34, 34, 34); border-right-style: none; border-right-widt=
h: 0px; border-top-color: rgb(34, 34, 34); border-top-style: none; border-t=
op-width: 0px; color: rgb(34, 34, 34); font-family: &amp;quot;Arial&amp;quo=
t;,&amp;quot;Helvetica&amp;quot;,sans-serif; font-size: 13px; font-style: n=
ormal; font-variant: normal; font-weight: 400; letter-spacing: normal; marg=
in-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; orpha=
ns: 2; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-=
top: 0px; text-align: left; text-decoration: none; text-indent: 0px; text-t=
ransform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-s=
pacing: 0px;"><br></div><div style=3D"background-color: transparent; border=
-bottom-color: rgb(34, 34, 34); border-bottom-style: none; border-bottom-wi=
dth: 0px; border-image-outset: 0; border-image-repeat: stretch; border-imag=
e-slice: 100%; border-image-source: none; border-image-width: 1; border-lef=
t-color: rgb(34, 34, 34); border-left-style: none; border-left-width: 0px; =
border-right-color: rgb(34, 34, 34); border-right-style: none; border-right=
-width: 0px; border-top-color: rgb(34, 34, 34); border-top-style: none; bor=
der-top-width: 0px; color: rgb(34, 34, 34); font-family: &amp;quot;Arial&am=
p;quot;,&amp;quot;Helvetica&amp;quot;,sans-serif; font-size: 13px; font-sty=
le: normal; font-variant: normal; font-weight: 400; letter-spacing: normal;=
 margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; =
orphans: 2; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; pad=
ding-top: 0px; text-align: left; text-decoration: none; text-indent: 0px; t=
ext-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; w=
ord-spacing: 0px;">But with your proposal, it isn&#39;t. If `compute(str)` =
has an rvalue overload or an overload that takes a `string` by value, then =
these two pieces of code will have fundamentally different behavior. Specif=
ically, it will have<i> undefined</i> behavior, since `str` will have been =
moved from by the time `operator+` gets called on it.</div><div style=3D"ba=
ckground-color: transparent; border-bottom-color: rgb(34, 34, 34); border-b=
ottom-style: none; border-bottom-width: 0px; border-image-outset: 0; border=
-image-repeat: stretch; border-image-slice: 100%; border-image-source: none=
; border-image-width: 1; border-left-color: rgb(34, 34, 34); border-left-st=
yle: none; border-left-width: 0px; border-right-color: rgb(34, 34, 34); bor=
der-right-style: none; border-right-width: 0px; border-top-color: rgb(34, 3=
4, 34); border-top-style: none; border-top-width: 0px; color: rgb(34, 34, 3=
4); font-family: &amp;quot;Arial&amp;quot;,&amp;quot;Helvetica&amp;quot;,sa=
ns-serif; font-size: 13px; font-style: normal; font-variant: normal; font-w=
eight: 400; letter-spacing: normal; margin-bottom: 0px; margin-left: 0px; m=
argin-right: 0px; margin-top: 0px; orphans: 2; padding-bottom: 0px; padding=
-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; text-de=
coration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke=
-width: 0px; white-space: normal; word-spacing: 0px;"><br></div><div style=
=3D"background-color: transparent; border-bottom-color: rgb(34, 34, 34); bo=
rder-bottom-style: none; border-bottom-width: 0px; border-image-outset: 0; =
border-image-repeat: stretch; border-image-slice: 100%; border-image-source=
: none; border-image-width: 1; border-left-color: rgb(34, 34, 34); border-l=
eft-style: none; border-left-width: 0px; border-right-color: rgb(34, 34, 34=
); border-right-style: none; border-right-width: 0px; border-top-color: rgb=
(34, 34, 34); border-top-style: none; border-top-width: 0px; color: rgb(34,=
 34, 34); font-family: &amp;quot;Arial&amp;quot;,&amp;quot;Helvetica&amp;qu=
ot;,sans-serif; font-size: 13px; font-style: normal; font-variant: normal; =
font-weight: 400; letter-spacing: normal; margin-bottom: 0px; margin-left: =
0px; margin-right: 0px; margin-top: 0px; orphans: 2; padding-bottom: 0px; p=
adding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; t=
ext-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-=
stroke-width: 0px; white-space: normal; word-spacing: 0px;">Stopping things=
 like this is<i> precisely why</i> `std::move` exists. If you have an lvalu=
e, you are explicitly required to use `std::move` on it if you want to move=
 it. Otherwise, it gets copied.</div><div style=3D"background-color: transp=
arent; border-bottom-color: rgb(34, 34, 34); border-bottom-style: none; bor=
der-bottom-width: 0px; border-image-outset: 0; border-image-repeat: stretch=
; border-image-slice: 100%; border-image-source: none; border-image-width: =
1; border-left-color: rgb(34, 34, 34); border-left-style: none; border-left=
-width: 0px; border-right-color: rgb(34, 34, 34); border-right-style: none;=
 border-right-width: 0px; border-top-color: rgb(34, 34, 34); border-top-sty=
le: none; border-top-width: 0px; color: rgb(34, 34, 34); font-family: &amp;=
quot;Arial&amp;quot;,&amp;quot;Helvetica&amp;quot;,sans-serif; font-size: 1=
3px; font-style: normal; font-variant: normal; font-weight: 400; letter-spa=
cing: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; marg=
in-top: 0px; orphans: 2; padding-bottom: 0px; padding-left: 0px; padding-ri=
ght: 0px; padding-top: 0px; text-align: left; text-decoration: none; text-i=
ndent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-spa=
ce: normal; word-spacing: 0px;"><br></div><div style=3D"background-color: t=
ransparent; border-bottom-color: rgb(34, 34, 34); border-bottom-style: none=
; border-bottom-width: 0px; border-image-outset: 0; border-image-repeat: st=
retch; border-image-slice: 100%; border-image-source: none; border-image-wi=
dth: 1; border-left-color: rgb(34, 34, 34); border-left-style: none; border=
-left-width: 0px; border-right-color: rgb(34, 34, 34); border-right-style: =
none; border-right-width: 0px; border-top-color: rgb(34, 34, 34); border-to=
p-style: none; border-top-width: 0px; color: rgb(34, 34, 34); font-family: =
&amp;quot;Arial&amp;quot;,&amp;quot;Helvetica&amp;quot;,sans-serif; font-si=
ze: 13px; font-style: normal; font-variant: normal; font-weight: 400; lette=
r-spacing: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px;=
 margin-top: 0px; orphans: 2; padding-bottom: 0px; padding-left: 0px; paddi=
ng-right: 0px; padding-top: 0px; text-align: left; text-decoration: none; t=
ext-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; whit=
e-space: normal; word-spacing: 0px;">`return variablename;` (and `throw var=
iablename`) is the only case of implicit moving from an lvalue. And this ca=
se is the only one because it is guaranteed by the language that you cannot=
 do anything with `variablename` after the move takes place.</div><div styl=
e=3D"background-color: transparent; border-bottom-color: rgb(34, 34, 34); b=
order-bottom-style: none; border-bottom-width: 0px; border-image-outset: 0;=
 border-image-repeat: stretch; border-image-slice: 100%; border-image-sourc=
e: none; border-image-width: 1; border-left-color: rgb(34, 34, 34); border-=
left-style: none; border-left-width: 0px; border-right-color: rgb(34, 34, 3=
4); border-right-style: none; border-right-width: 0px; border-top-color: rg=
b(34, 34, 34); border-top-style: none; border-top-width: 0px; color: rgb(34=
, 34, 34); font-family: &amp;quot;Arial&amp;quot;,&amp;quot;Helvetica&amp;q=
uot;,sans-serif; font-size: 13px; font-style: normal; font-variant: normal;=
 font-weight: 400; letter-spacing: normal; margin-bottom: 0px; margin-left:=
 0px; margin-right: 0px; margin-top: 0px; orphans: 2; padding-bottom: 0px; =
padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; =
text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text=
-stroke-width: 0px; white-space: normal; word-spacing: 0px;"><br></div><div=
 style=3D"background-color: transparent; border-bottom-color: rgb(34, 34, 3=
4); border-bottom-style: none; border-bottom-width: 0px; border-image-outse=
t: 0; border-image-repeat: stretch; border-image-slice: 100%; border-image-=
source: none; border-image-width: 1; border-left-color: rgb(34, 34, 34); bo=
rder-left-style: none; border-left-width: 0px; border-right-color: rgb(34, =
34, 34); border-right-style: none; border-right-width: 0px; border-top-colo=
r: rgb(34, 34, 34); border-top-style: none; border-top-width: 0px; color: r=
gb(34, 34, 34); font-family: &amp;quot;Arial&amp;quot;,&amp;quot;Helvetica&=
amp;quot;,sans-serif; font-size: 13px; font-style: normal; font-variant: no=
rmal; font-weight: 400; letter-spacing: normal; margin-bottom: 0px; margin-=
left: 0px; margin-right: 0px; margin-top: 0px; orphans: 2; padding-bottom: =
0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: l=
eft; text-decoration: none; text-indent: 0px; text-transform: none; -webkit=
-text-stroke-width: 0px; white-space: normal; word-spacing: 0px;">If you al=
low an arbitrary expression, that guarantee goes away.</div><div style=3D"b=
ackground-color: transparent; border-bottom-color: rgb(34, 34, 34); border-=
bottom-style: none; border-bottom-width: 0px; border-image-outset: 0; borde=
r-image-repeat: stretch; border-image-slice: 100%; border-image-source: non=
e; border-image-width: 1; border-left-color: rgb(34, 34, 34); border-left-s=
tyle: none; border-left-width: 0px; border-right-color: rgb(34, 34, 34); bo=
rder-right-style: none; border-right-width: 0px; border-top-color: rgb(34, =
34, 34); border-top-style: none; border-top-width: 0px; color: rgb(34, 34, =
34); font-family: &amp;quot;Arial&amp;quot;,&amp;quot;Helvetica&amp;quot;,s=
ans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-=
weight: 400; letter-spacing: normal; margin-bottom: 0px; margin-left: 0px; =
margin-right: 0px; margin-top: 0px; orphans: 2; padding-bottom: 0px; paddin=
g-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; text-d=
ecoration: none; text-indent: 0px; text-transform: none; -webkit-text-strok=
e-width: 0px; white-space: normal; word-spacing: 0px;"><br></div><div style=
=3D"background-color: transparent; border-bottom-color: rgb(34, 34, 34); bo=
rder-bottom-style: none; border-bottom-width: 0px; border-image-outset: 0; =
border-image-repeat: stretch; border-image-slice: 100%; border-image-source=
: none; border-image-width: 1; border-left-color: rgb(34, 34, 34); border-l=
eft-style: none; border-left-width: 0px; border-right-color: rgb(34, 34, 34=
); border-right-style: none; border-right-width: 0px; border-top-color: rgb=
(34, 34, 34); border-top-style: none; border-top-width: 0px; color: rgb(34,=
 34, 34); font-family: &amp;quot;Arial&amp;quot;,&amp;quot;Helvetica&amp;qu=
ot;,sans-serif; font-size: 13px; font-style: normal; font-variant: normal; =
font-weight: 400; letter-spacing: normal; margin-bottom: 0px; margin-left: =
0px; margin-right: 0px; margin-top: 0px; orphans: 2; padding-bottom: 0px; p=
adding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; t=
ext-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-=
stroke-width: 0px; white-space: normal; word-spacing: 0px;">And lets&#39; n=
ot forget: the meaning of `return str + compute(str);` is already<i> well d=
efined</i> in C++ right now. If you change its meaning, you are breaking pe=
ople&#39;s existing code. Code that worked fine in C++98.</div></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/d5b5434c-6300-4f82-92b4-a439696d6020%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/d5b5434c-6300-4f82-92b4-a439696d6020=
%40isocpp.org</a>.<br />

------=_Part_17374_1602619044.1514258232100--

------=_Part_17373_1149245851.1514258232100--

.
