Topic: Treating local variables as rvalues in return statements


Author: jgottman6@gmail.com
Date: Mon, 25 Dec 2017 18:10:02 -0800 (PST)
Raw View
------=_Part_16888_358189822.1514254202693
Content-Type: multipart/alternative;
 boundary="----=_Part_16889_293035515.1514254202693"

------=_Part_16889_293035515.1514254202693
Content-Type: text/plain; charset="UTF-8"

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.  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.

Joe Gottman

--
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/4ff5fe2d-0945-491f-9888-479b8e866ace%40isocpp.org.

------=_Part_16889_293035515.1514254202693
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Since C++11, if a function returns a local variable it wil=
l move from from that variable.<div><br></div><div><div class=3D"prettyprin=
t" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 18=
7, 187); border-style: solid; border-width: 1px; word-wrap: break-word;"><c=
ode class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">std</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">::</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">string</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> foo</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">(){</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br>=C2=A0std</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">::</span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">string</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> o=
utput</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span style=3D"color: #080;" class=3D"styled-by-prettify">&quot;Hello wo=
rld&quot;</span><span style=3D"color: #660;" class=3D"styled-by-prettify">}=
;</span><font color=3D"#000000"><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0</span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> output</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #800;" class=3D"styled-by-prettify">// output =
is treated as an rvalue and moved from.</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span></font></div></code></div><br>However, if f=
oo&#39;s return statement were something like=C2=A0=C2=A0<div class=3D"pret=
typrint" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(1=
87, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-wor=
d;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><font color=
=3D"#660066"><span style=3D"color: #008;" class=3D"styled-by-prettify">retu=
rn</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> my_func=
tion</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">output</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">);</span></font></d=
iv></code></div>then output would be treated as an lvalue, even though it i=
s 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 href=3D"http://www.open-s=
td.org/jtc1/sc22/wg21/docs/papers/2017/p0408r3.pdf">P0408r3</a>=C2=A0propos=
es adding an rvalue overload to std::ostringstream&#39;s str() method that =
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 class=3D"prettyprint" style=3D"background-color: rgb(25=
0, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; border=
-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=
=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">string</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> to_string</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">const</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">MyType</span><font color=3D"#666600">=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">myType</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 =C2=A0std</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">ostringstream os</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">// output the fields of myType to os.</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0</span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> os</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">str</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">();</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">}</span></font></div></code></div><br><br></div><div>Even=
 if P0408r3 were accepted, this function would call the lvalue overload of =
ostringstream::str().=C2=A0 In order to get the rvalue overload, the user w=
ould have to return std::move(os).str(), which is not very intuitive.=C2=A0=
 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 mov=
e statement.</div><div><br></div><div>Joe Gottman</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/4ff5fe2d-0945-491f-9888-479b8e866ace%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4ff5fe2d-0945-491f-9888-479b8e866ace=
%40isocpp.org</a>.<br />

------=_Part_16889_293035515.1514254202693--

------=_Part_16888_358189822.1514254202693--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 25 Dec 2017 19:17:11 -0800 (PST)
Raw View
------=_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--

.


Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Date: Tue, 26 Dec 2017 14:47:43 -0800 (PST)
Raw View
------=_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--

.


Author: olafvdspek@gmail.com
Date: Wed, 3 Jan 2018 02:51:05 -0800 (PST)
Raw View
------=_Part_2553_329857212.1514976665987
Content-Type: multipart/alternative;
 boundary="----=_Part_2554_1975210151.1514976665987"

------=_Part_2554_1975210151.1514976665987
Content-Type: text/plain; charset="UTF-8"



Op dinsdag 26 december 2017 04:17:12 UTC+1 schreef Nicol Bolas:
>
> 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.
>

Wouldn't the idea be to do the analysis and only consider it a rvalue if
it's NOT accessed later in the statement / function?

--
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/55bb7162-834a-4ba4-bd68-915470842430%40isocpp.org.

------=_Part_2554_1975210151.1514976665987
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>Op dinsdag 26 december 2017 04:17:12 UTC+1 schreef=
 Nicol Bolas:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
<div>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 piec=
es of code will have fundamentally different behavior. Specifically, it wil=
l have<i> undefined</i> behavior, since `str` will have been moved from by =
the time `operator+` gets called on it.</div></div></blockquote><div><br></=
div><div>Wouldn&#39;t the idea be to do the analysis and only consider it a=
 rvalue if it&#39;s NOT accessed later in the statement / function?=C2=A0</=
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/55bb7162-834a-4ba4-bd68-915470842430%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/55bb7162-834a-4ba4-bd68-915470842430=
%40isocpp.org</a>.<br />

------=_Part_2554_1975210151.1514976665987--

------=_Part_2553_329857212.1514976665987--

.


Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 03 Jan 2018 09:33:21 -0200
Raw View
On Wednesday, 3 January 2018 08:51:05 -02 olafvdspek@gmail.com wrote:
> Wouldn't the idea be to do the analysis and only consider it a rvalue if
> it's NOT accessed later in the statement / function?

And its address has never been taken, which also means it must never have been
passed by reference either. That limits the usefulness too much to make it a
feature.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center

--
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/1823126.nxGvHgdJMA%40tjmaciei-mobl1.

.


Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Wed, 3 Jan 2018 13:32:40 +0100
Raw View
2018-01-03 12:33 GMT+01:00 Thiago Macieira <thiago@macieira.org>:
> On Wednesday, 3 January 2018 08:51:05 -02 olafvdspek@gmail.com wrote:
>> Wouldn't the idea be to do the analysis and only consider it a rvalue if
>> it's NOT accessed later in the statement / function?
>
> And its address has never been taken, which also means it must never have been
> passed by reference either. That limits the usefulness too much to make it a
> feature.

Taking the address is fine as long as all references are dead by the
time it's considered an rvalue.


--
Olaf

--
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/CAA7U3HPMh9VHo_16djyzT0KnzVf%2Bab0Nm2CoU7zFfKJqCyfJ3w%40mail.gmail.com.

.


Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 03 Jan 2018 11:31:26 -0200
Raw View
On Wednesday, 3 January 2018 10:32:40 -02 Olaf van der Spek wrote:
> 2018-01-03 12:33 GMT+01:00 Thiago Macieira <thiago@macieira.org>:
> > On Wednesday, 3 January 2018 08:51:05 -02 olafvdspek@gmail.com wrote:
> >> Wouldn't the idea be to do the analysis and only consider it a rvalue if
> >> it's NOT accessed later in the statement / function?
> >
> > And its address has never been taken, which also means it must never have
> > been passed by reference either. That limits the usefulness too much to
> > make it a feature.
>
> Taking the address is fine as long as all references are dead by the
> time it's considered an rvalue.

And how do you prove that they are?

Please answer in standardese, not in terms of compiler optimisations.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center

--
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/3356554.N1GgDjyayG%40tjmaciei-mobl1.

.


Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Wed, 3 Jan 2018 14:39:51 +0100
Raw View
2018-01-03 14:31 GMT+01:00 Thiago Macieira <thiago@macieira.org>:
> On Wednesday, 3 January 2018 10:32:40 -02 Olaf van der Spek wrote:
>> 2018-01-03 12:33 GMT+01:00 Thiago Macieira <thiago@macieira.org>:
>> > On Wednesday, 3 January 2018 08:51:05 -02 olafvdspek@gmail.com wrote:
>> >> Wouldn't the idea be to do the analysis and only consider it a rvalue if
>> >> it's NOT accessed later in the statement / function?
>> >
>> > And its address has never been taken, which also means it must never have
>> > been passed by reference either. That limits the usefulness too much to
>> > make it a feature.
>>
>> Taking the address is fine as long as all references are dead by the
>> time it's considered an rvalue.
>
> And how do you prove that they are?
>
> Please answer in standardese, not in terms of compiler optimisations.

Why?
An idea isn't bad just because standardese isn't available (yet).

I'm also not saying this is easy to do or worthwhile to focus on BTW.


Gr,
--
Olaf

--
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/CAA7U3HMDj3r5M70izHb30%2Bo1xHqUhgYX2KERBvvvgeAsq--muA%40mail.gmail.com.

.


Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 03 Jan 2018 11:50:01 -0200
Raw View
On Wednesday, 3 January 2018 11:39:51 -02 Olaf van der Spek wrote:
> 2018-01-03 14:31 GMT+01:00 Thiago Macieira <thiago@macieira.org>:
> > On Wednesday, 3 January 2018 10:32:40 -02 Olaf van der Spek wrote:
> >> 2018-01-03 12:33 GMT+01:00 Thiago Macieira <thiago@macieira.org>:
> >> > On Wednesday, 3 January 2018 08:51:05 -02 olafvdspek@gmail.com wrote:
> >> >> Wouldn't the idea be to do the analysis and only consider it a rvalue
> >> >> if
> >> >> it's NOT accessed later in the statement / function?
> >> >
> >> > And its address has never been taken, which also means it must never
> >> > have
> >> > been passed by reference either. That limits the usefulness too much to
> >> > make it a feature.
> >>
> >> Taking the address is fine as long as all references are dead by the
> >> time it's considered an rvalue.
> >
> > And how do you prove that they are?
> >
> > Please answer in standardese, not in terms of compiler optimisations.
>
> Why?
> An idea isn't bad just because standardese isn't available (yet).

Because I have the suspicion that it can't exist at all. The idea is bad if it
can't be described meaningfully.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center

--
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/2503165.NFYEXWA1nm%40tjmaciei-mobl1.

.


Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Wed, 3 Jan 2018 14:51:33 +0100
Raw View
2018-01-03 14:50 GMT+01:00 Thiago Macieira <thiago@macieira.org>:
>> Why?
>> An idea isn't bad just because standardese isn't available (yet).
>
> Because I have the suspicion that it can't exist at all. The idea is bad if it
> can't be described meaningfully.

Fair enough.
Escape analysis isn't a new thing though:
https://en.wikipedia.org/wiki/Escape_analysis


--
Olaf

--
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/CAA7U3HO7eRNcHuzV38A0jtiZ-dbywnHTEP2Y6yz4oj5KHhCgrg%40mail.gmail.com.

.


Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 03 Jan 2018 13:35:24 -0200
Raw View
On Wednesday, 3 January 2018 11:51:33 -02 Olaf van der Spek wrote:
> 2018-01-03 14:50 GMT+01:00 Thiago Macieira <thiago@macieira.org>:
> >> Why?
> >> An idea isn't bad just because standardese isn't available (yet).
> >
> > Because I have the suspicion that it can't exist at all. The idea is bad
> > if it can't be described meaningfully.
>
> Fair enough.
> Escape analysis isn't a new thing though:
> https://en.wikipedia.org/wiki/Escape_analysis

Right, but there's a difference in using that for optimisations and using it
for mandatory behaviour. Using escape analysis to determine if a given local,
automatic variable could be modified by a given function call is one thing.
Using it to determine whether to call a copy constructor versus a move
constructor is an entirely different situation.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center

--
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/3124075.L0jXXNC7oo%40tjmaciei-mobl1.

.


Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Wed, 3 Jan 2018 11:05:10 -0800
Raw View
--f403045c28b8fa3ae30561e3e423
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Wed, Jan 3, 2018 at 5:31 AM, Thiago Macieira <thiago@macieira.org> wrote=
:

> On Wednesday, 3 January 2018 10:32:40 -02 Olaf van der Spek wrote:
> > 2018-01-03 12:33 GMT+01:00 Thiago Macieira <thiago@macieira.org>:
> > > On Wednesday, 3 January 2018 08:51:05 -02 olafvdspek@gmail.com wrote:
> > >> Wouldn't the idea be to do the analysis and only consider it a rvalu=
e
> if
> > >> it's NOT accessed later in the statement / function?
> > >
> > > And its address has never been taken, which also means it must never
> have
> > > been passed by reference either. That limits the usefulness too much =
to
> > > make it a feature.
> >
> > Taking the address is fine as long as all references are dead by the
> > time it's considered an rvalue.
>
> And how do you prove that they are?
>

Guys, you're going down an unnecessary rabbit hole here.
The way C++11 solved the problem was just to say that *it doesn't matter*
if there's a live reference or not. Certain syntactic constructs simply
turn into moves (not copies), *regardless* of the number of live references
to the operand.

https://wandbox.org/permlink/DIveFuEiL5JzSkOj
(The output "moved from" indicates that we're observing `Observable o`
*after* it has been moved from, via the reference we stashed.)

Also, please remember that even in simple cases with no aliasing at all,
moving-from an object *does not end its lifetime*. Every object is accessed
at least once after its "last" move-access =E2=80=94 namely, when it is ref=
erenced
by the `this` argument of its own destructor. Moves are *always*
observable. Trying to "hide" moves or pretend that you can do them under
the as-if rule will never work. You *must* confront the human factor
head-on: Which syntactic constructs do human programmers "expect" to
produce moves, and which do they "expect" to produce copies?

HTH,
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/CADvuK0LhJMe01RiTW5M52A9WwsG4wzHrgcHiT5jXN59Gyoh=
6AQ%40mail.gmail.com.

--f403045c28b8fa3ae30561e3e423
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Wed, Jan 3, 2018 at 5:31 AM, Thiago Macieira <span dir=
=3D"ltr">&lt;<a href=3D"mailto:thiago@macieira.org" target=3D"_blank">thiag=
o@macieira.org</a>&gt;</span> wrote:<br><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 =
..8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=3D"">On Wedne=
sday, 3 January 2018 10:32:40 -02 Olaf van der Spek wrote:<br>
&gt; 2018-01-03 12:33 GMT+01:00 Thiago Macieira &lt;<a href=3D"mailto:thiag=
o@macieira.org">thiago@macieira.org</a>&gt;:<br>
&gt; &gt; On Wednesday, 3 January 2018 08:51:05 -02 <a href=3D"mailto:olafv=
dspek@gmail.com">olafvdspek@gmail.com</a> wrote:<br>
&gt; &gt;&gt; Wouldn&#39;t the idea be to do the analysis and only consider=
 it a rvalue if<br>
&gt; &gt;&gt; it&#39;s NOT accessed later in the statement / function?<br>
&gt; &gt;<br>
&gt; &gt; And its address has never been taken, which also means it must ne=
ver have<br>
&gt; &gt; been passed by reference either. That limits the usefulness too m=
uch to<br>
&gt; &gt; make it a feature.<br>
&gt;<br>
&gt; Taking the address is fine as long as all references are dead by the<b=
r>
&gt; time it&#39;s considered an rvalue.<br>
<br>
</span>And how do you prove that they are?<br></blockquote><div><br></div><=
div>Guys, you&#39;re going down an unnecessary rabbit hole here.</div><div>=
The way C++11 solved the problem was just to say that <i><b>it doesn&#39;t =
matter</b></i> if there&#39;s a live reference or not. Certain syntactic co=
nstructs simply turn into moves (not copies), <i><b>regardless</b></i> of t=
he number of live references to the operand.</div><div><br></div><div><a hr=
ef=3D"https://wandbox.org/permlink/DIveFuEiL5JzSkOj">https://wandbox.org/pe=
rmlink/DIveFuEiL5JzSkOj</a><span class=3D"sew91g79wnqs5il"></span><span cla=
ss=3D"sewoupv9y3xeow"></span><br></div><div>(The output &quot;moved from&qu=
ot; indicates that we&#39;re observing `Observable o` <i>after</i> it has b=
een moved from, via the reference we stashed.)</div><div><br></div><div>Als=
o, please remember that even in simple cases with no aliasing at all, movin=
g-from an object <i>does not end its lifetime</i>. Every object is accessed=
 at least once after its &quot;last&quot; move-access =E2=80=94 namely, whe=
n it is referenced by the `this` argument of its own destructor. Moves are =
<i>always</i> observable. Trying to &quot;hide&quot; moves or pretend that =
you can do them under the as-if rule will never work. You <i>must</i> confr=
ont the human factor head-on: Which syntactic constructs do human programme=
rs &quot;expect&quot; to produce moves, and which do they &quot;expect&quot=
; to produce copies?</div><div><br></div><div>HTH,</div><div>Arthur</div></=
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/CADvuK0LhJMe01RiTW5M52A9WwsG4wzHrgcHi=
T5jXN59Gyoh6AQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0LhJMe01RiT=
W5M52A9WwsG4wzHrgcHiT5jXN59Gyoh6AQ%40mail.gmail.com</a>.<br />

--f403045c28b8fa3ae30561e3e423--

.


Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 03 Jan 2018 17:33:33 -0200
Raw View
On Wednesday, 3 January 2018 17:05:10 -02 Arthur O'Dwyer wrote:
> Guys, you're going down an unnecessary rabbit hole here.
> The way C++11 solved the problem was just to say that *it doesn't matter*
> if there's a live reference or not. Certain syntactic constructs simply
> turn into moves (not copies), *regardless* of the number of live referenc=
es
> to the operand.

Indeed, but that was done because in those cases, any live references were=
=20
about to become dangling anyway, so any well-defined program would never us=
e=20
them after this point. It was safe to move from this particular object.

> Also, please remember that even in simple cases with no aliasing at all,
> moving-from an object *does not end its lifetime*. Every object is access=
ed
> at least once after its "last" move-access =E2=80=94 namely, when it is r=
eferenced
> by the `this` argument of its own destructor. Moves are *always*
> observable. Trying to "hide" moves or pretend that you can do them under
> the as-if rule will never work. You *must* confront the human factor
> head-on: Which syntactic constructs do human programmers "expect" to
> produce moves, and which do they "expect" to produce copies?

All true.

Which is also another reason we want the destructive move.

--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center

--=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/2794319.GCS1XuZPMK%40tjmaciei-mobl1.

.


Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Wed, 3 Jan 2018 11:41:26 -0800
Raw View
--94eb2c1b5110bc5f730561e46697
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Wed, Jan 3, 2018 at 11:33 AM, Thiago Macieira <thiago@macieira.org>
wrote:

> On Wednesday, 3 January 2018 17:05:10 -02 Arthur O'Dwyer wrote:
> > Guys, you're going down an unnecessary rabbit hole here.
> > The way C++11 solved the problem was just to say that *it doesn't matte=
r*
> > if there's a live reference or not. Certain syntactic constructs simply
> > turn into moves (not copies), *regardless* of the number of live
> references
> > to the operand.
>
> Indeed, but that was done because in those cases, any live references wer=
e
> about to become dangling anyway, so any well-defined program would never
> use
> them after this point.


You snipped out the example of a well-defined program that used them after
that point. Here it is again.
https://wandbox.org/permlink/DIveFuEiL5JzSkOj
Perfectly well-defined. No undefined behavior here.


It was safe to move from this particular object.
>

I'd tend to agree with you there. However, please continue to remember that
"safe" is a human concept, not a computerese concept. It's "safe" to move
from `o` in this case because that's what the human programmer "expected."
If the human programmer hadn't expected `o` to appear "moved from" in the
second output =E2=80=94 such that that faulty expectation had caused the co=
mputer
to launch missiles or crash the plane or whatever =E2=80=94 then it wouldn'=
t have
been "safe" after all.


> Also, please remember that even in simple cases with no aliasing at all,
> > moving-from an object *does not end its lifetime*. Every object is
> accessed
> > at least once after its "last" move-access =E2=80=94 namely, when it is
> referenced
> > by the `this` argument of its own destructor. Moves are *always*
> > observable. Trying to "hide" moves or pretend that you can do them unde=
r
> > the as-if rule will never work. You *must* confront the human factor
> > head-on: Which syntactic constructs do human programmers "expect" to
> > produce moves, and which do they "expect" to produce copies?
>
> All true.
>

=E2=80=93Arthur

--=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/CADvuK0K1DGi-uv%2BFc-33wT%3D_VR0R6NDThAR-ZFK%2B%=
3DXcgtrwdrw%40mail.gmail.com.

--94eb2c1b5110bc5f730561e46697
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Wed, Jan 3, 2018 at 11:33 AM, Thiago Macieira <span dir=
=3D"ltr">&lt;<a href=3D"mailto:thiago@macieira.org" target=3D"_blank">thiag=
o@macieira.org</a>&gt;</span> wrote:<br><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 =
..8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=3D"">On Wedne=
sday, 3 January 2018 17:05:10 -02 Arthur O&#39;Dwyer wrote:<br>
&gt; Guys, you&#39;re going down an unnecessary rabbit hole here.<br>
</span>&gt; The way C++11 solved the problem was just to say that *it doesn=
&#39;t matter*<br>
<span class=3D"">&gt; if there&#39;s a live reference or not. Certain synta=
ctic constructs simply<br>
</span>&gt; turn into moves (not copies), *regardless* of the number of liv=
e references<br>
&gt; to the operand.<br>
<br>
Indeed, but that was done because in those cases, any live references were<=
br>
about to become dangling anyway, so any well-defined program would never us=
e<br>
them after this point.</blockquote><div><br></div><div>You snipped out the =
example of a well-defined program that used them after that point. Here it =
is again.</div><div><a href=3D"https://wandbox.org/permlink/DIveFuEiL5JzSkO=
j" target=3D"_blank" style=3D"font-size:13px">https://wandbox.org/permlink/=
<wbr>DIveFuEiL5JzSkOj<span class=3D"sewjv75brkwdpx4"></span><span class=3D"=
sewldzyip7aq7z5"></span></a><br></div><div><div>Perfectly well-defined. No =
undefined behavior here.</div><div><br></div><div><br></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;=
border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex=
">It was safe to move from this particular object.<span class=3D""><br></sp=
an></blockquote></div><div><span class=3D"sewjv75brkwdpx4"></span><span cla=
ss=3D"sewldzyip7aq7z5"></span><br></div><div>I&#39;d tend to agree with you=
 there. However, please continue to remember that &quot;safe&quot; is a hum=
an concept, not a computerese concept. It&#39;s &quot;safe&quot; to move fr=
om `o` in this case because that&#39;s what the human programmer &quot;expe=
cted.&quot; If the human programmer hadn&#39;t expected `o` to appear &quot=
;moved from&quot; in the second output =E2=80=94 such that that faulty expe=
ctation had caused the computer to launch missiles or crash the plane or wh=
atever =E2=80=94 then it wouldn&#39;t have been &quot;safe&quot; after all.=
</div><div><br></div><div><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span cl=
ass=3D"">
&gt; Also, please remember that even in simple cases with no aliasing at al=
l,<br>
</span>&gt; moving-from an object *does not end its lifetime*. Every object=
 is accessed<br>
<span class=3D"">&gt; at least once after its &quot;last&quot; move-access =
=E2=80=94 namely, when it is referenced<br>
</span>&gt; by the `this` argument of its own destructor. Moves are *always=
*<br>
<span class=3D"">&gt; observable. Trying to &quot;hide&quot; moves or prete=
nd that you can do them under<br>
</span>&gt; the as-if rule will never work. You *must* confront the human f=
actor<br>
<span class=3D"">&gt; head-on: Which syntactic constructs do human programm=
ers &quot;expect&quot; to<br>
&gt; produce moves, and which do they &quot;expect&quot; to produce copies?=
<br>
<br>
</span>All true.<br></blockquote><div><br></div><div>=E2=80=93Arthur=C2=A0<=
/div></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/CADvuK0K1DGi-uv%2BFc-33wT%3D_VR0R6NDT=
hAR-ZFK%2B%3DXcgtrwdrw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoo=
ter">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CADvuK0K1=
DGi-uv%2BFc-33wT%3D_VR0R6NDThAR-ZFK%2B%3DXcgtrwdrw%40mail.gmail.com</a>.<br=
 />

--94eb2c1b5110bc5f730561e46697--

.