220 36370 <b6e25153-cfb5-4978-9095-5caabc3b82d1@isocpp.org> article
Path: news.gmane.org!.POSTED!not-for-mail
From: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Treating local variables as rvalues in return statements
Date: Tue, 26 Dec 2017 14:47:43 -0800 (PST)
Lines: 284
Approved: news@gmane.org
Message-ID: <b6e25153-cfb5-4978-9095-5caabc3b82d1@isocpp.org>
References: <4ff5fe2d-0945-491f-9888-479b8e866ace@isocpp.org>
 <d5b5434c-6300-4f82-92b4-a439696d6020@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_19528_511598247.1514328463535"
X-Trace: blaine.gmane.org 1514328351 17998 195.159.176.226 (26 Dec 2017 22:45:51 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Tue, 26 Dec 2017 22:45:51 +0000 (UTC)
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBDLZJYWNDQIJBI4L2ICRUBG24QAAQ@isocpp.org Tue Dec 26 23:45:47 2017
Return-path: <std-proposals+bncBDLZJYWNDQIJBI4L2ICRUBG24QAAQ@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-ua0-f199.google.com ([209.85.217.199])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBDLZJYWNDQIJBI4L2ICRUBG24QAAQ@isocpp.org>)
	id 1eTxyh-0004AL-Ma
	for gclcip-std-proposals@m.gmane.org; Tue, 26 Dec 2017 23:45:43 +0100
Original-Received: by mail-ua0-f199.google.com with SMTP id x25sf17280307uax.16
        for <gclcip-std-proposals@m.gmane.org>; Tue, 26 Dec 2017 14:47:46 -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=PzNjLCZvVCpW3AHhBPpT+vD9Zz4h6S8D25cPvSQhzko=;
        b=j0RFjIX0+LoMauGTzfnCYI5e6+aSnAOuXiTDon3SNu0dEnO0tGhxvT/xCOSfif9W68
         n6iIHG5YUSFpE5ZLyNaQIWzui45vr0Dxh8l/l4bEqcgOgRei5L/fmuKu9KpRaZy/Cyp8
         D34SopJkae+8mf4RB/PZXzauxo35Aj+tYAAcwtssaBgW9v9Ty8YdoeRo4+w5eNM5O2Kc
         HPpOlrODULyvxBWNRx8dhJ4/9rYl3o78mOMA5TgsUI3N+qj/5Us0whiIG4sUot2sMFsO
         IIG6LsEQlEG2TFANoZuJ9WHGoG5rXt9upRokkBnVJqEOY+NA4jE2DCgkFM26yJ+fUPOv
         TBNA==
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=PzNjLCZvVCpW3AHhBPpT+vD9Zz4h6S8D25cPvSQhzko=;
        b=I7zugyOwjsl0o9x+fHzCy8Cw49dDa4pW5bkpuLv5n0JLIn2QsOKwIy0+hiCMh0Oe3C
         CmLhjFkTtRGS6/cZ9JJHbmIlfzhK/uJN0rG5svnoKlKuUjb2CjcX+HyhZ6iFe+Q2nMVQ
         cSim9L0Gm+IyS4oAAM/Ejorn4Ic6NjQ551UBTRWifj7ydvQsWbbGDYTvofYrEUAvhEom
         Obi9Y23ht3dqtZwXut0OgupC1WgNsH2+wUoYGCMLOAAnLD3gIE3qK+8yoa2g1BUGGalX
         +OzZ25kiNy5CoZ2fYx2RlNlIScag1MHl3Yk14fvq013DAo2FLIARhtzvYFek0qogulOk
         KxHw==
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=PzNjLCZvVCpW3AHhBPpT+vD9Zz4h6S8D25cPvSQhzko=;
        b=OgLLXxnMalUkQsTAVI7GA1ig0k457bwiOWlsW4/Qbgq/ba4OPf951YnI0XLj+ctdbp
         CchkFqlDWMe0rnQkqKCXKJP3GheAZEIKmJLhaViFvpNZMMONf6qGdk6FtbrHJUB0lSsw
         ScLArgMi12FtHyyCiodeBukaU74Z/V4B5jy8tY+HC19Ol+c3nRAyOd0pfJMgsPxPTVYp
         XiBOKF7YqTezgA1FUk2KwUeWc2CODANaWsLa8sVDDVHZXeBdYcePkGxDnjcnS6c0UihA
         ep24vFuNS5bmr0ne8wbpgMb/N9UvoIQLHV6cqPxbeRdtDwPom0ydR58h396bmFhLQ4Sw
         Gk0Q==
X-Gm-Message-State: AKGB3mJ+0WLLGnDO14DrhYp3TjjeHbX/HJPVO2XpL01dmxuTWFajC3qE
	QZpmKUep/3VQu9TAewNp09MVWg==
X-Google-Smtp-Source: ACJfBovPK9m64m4MQNJNTyxhN7rN5qggmyyG0yAihOszEYnK46t+IOjRxJaq+T3V7LPrEG/zQEpDUw==
X-Received: by 10.31.152.194 with SMTP id a185mr12170090vke.34.1514328466187;
        Tue, 26 Dec 2017 14:47:46 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.159.54.65 with SMTP id s1ls3485861uad.16.gmail; Tue, 26 Dec
 2017 14:47:44 -0800 (PST)
X-Received: by 10.31.192.135 with SMTP id q129mr2472295vkf.0.1514328464033;
        Tue, 26 Dec 2017 14:47:44 -0800 (PST)
In-Reply-To: <d5b5434c-6300-4f82-92b4-a439696d6020@isocpp.org>
X-Original-Sender: arthur.j.odwyer@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:36370
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/36370>

------=_Part_19528_511598247.1514328463535
Content-Type: multipart/alternative; 
	boundary="----=_Part_19529_1659168147.1514328463536"

------=_Part_19529_1659168147.1514328463536
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Monday, December 25, 2017 at 7:17:12 PM UTC-8, Nicol Bolas wrote:
>
> On Monday, December 25, 2017 at 9:10:02 PM UTC-5, jgot...@gmail.com wrote=
:
>>
>> [...] For example, P0408r3=20
>> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0408r3.pdf> pr=
oposes=20
>> adding an rvalue overload to std::ostringstream's str() method that move=
s=20
>> instead of copies from the ostringstream's internal buffer.  Most functi=
ons=20
>> 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=20
>> overload of ostringstream::str().  In order to get the rvalue overload, =
the=20
>> user would have to return std::move(os).str(), which is not very intuiti=
ve.
>>
>
> The sooner people learn to use `std::move` when they want to move things,=
=20
> the better. "Intuitive" or not, it's better off in the long run to make=
=20
> moving explicit.
>

Yes. This is why LEWG decided that the correct name for this thingamajig=20
was "return std::move(os).str();" and not the next-most-popular contender,=
=20
"return os.pilfer();" =E2=80=94 because the latter would Do The Right Thing=
 only in=20
C++2a, and simply fail to compile in C++17-and-earlier, whereas the former=
=20
will Do The Right Thing in any dialect C++11-and-later. (In=20
C++17-and-earlier, pedantic mode, it will be less efficient; but it will=20
still compile and run correctly.)  Sufficiently forward-thinking C++11=20
users may already be using std::move(os).str() in real code.

=20

> I think that naturally treating os as an rvalue in this case could result=
=20
>> in faster code without programmers having to worry about where to put a=
=20
>> move statement.
>>
>
> It would also result in breaking lots of stuff. [...] Consider the=20
> following:
>
> std::string str =3D ...;
> return str + compute(str);
>
> [...] with your proposal [...] it will have* undefined* behavior, since=
=20
> `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=
=20
> have an lvalue, you are explicitly required to use `std::move` on it if y=
ou=20
> want to move it. Otherwise, it gets copied.
>
> `return variablename;` (and `throw variablename`) is the only case of=20
> implicit moving from an lvalue. And this case is the only one because it =
is=20
> guaranteed by the language that you cannot do anything with `variablename=
`=20
> after the move takes place.
>
> If you allow an arbitrary expression, that guarantee goes away.
>

Yes. Kind of. Actually in the case of `return` and `throw` you can't do=20
anything with the *name* variablename, but you can still access the=20
moved-from *object* (via the destructor of another local object that holds=
=20
a reference to it); it's just that this was considered a negligible risk.

And lets' not forget: the meaning of `return str + compute(str);` is alread=
y*=20
> well defined* in C++ right now. If you change its meaning, you are=20
> breaking people's existing code. Code that worked fine in C++98.
>

This, like any invocation of "ABI breakage," is a slight overreach.=20
Technically, when "return x;" became a move in C++11, it broke people's=20
code; and again when "return y;" (from a function with return type X)=20
became a move in C++17, it broke people's code; in that old code continued=
=20
to compile but now called different routines under the hood, so that the=20
same old code had perhaps-surprising new behavior. It's just that this=20
particular new behavior was generally seen as "awesome, yes, we want this=
=20
new behavior."

You're definitely right that we'll never get anything like

    return str + compute(str);  // move twice from str

and maybe never even

    return compute(str);  // move from str
    // ha ha! now we run RAII destructors for this frame's local objects,=
=20
and they see str in a moved-from state!

We just don't have suitable vocabulary and mental models for thinking about=
=20
this stuff yet. But I continue to hope that one day someone will have a=20
breakthrough and then we'll see how to build *something* along these lines=
=20
=E2=80=94 something that gets us the easy, source-compatible speed boosts w=
ithout=20
breaking too much existing code. Kind of like how rvalue semantics happened=
=20
in C++11. :)  What that breakthrough will *be*, I have no idea.

my $.02,
Arthur

--=20
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 e=
mail 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/b6e25153-cfb5-4978-9095-5caabc3b82d1%40isocpp.or=
g.

------=_Part_19529_1659168147.1514328463536
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Monday, December 25, 2017 at 7:17:12 PM UTC-8, Nicol Bo=
las 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"ltr">On =
Monday, December 25, 2017 at 9:10:02 PM UTC-5, <a>jgot...@gmail.com</a> wro=
te:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>[...] For =
example,=C2=A0<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers=
/2017/p0408r3.pdf" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.h=
ref=3D&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fj=
tc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2017%2Fp0408r3.pdf\x26sa\x3dD\x26sntz\x=
3d1\x26usg\x3dAFQjCNGbQSTAcF7Rw1pCBV081Mg96khyCw&#39;;return true;" onclick=
=3D"this.href=3D&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.open-s=
td.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2017%2Fp0408r3.pdf\x26sa\x3dD=
\x26sntz\x3d1\x26usg\x3dAFQjCNGbQSTAcF7Rw1pCBV081Mg96khyCw&#39;;return true=
;">P0408r3</a>=C2=A0proposes adding an rvalue overload to std::ostringstrea=
m&#39;s str() method that moves instead of copies from the ostringstream&#3=
9;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"color:#000"> to_string</span><span style=3D"color:#660">(</=
span><span style=3D"color:#008">const</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#606">MyType</span><font color=3D"#666600"><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#660">&amp;</span><span st=
yle=3D"color:#000">myType</span><span style=3D"color:#660">)</span><span st=
yle=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">::</s=
pan><span style=3D"color:#000">ostringstream os</span><span style=3D"color:=
#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span sty=
le=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">.</spa=
n><span style=3D"color:#000">str</span><span style=3D"color:#660">();</span=
><span style=3D"color:#000"><br></span><span style=3D"color:#660">}</span><=
/font></div></code></div><br>Even if P0408r3 were accepted, this function w=
ould call the lvalue overload of ostringstream::str().=C2=A0 In order to ge=
t the rvalue overload, the user would have to return std::move(os).str(), w=
hich is not very intuitive.</div></div></blockquote><div><br></div><div>The=
 sooner people learn to use `std::move` when they want to move things, the =
better. &quot;Intuitive&quot; or not, it&#39;s better off in the long run t=
o make moving explicit.</div></div></blockquote><div><br></div><div>Yes. Th=
is is why LEWG decided that the correct name for this thingamajig was &quot=
;return std::move(os).str();&quot; and not the next-most-popular contender,=
 &quot;return os.pilfer();&quot; =E2=80=94 because the latter would Do The =
Right Thing only in C++2a, and simply fail to compile in C++17-and-earlier,=
 whereas the former will Do The Right Thing in any dialect C++11-and-later.=
 (In C++17-and-earlier, pedantic mode, it will be less efficient; but it wi=
ll still compile and run correctly.) =C2=A0Sufficiently forward-thinking C+=
+11 users may already be using std::move(os).str() in real code.</div><div>=
<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v dir=3D"ltr"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:=
0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div>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.</div></div></blockquote><div><br></div><div>It wo=
uld also result in breaking lots of stuff. [...] Consider the following:</d=
iv><div><br></div><div><div style=3D"border:1px solid rgb(187,187,187);word=
-wrap:break-word;background-color:rgb(250,250,250)"><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"color:#000"> str </span><span s=
tyle=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">...;</span><span style=3D"color:#000"><br></span><span sty=
le=3D"color:#008">return</span><span style=3D"color:#000"> str </span><span=
 style=3D"color:#660">+</span><span style=3D"color:#000"> compute</span><sp=
an style=3D"color:#660">(</span><span style=3D"color:#000">str</span><span =
style=3D"color:#660">);</span></div></code></div><div><br></div><div>[...] =
with your proposal [...] it will have<i> undefined</i> behavior, since `str=
` will have been moved from by the time `operator+` gets called on it.</div=
><div><br></div><div>Stopping things like this is<i> precisely why</i> `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.</div><d=
iv><br></div><div>`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.</div><div><br></div><div>If you a=
llow an arbitrary expression, that guarantee goes away.</div></div></div></=
blockquote><div><br></div><div>Yes. Kind of. Actually in the case of `retur=
n` and `throw` you can&#39;t do anything with the <i>name</i> <font face=3D=
"courier new, monospace">variablename</font>, but you can still access the =
moved-from=C2=A0<i>object</i>=C2=A0(via the destructor of another local obj=
ect that holds a reference to it); it&#39;s just that this was considered a=
 negligible risk.</div><div><br></div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;"><div dir=3D"ltr"><div>And lets&#39; not forget: the meaning of `ret=
urn str + compute(str);` is already<i> well defined</i> in C++ right now. I=
f you change its meaning, you are breaking people&#39;s existing code. Code=
 that worked fine in C++98.<br></div></div></blockquote><div><br></div><div=
>This, like any invocation of &quot;ABI breakage,&quot; is a slight overrea=
ch. Technically, when &quot;return x;&quot; became a move in C++11, it brok=
e people&#39;s code; and again when &quot;return y;&quot; (from a function =
with return type X) became a move in C++17, it broke people&#39;s code; in =
that old code continued to compile but now called different routines under =
the hood, so that the same old code had perhaps-surprising new behavior. It=
&#39;s just that this particular new behavior was generally seen as &quot;a=
wesome, yes, we want this new behavior.&quot;</div><div><br></div><div>You&=
#39;re definitely right that we&#39;ll never get anything like</div><div><b=
r></div><div>=C2=A0 =C2=A0 return str + compute(str); =C2=A0// move twice f=
rom str</div><div><br></div><div>and maybe never even</div><div><br></div><=
div>=C2=A0 =C2=A0 return compute(str); =C2=A0// move from str</div><div>=C2=
=A0 =C2=A0 // ha ha! now we run RAII destructors for this frame&#39;s local=
 objects, and they see str in a moved-from state!</div><div><br></div><div>=
We just don&#39;t have suitable vocabulary and mental models for thinking a=
bout this stuff yet. But I continue to hope that one day someone will have =
a breakthrough and then we&#39;ll see how to build=C2=A0<i>something</i>=C2=
=A0along these lines =E2=80=94 something that gets us the easy, source-comp=
atible speed boosts without breaking too much existing code. Kind of like h=
ow rvalue semantics happened in C++11. :) =C2=A0What that breakthrough will=
 <i>be</i>, I have no idea.<br></div><div><br></div><div>my $.02,</div><div=
>Arthur</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/b6e25153-cfb5-4978-9095-5caabc3b82d1%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b6e25153-cfb5-4978-9095-5caabc3b82d1=
%40isocpp.org</a>.<br />

------=_Part_19529_1659168147.1514328463536--

------=_Part_19528_511598247.1514328463535--

.
