Topic: Sub-objects and their copy ellision


Author: Eyal Rozenberg <eyalroz@technion.ac.il>
Date: Tue, 19 Dec 2017 18:34:31 +0100
Raw View
Hello list,

I've recently gone over Antony Polukhin's proposal (or proposal draft)
regarding subobject copy elision:

https://apolukhin.github.io/papers/subobjects_copy_elision.html

where he describes how, at the moment, if your function returns fields
in an object, compilers do not construct them where the output needs to
be placed, and consequently generate much longer and slower code.

Supposedly, this is due to the standard's provision regarding copy
elision, [class.copy.elision], which says that elision is permitted:

"... in a return statement in a function with a class return type, when
the expression is the name of a non-volatile automatic object etc. etc."

As I was reading the paper, it made me wonder: Why does it matter that
these are subobjects? Aren't subobjects just another kind of object?

So I looked it up in the current standard draft:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4700.pdf

and, indeed, in Section [intro.object], we find the definition of a
subobject:

"Objects can contain other objects, called \emph{subobjects}"

that is to say, subobjects _are_ objects. And if an object has automatic
storage duration, then so do its (non-static) subobjects. Well, then,
why is it the case that copy elision doesn't occur for subobjects? And
is this proposal really necessary, or is it just an unimaginative
interpretation of the wording of [class.copy.elision] by compiler
implementers?


I'm hoping some language lawyers or compiler people can shed some light
on this point.

Eyal

--
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/caca241d-3498-b79b-fbf3-e57d8b7c3518%40technion.ac.il.

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 19 Dec 2017 12:10:15 -0800 (PST)
Raw View
------=_Part_31022_491329282.1513714215421
Content-Type: multipart/alternative;
 boundary="----=_Part_31023_181678153.1513714215421"

------=_Part_31023_181678153.1513714215421
Content-Type: text/plain; charset="UTF-8"



On Tuesday, December 19, 2017 at 12:34:40 PM UTC-5, Eyal Rozenberg wrote:
>
>
> Hello list,
>
> I've recently gone over Antony Polukhin's proposal (or proposal draft)
> regarding subobject copy elision:
>
> https://apolukhin.github.io/papers/subobjects_copy_elision.html
>
> where he describes how, at the moment, if your function returns fields
> in an object, compilers do not construct them where the output needs to
> be placed, and consequently generate much longer and slower code.
>
> Supposedly, this is due to the standard's provision regarding copy
> elision, [class.copy.elision], which says that elision is permitted:
>
> "... in a return statement in a function with a class return type, when
> the expression is the name of a non-volatile automatic object etc. etc."
>
> As I was reading the paper, it made me wonder: Why does it matter that
> these are subobjects? Aren't subobjects just another kind of object?
>
> So I looked it up in the current standard draft:
>
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4700.pdf
>
> and, indeed, in Section [intro.object], we find the definition of a
> subobject:
>
> "Objects can contain other objects, called \emph{subobjects}"
>
> that is to say, subobjects _are_ objects. And if an object has automatic
> storage duration, then so do its (non-static) subobjects. Well, then,
> why is it the case that copy elision doesn't occur for subobjects? And
> is this proposal really necessary, or is it just an unimaginative
> interpretation of the wording of [class.copy.elision] by compiler
> implementers?
>

First, let's not forget that elision is not a *requirement* of the
standard. Implementations don't have to elide such copy/move operations,
regardless of the circumstance. [class.copy.elision] gives compilers
*permission* to elide the copy/move, not requires them to do so. Note that
C++17's guaranteed elision works by *redefining the meaning of a prvalue*
<https://stackoverflow.com/questions/38043319/how-does-guaranteed-copy-elision-work/38043447#38043447>,
and in so doing making it so that these circumstances don't need elision at
all.

Second, yes, subobjects are objects. But look at what
`[class.copy.elision]/1.1 says:

> when the expression is the name of a non-volatile automatic object (other
than a function parameter or a variable introduced by the
exception-declaration of a handler (18.3))

The expression `v.first` is not "the name of a non-volatile automatic
object". `first` is not an automatic object; it is a member subobject of
`v`. And `v.first` is not its name; `first` is its name. `v.first` is an
expression that accesses a subobject from an object.

Third, regardless of all of that, no compiler could possibly elide such
things. Why? Because of how elision is implemented.

When a function gets called, the function has to return a value. That value
needs memory to live in, but the return value needs to out-live the
function itself. The ABI defines how this all works. Generally speaking,
this happens by the caller providing a piece of memory of the
size/alignment for the return value to the function.

Elision works by having the function itself construct the return value
directly into that memory. That is, if you do this:
string foo()
{
  string ret;
  ret = ...;
  return ret;
}

The compiler can elect to have the storage for `ret` be the actual storage
for the return value object provided by the caller.

Now, consider this:

string foo()
{
  pair<string, string> pr;
  pr.first = ...;
  return pr.first;
}

The layout of `pair<string, string>` is fixed. `pr` must have the same
structural layout as any other instance of that type. And that layout will
necessarily be larger than that of just a `std::string`.

But the* caller* doesn't know that. The caller is the one who provides
memory for the return value object. And as far as the caller can tell, all
it needs to provide is `sizeof(string)` bytes.

The compiler cannot stick* part* of an object in one place of memory and
part in another. So the only way this could possibly work is if the caller
provided enough storage for `pr`, not just for `pr.first`.

Not to mention, this creates a problem for the entire object model. To make
this work, `pr.first` would have to be able to outlive the object it is
stored within. But the object model doesn't allow that; if you destroy a
complete object, you destroy its subobjects too. That's required.

So how does this work? Either `pr` is destroyed at the end of the
statement, which destroys `pr.first` and `pr.second` Or `pr` is not
destroyed, which means `pr.second`* is not destroyed*. If `pr.second`
survives the execution of `foo`, who is responsible for destroying it?

It can't be the caller, since the caller has no idea that `pr.second`*
exists*. That's an implementation detail that the caller is not privy to.

No, this is not gonna happen. Not unless someone comes up with a really
novel way of allowing it.

I'm hoping some language lawyers or compiler people can shed some light
> on this point.
>
> Eyal
>

--
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/1c6eff77-d71f-4dd7-8c13-f609460a03f0%40isocpp.org.

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

<div dir=3D"ltr"><br><br>On Tuesday, December 19, 2017 at 12:34:40 PM UTC-5=
, Eyal Rozenberg wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>Hello list,
<br>
<br>I&#39;ve recently gone over Antony Polukhin&#39;s proposal (or proposal=
 draft)
<br>regarding subobject copy elision:
<br>
<br><a onmousedown=3D"this.href=3D&#39;https://www.google.com/url?q\x3dhttp=
s%3A%2F%2Fapolukhin.github.io%2Fpapers%2Fsubobjects_copy_elision.html\x26sa=
\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHO4JCvzZ1QGfpLCqZvjN7b7dl1pg&#39;;return=
 true;" onclick=3D"this.href=3D&#39;https://www.google.com/url?q\x3dhttps%3=
A%2F%2Fapolukhin.github.io%2Fpapers%2Fsubobjects_copy_elision.html\x26sa\x3=
dD\x26sntz\x3d1\x26usg\x3dAFQjCNHO4JCvzZ1QGfpLCqZvjN7b7dl1pg&#39;;return tr=
ue;" href=3D"https://apolukhin.github.io/papers/subobjects_copy_elision.htm=
l" target=3D"_blank" rel=3D"nofollow">https://apolukhin.github.io/<wbr>pape=
rs/subobjects_copy_<wbr>elision.html</a>
<br>
<br>where he describes how, at the moment, if your function returns fields
<br>in an object, compilers do not construct them where the output needs to
<br>be placed, and consequently generate much longer and slower code.
<br>
<br>Supposedly, this is due to the standard&#39;s provision regarding copy
<br>elision, [class.copy.elision], which says that elision is permitted:
<br>
<br>&quot;... in a return statement in a function with a class return type,=
 when
<br>the expression is the name of a non-volatile automatic object etc. etc.=
&quot;
<br>
<br>As I was reading the paper, it made me wonder: Why does it matter that
<br>these are subobjects? Aren&#39;t subobjects just another kind of object=
?
<br>
<br>So I looked it up in the current standard draft:
<br>
<br><a onmousedown=3D"this.href=3D&#39;http://www.google.com/url?q\x3dhttp%=
3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2017%2Fn470=
0.pdf\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHudSZ-z16lfCJSOi7QpmbcBRZTRw&=
#39;;return 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%2F201=
7%2Fn4700.pdf\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHudSZ-z16lfCJSOi7Qpmb=
cBRZTRw&#39;;return true;" href=3D"http://www.open-std.org/jtc1/sc22/wg21/d=
ocs/papers/2017/n4700.pdf" target=3D"_blank" rel=3D"nofollow">http://www.op=
en-std.org/jtc1/<wbr>sc22/wg21/docs/papers/2017/<wbr>n4700.pdf</a>
<br>
<br>and, indeed, in Section [intro.object], we find the definition of a
<br>subobject:
<br>
<br>&quot;Objects can contain other objects, called \emph{subobjects}&quot;
<br>
<br>that is to say, subobjects _are_ objects. And if an object has automati=
c
<br>storage duration, then so do its (non-static) subobjects. Well, then,
<br>why is it the case that copy elision doesn&#39;t occur for subobjects? =
And
<br>is this proposal really necessary, or is it just an unimaginative
<br>interpretation of the wording of [class.copy.elision] by compiler
<br>implementers?<br></blockquote><div><br></div><div><div>First, let&#39;s=
 not forget that elision is not a <i>requirement</i>
 of the standard. Implementations don&#39;t have to elide such copy/move=20
operations, regardless of the circumstance. [class.copy.elision] gives comp=
ilers <i>permission</i> to elide the copy/move, not requires them to do so.=
 Note that C++17&#39;s guaranteed
 elision works by <a href=3D"https://stackoverflow.com/questions/38043319/h=
ow-does-guaranteed-copy-elision-work/38043447#38043447"><u><font color=3D"#=
0066cc">redefining the meaning of a prvalue</font></u></a>, and in so doing=
 making it so that these circumstances don&#39;t need elision at all.<br></=
div><div><br></div><div>Second, yes, subobjects are objects. But look at wh=
at `[class.copy.elision]/1.1 says:</div><div><br></div><div>&gt;
 when the expression is the name of a non-volatile automatic object=20
(other than a function parameter or a variable introduced by the<br>excepti=
on-declaration of a handler (18.3)) <br></div><div><br></div><div>The expre=
ssion `v.first` is not &quot;the name of a non-volatile automatic object&qu=
ot;. `first` is not an automatic object; it is a member subobject of `v`. A=
nd `v.first` is not its name; `first` is its name. `v.first` is an expressi=
on that accesses a subobject from an object.</div><div><br></div><div>Third=
, regardless of all of that, no compiler could possibly elide such things. =
Why? Because of how elision is implemented.</div><div><br></div><div>When a=
 function gets called, the function has to return a value. That=20
value needs memory to live in, but the return value needs to out-live=20
the function itself. The ABI defines how this all works. Generally=20
speaking, this happens by the caller providing a piece of memory of the=20
size/alignment for the return value to the function.</div><div><br></div><d=
iv>Elision works by having the function itself construct the return value d=
irectly into that memory. That is, if you do this:</div><div class=3D"prett=
yprint" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-wor=
d; background-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div =
class=3D"subprettyprint"><span class=3D"styled-by-prettify" style=3D"color:=
 #008;">string</span><span class=3D"styled-by-prettify" style=3D"color: #00=
0;"> foo</span><span class=3D"styled-by-prettify" style=3D"color: #660;">()=
</span><span class=3D"styled-by-prettify" style=3D"color: #000;"><br></span=
><span class=3D"styled-by-prettify" style=3D"color: #660;">{</span><span cl=
ass=3D"styled-by-prettify" style=3D"color: #000;"><br>=C2=A0 </span><span c=
lass=3D"styled-by-prettify" style=3D"color: #008;">string</span><span class=
=3D"styled-by-prettify" style=3D"color: #000;"> ret</span><span class=3D"st=
yled-by-prettify" style=3D"color: #660;">;</span><span class=3D"styled-by-p=
rettify" style=3D"color: #000;"><br>=C2=A0 ret </span><span class=3D"styled=
-by-prettify" style=3D"color: #660;">=3D</span><span class=3D"styled-by-pre=
ttify" style=3D"color: #000;"> </span><span class=3D"styled-by-prettify" st=
yle=3D"color: #660;">...;</span><span class=3D"styled-by-prettify" style=3D=
"color: #000;"><br>=C2=A0 </span><span class=3D"styled-by-prettify" style=
=3D"color: #008;">return</span><span class=3D"styled-by-prettify" style=3D"=
color: #000;"> ret</span><span class=3D"styled-by-prettify" style=3D"color:=
 #660;">;</span><span class=3D"styled-by-prettify" style=3D"color: #000;"><=
br></span><span class=3D"styled-by-prettify" style=3D"color: #660;">}</span=
></div></code></div><div><br></div><div>The compiler can elect to have the =
storage for `ret` be the actual storage for the return value object provide=
d by the caller.</div><div><br></div><div>Now, consider this:</div><div><br=
></div><div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187, =
187); word-wrap: break-word; background-color: rgb(250, 250, 250);"><code c=
lass=3D"prettyprint"><div class=3D"subprettyprint"><span class=3D"styled-by=
-prettify" style=3D"color: #008;">string</span><span class=3D"styled-by-pre=
ttify" style=3D"color: #000;"> foo</span><span class=3D"styled-by-prettify"=
 style=3D"color: #660;">()</span><span class=3D"styled-by-prettify" style=
=3D"color: #000;"><br></span><span class=3D"styled-by-prettify" style=3D"co=
lor: #660;">{</span><span class=3D"styled-by-prettify" style=3D"color: #000=
;"><br>=C2=A0 pair</span><span class=3D"styled-by-prettify" style=3D"color:=
 #660;">&lt;</span><span class=3D"styled-by-prettify" style=3D"color: #008;=
">string</span><span class=3D"styled-by-prettify" style=3D"color: #660;">,<=
/span><span class=3D"styled-by-prettify" style=3D"color: #000;"> </span><sp=
an class=3D"styled-by-prettify" style=3D"color: #008;">string</span><span c=
lass=3D"styled-by-prettify" style=3D"color: #660;">&gt;</span><span class=
=3D"styled-by-prettify" style=3D"color: #000;"> pr</span><span class=3D"sty=
led-by-prettify" style=3D"color: #660;">;</span><span class=3D"styled-by-pr=
ettify" style=3D"color: #000;"><br>=C2=A0 pr</span><span class=3D"styled-by=
-prettify" style=3D"color: #660;">.</span><span class=3D"styled-by-prettify=
" style=3D"color: #000;">first </span><span class=3D"styled-by-prettify" st=
yle=3D"color: #660;">=3D</span><span class=3D"styled-by-prettify" style=3D"=
color: #000;"> </span><span class=3D"styled-by-prettify" style=3D"color: #6=
60;">...;</span><span class=3D"styled-by-prettify" style=3D"color: #000;"><=
br>=C2=A0 </span><span class=3D"styled-by-prettify" style=3D"color: #008;">=
return</span><span class=3D"styled-by-prettify" style=3D"color: #000;"> pr<=
/span><span class=3D"styled-by-prettify" style=3D"color: #660;">.</span><sp=
an class=3D"styled-by-prettify" style=3D"color: #000;">first</span><span cl=
ass=3D"styled-by-prettify" style=3D"color: #660;">;</span><span class=3D"st=
yled-by-prettify" style=3D"color: #000;"><br></span><span class=3D"styled-b=
y-prettify" style=3D"color: #660;">}</span></div></code></div><div><br></di=
v><div>The layout of `pair&lt;string, string&gt;` is fixed. `pr` must have =
the same structural layout as any other instance of that type. And that lay=
out will necessarily be larger than that of just a `std::string`.</div><div=
><br></div><div>But the<i> caller</i> doesn&#39;t know that. The caller is =
the one who provides memory for the return value object. And as far as the =
caller can tell, all it needs to provide is `sizeof(string)` bytes.</div><d=
iv><br></div><div>The compiler cannot stick<i> part</i> of an object in one=
 place of memory and part in another. So the only way this could possibly w=
ork is if the caller provided enough storage for `pr`, not just for `pr.fir=
st`.</div><div><i><br></i></div><div>Not to mention, this creates a problem=
 for the entire object model. To make this work, `pr.first` would have to b=
e able to outlive the object it is stored within. But the object model does=
n&#39;t allow that; if you destroy a complete object, you destroy its subob=
jects too. That&#39;s required.</div><div><br></div><div>So how does this w=
ork? Either `pr` is destroyed at the end of the statement, which destroys `=
pr.first` and `pr.second` Or `pr` is not destroyed, which means `pr.second`=
<i> is not destroyed</i>. If `pr.second` survives the execution of `foo`, w=
ho is responsible for destroying it?</div><div><br></div><div>It can&#39;t =
be the caller, since the caller has no idea that `pr.second`<i> exists</i>.=
 That&#39;s an implementation detail that the caller is not privy to.</div>=
<div><br></div><div>No, this is not gonna happen. Not unless someone comes =
up with a really novel way of allowing it.</div><div><br></div><b><i></i></=
b></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;">I&#39;m hoping some la=
nguage lawyers or compiler people can shed some light
<br>on this point.
<br>
<br>Eyal
<br></blockquote></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/1c6eff77-d71f-4dd7-8c13-f609460a03f0%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/1c6eff77-d71f-4dd7-8c13-f609460a03f0=
%40isocpp.org</a>.<br />

------=_Part_31023_181678153.1513714215421--

------=_Part_31022_491329282.1513714215421--

.


Author: Eyal Rozenberg <eyalroz@technion.ac.il>
Date: Tue, 19 Dec 2017 23:09:25 +0100
Raw View

On 12/19/17 9:10 PM, Nicol Bolas wrote:
> look at what [class.copy.elision]/1.1 says:
>=20
>> when the expression is the name of a non-volatile automatic object
> (other than a function parameter or a variable introduced by the
> exception-declaration of a handler (18.3))
>=20
> The expression `v.first` is not "the name of a non-volatile automatic
> object". `first` is not an automatic object; it is a member subobject of
> `v`. And `v.first` is not its name; `first` is its name. `v.first` is an
> expression that accesses a subobject from an object.

Ah. Indeed, it seems only variables can have "automatic storage
duration", even though their sub-objects have the same storage behavior
as them. Ok.

> Now, consider this:
>=20
> |
> stringfoo()
> {
> =C2=A0 pair<string,string>pr;
> =C2=A0 pr.first =3D...;
> =C2=A0 returnpr.first;
> }
> |
>=20
> The layout of `pair<string, string>` is fixed.

But when optimizing, the compiler is not committed to using that layout.
In fact, in the example you've given it can completely drop pr, and just
construct the returned string at the area where a string is supposed to
end up. It will be "as if" the pr was used and the first element was copied=
..

> But the/caller/ doesn't know that. The caller is the one who provides
> memory for the return value object. And as far as the caller can tell,
> all it needs to provide is `sizeof(string)` bytes.

.... which is good enough with your specific example. Now, it's true that
there could be code in foo() which depends on the layout being as it is
that a compiler's optimizer will not be able to clear away; but there
could also not be such code. And since, like you pointed out at the
beginning of your reply, elision is just an option - why not give that
option?

> Not to mention, this creates a problem for the entire object model. To
> make this work, `pr.first` would have to be able to outlive the object
> it is stored within. But the object model doesn't allow that; if you
> destroy a complete object, you destroy its subobjects too. That's require=
d.

Under certain assumptions, which std::pair meets, that should not be a
problem. I guess a defaulted destructor would be one of those.

> No, this is not gonna happen. Not unless someone comes up with a really
> novel way of allowing it.

Would you not say there's some leeway for what I describe (i.e. break
up objects that are not necessary) rather than what you ruled out
(negotiations over who destroys an object)? Under the "as if" rule?

Eyal

--=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/c14fe13b-a658-e295-40a6-1465638d18db%40technion.=
ac.il.

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 19 Dec 2017 17:06:36 -0800 (PST)
Raw View
------=_Part_775_113262069.1513731997094
Content-Type: multipart/alternative;
 boundary="----=_Part_776_1421323396.1513731997094"

------=_Part_776_1421323396.1513731997094
Content-Type: text/plain; charset="UTF-8"



On Tuesday, December 19, 2017 at 5:09:34 PM UTC-5, Eyal Rozenberg wrote:
>
>
>
> On 12/19/17 9:10 PM, Nicol Bolas wrote:
> > look at what [class.copy.elision]/1.1 says:
> >
> >> when the expression is the name of a non-volatile automatic object
> > (other than a function parameter or a variable introduced by the
> > exception-declaration of a handler (18.3))
> >
> > The expression `v.first` is not "the name of a non-volatile automatic
> > object". `first` is not an automatic object; it is a member subobject of
> > `v`. And `v.first` is not its name; `first` is its name. `v.first` is an
> > expression that accesses a subobject from an object.
>
> Ah. Indeed, it seems only variables can have "automatic storage
> duration", even though their sub-objects have the same storage behavior
> as them. Ok.
>
> > Now, consider this:
> >
> > |
> > stringfoo()
> > {
> >   pair<string,string>pr;
> >   pr.first =...;
> >   returnpr.first;
> > }
> > |
> >
> > The layout of `pair<string, string>` is fixed.
>
> But when optimizing, the compiler is not committed to using that layout.
>

Yes, it is. I can pass a pointer/reference to `pr` to any function, and
that function has to be able to work with what I generate.

In fact, in the example you've given it can completely drop pr, and just
> construct the returned string at the area where a string is supposed to
> end up. It will be "as if" the pr was used and the first element was
> copied.
>
> > But the/caller/ doesn't know that. The caller is the one who provides
> > memory for the return value object. And as far as the caller can tell,
> > all it needs to provide is `sizeof(string)` bytes.
>
> ... which is good enough with your specific example. Now, it's true that
> there could be code in foo() which depends on the layout being as it is
> that a compiler's optimizer will not be able to clear away; but there
> could also not be such code. And since, like you pointed out at the
> beginning of your reply, elision is just an option - why not give that
> option?
>

What "option"?

Just within this thread, we have identified a number of limitations on what
you can do with such objects. Let's not go further than merely what you've
already agree to: destruction of subobjects and layout. That is, this
optimization is not possible if any of the following is true:

1) The containing type has a non-defaulted destructor.
2) The containing object is not passed to another function by pointer or
reference, since that requires the object's layout to be consistent with
what the standard says.
3) The user of the containing object does not do anything layout-specific
itself.

Note that this is almost certainly* not* a complete list. It's merely the
ones talked about thus far; there are almost certainly others.

Item #2 is particularly important. Why? Because that rules out calling* any
member functions*, since all non-static member functions take the object by
pointer. And that requires the object's layout to be consistent with its
definition.

Notice that "Motivating example #2" doesn't qualify for this, since we call
a function on the object. That requires it to have a certain layout.

So, how much real code actually qualifies for such elision?

Because here's the thing the person behind that proposal just doesn't get.
His proposal* doesn't work*. It does not solve the problem. Why?

Because compilers can't do it in so many of these cases. RVO was very
reliable; when compilers offered it, it worked for any case of returning a
prvalue. NRVO is pretty reliable; declare the variable at the top of the
function, return it whenever, and you're almost guaranteed to get the
optimization.

What are the guidelines for getting this proposal's optimizations? What
circumstances stop it, and what can be done to avoid them?

Because here's the thing: if I do this:

string foo()
{
  string str;
  str = ...;
  return str;
}

If I do that, and I* don't* get elision, it's still fine. Why? Because I
still get automatic move support. `str` in the return statement is a
reference to an automatic variable in the function's scope, so it is moved
from. I may not have gotten the best answer, but I got a good enough one.

In this case:

string foo()
{
  pair<string, string> pr = ...;
  return pr.second;
}

What happens if this doesn't get elided? Well, you get a copy. The only way
to get a move is to ask for it: `return std::move(pr.second)`.

So the proposal actually* encourages bad code*, on the assumption that the
compiler will swoop in and save you.

--
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/3ec0bd22-b228-4026-bb49-aec5102918c7%40isocpp.org.

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

<div dir=3D"ltr"><br><br>On Tuesday, December 19, 2017 at 5:09:34 PM UTC-5,=
 Eyal Rozenberg wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>
<br>On 12/19/17 9:10 PM, Nicol Bolas wrote:
<br>&gt; look at what [class.copy.elision]/1.1 says:
<br>&gt;=20
<br>&gt;&gt; when the expression is the name of a non-volatile automatic ob=
ject
<br>&gt; (other than a function parameter or a variable introduced by the
<br>&gt; exception-declaration of a handler (18.3))
<br>&gt;=20
<br>&gt; The expression `v.first` is not &quot;the name of a non-volatile a=
utomatic
<br>&gt; object&quot;. `first` is not an automatic object; it is a member s=
ubobject of
<br>&gt; `v`. And `v.first` is not its name; `first` is its name. `v.first`=
 is an
<br>&gt; expression that accesses a subobject from an object.
<br>
<br>Ah. Indeed, it seems only variables can have &quot;automatic storage
<br>duration&quot;, even though their sub-objects have the same storage beh=
avior
<br>as them. Ok.
<br>
<br>&gt; Now, consider this:
<br>&gt;=20
<br>&gt; |
<br>&gt; stringfoo()
<br>&gt; {
<br>&gt; =C2=A0 pair&lt;string,string&gt;pr;
<br>&gt; =C2=A0 pr.first =3D...;
<br>&gt; =C2=A0 returnpr.first;
<br>&gt; }
<br>&gt; |
<br>&gt;=20
<br>&gt; The layout of `pair&lt;string, string&gt;` is fixed.
<br>
<br>But when optimizing, the compiler is not committed to using that layout=
..<br></blockquote><div><br></div><div>Yes, it is. I can pass a pointer/refe=
rence to `pr` to any function, and that function has to be able to work wit=
h what I generate.</div><div><br></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;">In fact, in the example you&#39;ve given it can completely drop pr=
, and just
<br>construct the returned string at the area where a string is supposed to
<br>end up. It will be &quot;as if&quot; the pr was used and the first elem=
ent was copied.
<br>
<br>&gt; But the/caller/ doesn&#39;t know that. The caller is the one who p=
rovides
<br>&gt; memory for the return value object. And as far as the caller can t=
ell,
<br>&gt; all it needs to provide is `sizeof(string)` bytes.
<br>
<br>... which is good enough with your specific example. Now, it&#39;s true=
 that
<br>there could be code in foo() which depends on the layout being as it is
<br>that a compiler&#39;s optimizer will not be able to clear away; but the=
re
<br>could also not be such code. And since, like you pointed out at the
<br>beginning of your reply, elision is just an option - why not give that
<br>option?<br></blockquote><div>=C2=A0</div><div>What &quot;option&quot;?<=
/div><div><br></div><div>Just within this thread, we have identified a numb=
er of limitations on what you can do with such objects. Let&#39;s not go fu=
rther than merely what you&#39;ve already agree to: destruction of subobjec=
ts and layout. That is, this optimization is not possible if any of the fol=
lowing is true:</div><div><br></div><div>1) The containing type has a non-d=
efaulted destructor.</div><div>2) The containing object is not passed to an=
other function by pointer or reference, since that requires the object&#39;=
s layout to be consistent with what the standard says.</div><div>3) The use=
r of the containing object does not do anything layout-specific itself.</di=
v><div><br></div><div>Note that this is almost certainly<i> not</i> a compl=
ete list. It&#39;s merely the ones talked about thus far; there are almost =
certainly others.</div><div><i><br></i></div><div>Item #2 is particularly i=
mportant. Why? Because that rules out calling<i> any member functions</i>, =
since all non-static member functions take the object by pointer. And that =
requires the object&#39;s layout to be consistent with its definition.</div=
><div><br></div><div>Notice that &quot;<span style=3D"display: inline !impo=
rtant; float: none; background-color: transparent; color: rgb(34, 34, 34); =
font-family: &quot;Arial&quot;,&quot;Helvetica&quot;,sans-serif; font-size:=
 13px; font-style: normal; font-variant: normal; font-weight: 400; letter-s=
pacing: normal; orphans: 2; 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;">Motivating example #2&quot; doesn&#39;t qua=
lify for this, since we call a function on the object. That requires it to =
have a certain layout.</span></div><div><span style=3D"display: inline !imp=
ortant; float: none; background-color: transparent; color: rgb(34, 34, 34);=
 font-family: &quot;Arial&quot;,&quot;Helvetica&quot;,sans-serif; font-size=
: 13px; font-style: normal; font-variant: normal; font-weight: 400; letter-=
spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-=
indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-sp=
ace: normal; word-spacing: 0px;"><br></span></div><div>So, how much real co=
de actually qualifies for such elision?</div><div><br></div><div>Because he=
re&#39;s the thing the person behind that proposal just doesn&#39;t get. Hi=
s proposal<i> doesn&#39;t work</i>. It does not solve the problem. Why?</di=
v><div><br></div><div>Because compilers can&#39;t do it in so many of these=
 cases. RVO was very reliable; when compilers offered it, it worked for any=
 case of returning a prvalue. NRVO is pretty reliable; declare the variable=
 at the top of the function, return it whenever, and you&#39;re almost guar=
anteed to get the optimization.</div><div><br></div><div>What are the guide=
lines for getting this proposal&#39;s optimizations? What circumstances sto=
p it, and what can be done to avoid them?</div><div><br></div><div>Because =
here&#39;s the thing: if I do this:</div><div><br></div><div class=3D"prett=
yprint" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-wor=
d; background-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div =
class=3D"subprettyprint"><span class=3D"styled-by-prettify" style=3D"color:=
 #008;">string</span><span class=3D"styled-by-prettify" style=3D"color: #00=
0;"> foo</span><span class=3D"styled-by-prettify" style=3D"color: #660;">()=
</span><span class=3D"styled-by-prettify" style=3D"color: #000;"><br></span=
><span class=3D"styled-by-prettify" style=3D"color: #660;">{</span><span cl=
ass=3D"styled-by-prettify" style=3D"color: #000;"><br>=C2=A0 </span><span c=
lass=3D"styled-by-prettify" style=3D"color: #008;">string</span><span class=
=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-p=
rettify" style=3D"color: #000;"><br>=C2=A0 str </span><span class=3D"styled=
-by-prettify" style=3D"color: #660;">=3D</span><span class=3D"styled-by-pre=
ttify" style=3D"color: #000;"> </span><span class=3D"styled-by-prettify" st=
yle=3D"color: #660;">...;</span><span class=3D"styled-by-prettify" style=3D=
"color: #000;"><br>=C2=A0 </span><span class=3D"styled-by-prettify" style=
=3D"color: #008;">return</span><span class=3D"styled-by-prettify" style=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;"><=
br></span><span class=3D"styled-by-prettify" style=3D"color: #660;">}</span=
></div></code></div><div><br></div><div>If I do that, and I<i> don&#39;t</i=
> get elision, it&#39;s still fine. Why? Because I still get automatic move=
 support. `str` in the return statement is a reference to an automatic vari=
able in the function&#39;s scope, so it is moved from. I may not have gotte=
n the best answer, but I got a good enough one.</div><div><br></div><div>In=
 this case:</div><div><br></div><div class=3D"prettyprint" style=3D"border:=
 1px solid rgb(187, 187, 187); word-wrap: break-word; background-color: rgb=
(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subprettyprint"=
><span class=3D"styled-by-prettify" style=3D"color: #008;">string</span><sp=
an class=3D"styled-by-prettify" style=3D"color: #000;"> foo</span><span cla=
ss=3D"styled-by-prettify" style=3D"color: #660;">()</span><span class=3D"st=
yled-by-prettify" style=3D"color: #000;"><br></span><span class=3D"styled-b=
y-prettify" style=3D"color: #660;">{</span><span class=3D"styled-by-prettif=
y" style=3D"color: #000;"><br>=C2=A0 pair</span><span class=3D"styled-by-pr=
ettify" style=3D"color: #660;">&lt;</span><span class=3D"styled-by-prettify=
" style=3D"color: #008;">string</span><span class=3D"styled-by-prettify" st=
yle=3D"color: #660;">,</span><span class=3D"styled-by-prettify" style=3D"co=
lor: #000;"> </span><span class=3D"styled-by-prettify" style=3D"color: #008=
;">string</span><span class=3D"styled-by-prettify" style=3D"color: #660;">&=
gt;</span><span class=3D"styled-by-prettify" style=3D"color: #000;"> pr </s=
pan><span class=3D"styled-by-prettify" style=3D"color: #660;">=3D</span><sp=
an class=3D"styled-by-prettify" style=3D"color: #000;"> </span><span class=
=3D"styled-by-prettify" style=3D"color: #660;">...;</span><span class=3D"st=
yled-by-prettify" style=3D"color: #000;"><br>=C2=A0 </span><span class=3D"s=
tyled-by-prettify" style=3D"color: #008;">return</span><span class=3D"style=
d-by-prettify" style=3D"color: #000;"> pr</span><span class=3D"styled-by-pr=
ettify" style=3D"color: #660;">.</span><span class=3D"styled-by-prettify" s=
tyle=3D"color: #000;">second</span><span class=3D"styled-by-prettify" style=
=3D"color: #660;">;</span><span class=3D"styled-by-prettify" style=3D"color=
: #000;"><br></span><span class=3D"styled-by-prettify" style=3D"color: #660=
;">}</span></div></code></div><div><br></div><div>What happens if this does=
n&#39;t get elided? Well, you get a copy. The only way to get a move is to =
ask for it: `return std::move(pr.second)`.</div><div><br></div><div>So the =
proposal actually<i> encourages bad code</i>, on the assumption that the co=
mpiler will swoop in and save you.<br></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/3ec0bd22-b228-4026-bb49-aec5102918c7%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/3ec0bd22-b228-4026-bb49-aec5102918c7=
%40isocpp.org</a>.<br />

------=_Part_776_1421323396.1513731997094--

------=_Part_775_113262069.1513731997094--

.


Author: Antony Polukhin <antoshkka@gmail.com>
Date: Mon, 25 Dec 2017 21:12:15 +0300
Raw View
--001a1140f4b42b3af105612e1bd4
Content-Type: text/plain; charset="UTF-8"

On Dec 20, 2017 04:06, "Nicol Bolas" <jmckesson@gmail.com> wrote:
<...>

Just within this thread, we have identified a number of limitations on what
you can do with such objects. Let's not go further than merely what you've
already agree to: destruction of subobjects and layout. That is, this
optimization is not possible if any of the following is true:

1) The containing type has a non-defaulted destructor.
2) The containing object is not passed to another function by pointer or
reference, since that requires the object's layout to be consistent with
what the standard says.
3) The user of the containing object does not do anything layout-specific
itself.

Note that this is almost certainly* not* a complete list. It's merely the
ones talked about thus far; there are almost certainly others.


Since late November paper concentrates on cases when the callee is inlined.
In that case there's no need to mess with the object layout. But please,
wait for a moment and read further. I know that this point rises even more
questions.





Item #2 is particularly important. Why? Because that rules out calling* any
member functions*, since all non-static member functions take the object by
pointer. And that requires the object's layout to be consistent with its
definition.

Notice that "Motivating example #2" doesn't qualify for this, since we call
a function on the object. That requires it to have a certain layout.

So, how much real code actually qualifies for such elision?

Because here's the thing the person behind that proposal just doesn't get.
His proposal* doesn't work*. It does not solve the problem. Why?

Because compilers can't do it in so many of these cases. RVO was very
reliable; when compilers offered it, it worked for any case of returning a
prvalue. NRVO is pretty reliable; declare the variable at the top of the
function, return it whenever, and you're almost guaranteed to get the
optimization.


That's true. But let me put it other way around.

Compilers could do devirtualization. Does this optimization reliable? No,
it is very dependent on the compiler abilities and flags. Does the C++
Standard forbids that optimization? No, because it's an optimization and
users may benefit from it.

Just treat optimization from the "subobject copy elision" paper as some
random optimization: not something you could rely on, but something that
may help if compiler is clever enough.



What are the guidelines for getting this proposal's optimizations? What
circumstances stop it, and what can be done to avoid them?

Because here's the thing: if I do this:

string foo()
{
  string str;
  str = ...;
  return str;
}

If I do that, and I* don't* get elision, it's still fine. Why? Because I
still get automatic move support. `str` in the return statement is a
reference to an automatic variable in the function's scope, so it is moved
from. I may not have gotten the best answer, but I got a good enough one.

In this case:

string foo()
{
  pair<string, string> pr = ...;
  return pr.second;
}

What happens if this doesn't get elided? Well, you get a copy. The only way
to get a move is to ask for it: `return std::move(pr.second)`.


So the proposal actually* encourages bad code*, on the assumption that the
compiler will swoop in and save you.


You've got that impression from the assumption that the optimization is
something you could rely on, which is not true.

But the example with std::move that disables the copy elision is a good
catch. I've been thinking on that problem a lot a few weeks ago and
suddenly came up with a more generic solution:
http://apolukhin.github.io/papers/ultimate_copy_elision.html

I'd be grateful if you and other volunteers could take a look at it. It
addresses most of the above comments.

--
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/CAKqmYPbdMjxUOp9u%2BErcx%2BeYjvUJvAn%2BCZe5EDpgGd4vaz47ag%40mail.gmail.com.

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

<div dir=3D"ltr"><div dir=3D"auto"><div><br><div class=3D"gmail_extra"><br>=
<div class=3D"gmail_quote">On Dec 20, 2017 04:06, &quot;Nicol Bolas&quot; &=
lt;<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail=
..com</a>&gt; wrote:</div><div class=3D"gmail_quote">&lt;...&gt;<br><blockqu=
ote class=3D"gmail-m_7257956923552495514quote" style=3D"margin:0px 0px 0px =
0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"=
ltr"><div></div><div>Just within this thread, we have identified a number o=
f limitations on what you can do with such objects. Let&#39;s not go furthe=
r than merely what you&#39;ve already agree to: destruction of subobjects a=
nd layout. That is, this optimization is not possible if any of the followi=
ng is true:</div><div><br></div><div>1) The containing type has a non-defau=
lted destructor.</div><div>2) The containing object is not passed to anothe=
r function by pointer or reference, since that requires the object&#39;s la=
yout to be consistent with what the standard says.</div><div>3) The user of=
 the containing object does not do anything layout-specific itself.</div><d=
iv><br></div><div>Note that this is almost certainly<i> not</i> a complete =
list. It&#39;s merely the ones talked about thus far; there are almost cert=
ainly others.</div></div></blockquote></div></div></div><div dir=3D"auto"><=
br></div><div dir=3D"auto">Since late November paper concentrates on cases =
when the callee is inlined. In that case there&#39;s no need to mess with t=
he object layout. But please, wait for a moment and read further. I know th=
at this point rises even more questions.</div><div dir=3D"auto"><div class=
=3D"gmail_extra"><div class=3D"gmail_quote"><blockquote class=3D"gmail-m_72=
57956923552495514quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px s=
olid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><i></i></div>=
</div></blockquote></div></div></div><div dir=3D"auto"><br></div><div dir=
=3D"auto"><br></div><div dir=3D"auto"><br></div><div dir=3D"auto"><div clas=
s=3D"gmail_extra"><div class=3D"gmail_quote"><blockquote class=3D"gmail-m_7=
257956923552495514quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px =
solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><i><br></i><=
/div><div>Item #2 is particularly important. Why? Because that rules out ca=
lling<i> any member functions</i>, since all non-static member functions ta=
ke the object by pointer. And that requires the object&#39;s layout to be c=
onsistent with its definition.</div><div><br></div><div>Notice that &quot;<=
span style=3D"display:inline;float:none;background-color:transparent;color:=
rgb(34,34,34);font-family:&quot;Arial&quot;,&quot;Helvetica&quot;,sans-seri=
f;font-size:13px;font-style:normal;font-variant:normal;font-weight:400;lett=
er-spacing:normal;text-align:left;text-decoration:none;text-indent:0px;text=
-transform:none;white-space:normal;word-spacing:0px">Motivating example #2&=
quot; doesn&#39;t qualify for this, since we call a function on the object.=
 That requires it to have a certain layout.</span></div><div><span style=3D=
"display:inline;float:none;background-color:transparent;color:rgb(34,34,34)=
;font-family:&quot;Arial&quot;,&quot;Helvetica&quot;,sans-serif;font-size:1=
3px;font-style:normal;font-variant:normal;font-weight:400;letter-spacing:no=
rmal;text-align:left;text-decoration:none;text-indent:0px;text-transform:no=
ne;white-space:normal;word-spacing:0px"><br></span></div><div>So, how much =
real code actually qualifies for such elision?</div><div><br></div><div>Bec=
ause here&#39;s the thing the person behind that proposal just doesn&#39;t =
get. His proposal<i> doesn&#39;t work</i>. It does not solve the problem. W=
hy?</div><div><br></div><div>Because compilers can&#39;t do it in so many o=
f these cases. RVO was very reliable; when compilers offered it, it worked =
for any case of returning a prvalue. NRVO is pretty reliable; declare the v=
ariable at the top of the function, return it whenever, and you&#39;re almo=
st guaranteed to get the optimization.</div></div></blockquote></div></div>=
</div><div dir=3D"auto"><br></div><div dir=3D"auto">That&#39;s true. But le=
t me put it other way around.</div><div dir=3D"auto"><br></div><div dir=3D"=
auto">Compilers could do devirtualization. Does this optimization reliable?=
 No, it is very dependent on the compiler abilities and flags. Does the C++=
 Standard forbids that optimization? No, because it&#39;s an optimization a=
nd users may benefit from it.</div><div dir=3D"auto"><br></div><div dir=3D"=
auto">Just treat optimization from the &quot;subobject copy elision&quot; p=
aper as some random optimization: not something you could rely on, but some=
thing that may help if compiler is clever enough.</div><div dir=3D"auto"><b=
r></div><div dir=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gmail_e=
xtra"><div class=3D"gmail_quote"><blockquote class=3D"gmail-m_7257956923552=
495514quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(20=
4,204,204);padding-left:1ex"><div dir=3D"ltr"><div><br></div><div>What are =
the guidelines for getting this proposal&#39;s optimizations? What circumst=
ances stop it, and what can be done to avoid them?</div><div><br></div><div=
>Because here&#39;s the thing: if I do this:</div><div><br></div><div class=
=3D"gmail-m_7257956923552495514m_6661943320342599201prettyprint" style=3D"b=
order-color:rgb(187,187,187);border-style:solid;border-width:1px;background=
-color:rgb(250,250,250)"><code class=3D"gmail-m_7257956923552495514m_666194=
3320342599201prettyprint"><div class=3D"gmail-m_7257956923552495514m_666194=
3320342599201subprettyprint"><span class=3D"gmail-m_7257956923552495514m_66=
61943320342599201styled-by-prettify" style=3D"color:rgb(0,0,136)">string</s=
pan><span class=3D"gmail-m_7257956923552495514m_6661943320342599201styled-b=
y-prettify" style=3D"color:rgb(0,0,0)"> foo</span><span class=3D"gmail-m_72=
57956923552495514m_6661943320342599201styled-by-prettify" style=3D"color:rg=
b(102,102,0)">()</span><span class=3D"gmail-m_7257956923552495514m_66619433=
20342599201styled-by-prettify" style=3D"color:rgb(0,0,0)"><br></span><span =
class=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify=
" style=3D"color:rgb(102,102,0)">{</span><span class=3D"gmail-m_72579569235=
52495514m_6661943320342599201styled-by-prettify" style=3D"color:rgb(0,0,0)"=
><br>=C2=A0 </span><span class=3D"gmail-m_7257956923552495514m_666194332034=
2599201styled-by-prettify" style=3D"color:rgb(0,0,136)">string</span><span =
class=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify=
" style=3D"color:rgb(0,0,0)"> str</span><span class=3D"gmail-m_725795692355=
2495514m_6661943320342599201styled-by-prettify" style=3D"color:rgb(102,102,=
0)">;</span><span class=3D"gmail-m_7257956923552495514m_6661943320342599201=
styled-by-prettify" style=3D"color:rgb(0,0,0)"><br>=C2=A0 str </span><span =
class=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify=
" style=3D"color:rgb(102,102,0)">=3D</span><span class=3D"gmail-m_725795692=
3552495514m_6661943320342599201styled-by-prettify" style=3D"color:rgb(0,0,0=
)"> </span><span class=3D"gmail-m_7257956923552495514m_6661943320342599201s=
tyled-by-prettify" style=3D"color:rgb(102,102,0)">...;</span><span class=3D=
"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify" style=
=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span class=3D"gmail-m_725795692355=
2495514m_6661943320342599201styled-by-prettify" style=3D"color:rgb(0,0,136)=
">return</span><span class=3D"gmail-m_7257956923552495514m_6661943320342599=
201styled-by-prettify" style=3D"color:rgb(0,0,0)"> str</span><span class=3D=
"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify" style=
=3D"color:rgb(102,102,0)">;</span><span class=3D"gmail-m_725795692355249551=
4m_6661943320342599201styled-by-prettify" style=3D"color:rgb(0,0,0)"><br></=
span><span class=3D"gmail-m_7257956923552495514m_6661943320342599201styled-=
by-prettify" style=3D"color:rgb(102,102,0)">}</span></div></code></div><div=
><br></div><div>If I do that, and I<i> don&#39;t</i> get elision, it&#39;s =
still fine. Why? Because I still get automatic move support. `str` in the r=
eturn statement is a reference to an automatic variable in the function&#39=
;s scope, so it is moved from. I may not have gotten the best answer, but I=
 got a good enough one.</div><div><br></div><div>In this case:</div><div><b=
r></div><div class=3D"gmail-m_7257956923552495514m_6661943320342599201prett=
yprint" style=3D"border-color:rgb(187,187,187);border-style:solid;border-wi=
dth:1px;background-color:rgb(250,250,250)"><code class=3D"gmail-m_725795692=
3552495514m_6661943320342599201prettyprint"><div class=3D"gmail-m_725795692=
3552495514m_6661943320342599201subprettyprint"><span class=3D"gmail-m_72579=
56923552495514m_6661943320342599201styled-by-prettify" style=3D"color:rgb(0=
,0,136)">string</span><span class=3D"gmail-m_7257956923552495514m_666194332=
0342599201styled-by-prettify" style=3D"color:rgb(0,0,0)"> foo</span><span c=
lass=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify"=
 style=3D"color:rgb(102,102,0)">()</span><span class=3D"gmail-m_72579569235=
52495514m_6661943320342599201styled-by-prettify" style=3D"color:rgb(0,0,0)"=
><br></span><span class=3D"gmail-m_7257956923552495514m_6661943320342599201=
styled-by-prettify" style=3D"color:rgb(102,102,0)">{</span><span class=3D"g=
mail-m_7257956923552495514m_6661943320342599201styled-by-prettify" style=3D=
"color:rgb(0,0,0)"><br>=C2=A0 pair</span><span class=3D"gmail-m_72579569235=
52495514m_6661943320342599201styled-by-prettify" style=3D"color:rgb(102,102=
,0)">&lt;</span><span class=3D"gmail-m_7257956923552495514m_666194332034259=
9201styled-by-prettify" style=3D"color:rgb(0,0,136)">string</span><span cla=
ss=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify" s=
tyle=3D"color:rgb(102,102,0)">,</span><span class=3D"gmail-m_72579569235524=
95514m_6661943320342599201styled-by-prettify" style=3D"color:rgb(0,0,0)"> <=
/span><span class=3D"gmail-m_7257956923552495514m_6661943320342599201styled=
-by-prettify" style=3D"color:rgb(0,0,136)">string</span><span class=3D"gmai=
l-m_7257956923552495514m_6661943320342599201styled-by-prettify" style=3D"co=
lor:rgb(102,102,0)">&gt;</span><span class=3D"gmail-m_7257956923552495514m_=
6661943320342599201styled-by-prettify" style=3D"color:rgb(0,0,0)"> pr </spa=
n><span class=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-=
prettify" style=3D"color:rgb(102,102,0)">=3D</span><span class=3D"gmail-m_7=
257956923552495514m_6661943320342599201styled-by-prettify" style=3D"color:r=
gb(0,0,0)"> </span><span class=3D"gmail-m_7257956923552495514m_666194332034=
2599201styled-by-prettify" style=3D"color:rgb(102,102,0)">...;</span><span =
class=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify=
" style=3D"color:rgb(0,0,0)"><br>=C2=A0 </span><span class=3D"gmail-m_72579=
56923552495514m_6661943320342599201styled-by-prettify" style=3D"color:rgb(0=
,0,136)">return</span><span class=3D"gmail-m_7257956923552495514m_666194332=
0342599201styled-by-prettify" style=3D"color:rgb(0,0,0)"> pr</span><span cl=
ass=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify" =
style=3D"color:rgb(102,102,0)">.</span><span class=3D"gmail-m_7257956923552=
495514m_6661943320342599201styled-by-prettify" style=3D"color:rgb(0,0,0)">s=
econd</span><span class=3D"gmail-m_7257956923552495514m_6661943320342599201=
styled-by-prettify" style=3D"color:rgb(102,102,0)">;</span><span class=3D"g=
mail-m_7257956923552495514m_6661943320342599201styled-by-prettify" style=3D=
"color:rgb(0,0,0)"><br></span><span class=3D"gmail-m_7257956923552495514m_6=
661943320342599201styled-by-prettify" style=3D"color:rgb(102,102,0)">}</spa=
n></div></code></div><div><br></div><div>What happens if this doesn&#39;t g=
et elided? Well, you get a copy. The only way to get a move is to ask for i=
t: `return std::move(pr.second)`.</div></div></blockquote></div></div></div=
><div dir=3D"auto"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><b=
lockquote class=3D"gmail-m_7257956923552495514quote" style=3D"margin:0px 0p=
x 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div d=
ir=3D"ltr"><div><br></div><div>So the proposal actually<i> encourages bad c=
ode</i>, on the assumption that the compiler will swoop in and save you.</d=
iv></div></blockquote><div dir=3D"ltr"><div><br></div><div>You&#39;ve got t=
hat impression from the assumption that the optimization is something you c=
ould rely on, which is not true.<br></div></div><div dir=3D"ltr"><br></div>=
<div>But the example with std::move that disables the copy elision is a goo=
d catch. I&#39;ve been thinking on that problem a lot a few weeks ago and s=
uddenly came up with a more generic solution: <a href=3D"http://apolukhin.g=
ithub.io/papers/ultimate_copy_elision.html">http://apolukhin.github.io/pape=
rs/ultimate_copy_elision.html</a></div><div><br></div><div>I&#39;d be grate=
ful if you and other volunteers could take a look at it. It addresses most =
of the above comments.<br></div><div dir=3D"ltr"><br></div></div></div></di=
v></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/CAKqmYPbdMjxUOp9u%2BErcx%2BeYjvUJvAn%=
2BCZe5EDpgGd4vaz47ag%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAKqmYPbdMj=
xUOp9u%2BErcx%2BeYjvUJvAn%2BCZe5EDpgGd4vaz47ag%40mail.gmail.com</a>.<br />

--001a1140f4b42b3af105612e1bd4--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 25 Dec 2017 11:15:57 -0800 (PST)
Raw View
------=_Part_16495_1086335912.1514229357820
Content-Type: multipart/alternative;
 boundary="----=_Part_16496_647231060.1514229357821"

------=_Part_16496_647231060.1514229357821
Content-Type: text/plain; charset="UTF-8"

On Monday, December 25, 2017 at 1:12:19 PM UTC-5, Antony Polukhin wrote:
>
> On Dec 20, 2017 04:06, "Nicol Bolas" <jmck...@gmail.com <javascript:>>
> wrote:
> <...>
>
> Just within this thread, we have identified a number of limitations on
> what you can do with such objects. Let's not go further than merely what
> you've already agree to: destruction of subobjects and layout. That is,
> this optimization is not possible if any of the following is true:
>
> 1) The containing type has a non-defaulted destructor.
> 2) The containing object is not passed to another function by pointer or
> reference, since that requires the object's layout to be consistent with
> what the standard says.
> 3) The user of the containing object does not do anything layout-specific
> itself.
>
> Note that this is almost certainly* not* a complete list. It's merely the
> ones talked about thus far; there are almost certainly others.
>
>
> Since late November paper concentrates on cases when the callee is inlined.
>

OK, so now we've added a fourth requirement: the function must be
inlinable. Not declared `inline` or something that can be checked by actual
C++ syntax, but some nebulous "inlineable".

Why is this circumstance important enough to be *worth* all of this hassle?


> In that case there's no need to mess with the object layout. But please,
> wait for a moment and read further. I know that this point rises even more
> questions.
>
>
>
>
> Item #2 is particularly important. Why? Because that rules out calling*
> any member functions*, since all non-static member functions take the
> object by pointer. And that requires the object's layout to be consistent
> with its definition.
>
> Notice that "Motivating example #2" doesn't qualify for this, since we
> call a function on the object. That requires it to have a certain layout.
>
> So, how much real code actually qualifies for such elision?
>
> Because here's the thing the person behind that proposal just doesn't get.
> His proposal* doesn't work*. It does not solve the problem. Why?
>
> Because compilers can't do it in so many of these cases. RVO was very
> reliable; when compilers offered it, it worked for any case of returning a
> prvalue. NRVO is pretty reliable; declare the variable at the top of the
> function, return it whenever, and you're almost guaranteed to get the
> optimization.
>
>
> That's true. But let me put it other way around.
>
> Compilers could do devirtualization. Does this optimization reliable? No,
> it is very dependent on the compiler abilities and flags. Does the C++
> Standard forbids that optimization? No, because it's an optimization and
> users may benefit from it.
>
> Just treat optimization from the "subobject copy elision" paper as some
> random optimization: not something you could rely on, but something that
> may help if compiler is clever enough.
>

Then why take the time to change the standard to allow it?

What are the guidelines for getting this proposal's optimizations? What
> circumstances stop it, and what can be done to avoid them?
>
> Because here's the thing: if I do this:
>
> string foo()
> {
>   string str;
>   str = ...;
>   return str;
> }
>
> If I do that, and I* don't* get elision, it's still fine. Why? Because I
> still get automatic move support. `str` in the return statement is a
> reference to an automatic variable in the function's scope, so it is moved
> from. I may not have gotten the best answer, but I got a good enough one.
>
> In this case:
>
> string foo()
> {
>   pair<string, string> pr = ...;
>   return pr.second;
> }
>
> What happens if this doesn't get elided? Well, you get a copy. The only
> way to get a move is to ask for it: `return std::move(pr.second)`.
>
>
> So the proposal actually* encourages bad code*, on the assumption that
> the compiler will swoop in and save you.
>
>
> You've got that impression from the assumption that the optimization is
> something you could rely on, which is not true.
>

But we do rely on it.

When people write this code:

T func()
{
  T t;
  t.something();
  do_other_thing(t);
  return t;
};

It is written with the expectation that, on most compilers, this will not
perform unnecessary copies/moves. Pretty much every compiler still in use
gets this code right.

It doesn't matter if `func` is "inlineable" from the site of where you call
`func`. It doesn't matter how big `T` is or whether its trivial or not (OK,
some ABIs make trivial types under a certain size go into registers, but
that's *better* than copy elision...). This being optimized depends on
exactly two factors: how you write `func`, and how your compiler compiles
`func`. If you write `func` in a certain way, you have reasonable assurance
that compilers worth using will optimize it.

There is no such guideline for the cases you describe. They're all based on
various nebulous properties and random code transformation and the like.

But the example with std::move that disables the copy elision is a good
> catch. I've been thinking on that problem a lot a few weeks ago and
> suddenly came up with a more generic solution:
> http://apolukhin.github.io/papers/ultimate_copy_elision.html
>
> I'd be grateful if you and other volunteers could take a look at it. It
> addresses most of the above comments.
>

It addresses them poorly.

> Concern: Eliding copy/move constructors could break user code
> Resp: Yes, but only if the following constraint for copy constructor is
not satisfied: "After the definition T u = v;, u is equal to v".

What does "equal to" mean in this context? It is perfectly legitimate for
every instance of a `T` to have a unique identifying integer. The
comparison for `T` wouldn't compare this integer, but it certainly* could*
use the integer in other behavior (ie: strong vs. weak equality in
`operator<=>`).

Equally importantly, you're missing the issue of extracting a subobject
from an object without actually *extracting it*. I can no longer assume
that the object I construct as a subobject is in any way part of myself,
nor can it assume that any sibling subobjects will always be around. And
there's no way to declare that `T` is a type for which those subobjects
still being around matters.

> Concern: We want an emergency hatch to disable copy elision for
particular places.
> Resp: Usual practice to disable optimizations for a variable is to make
it volatile. This feature must be kept.

But `volatile` carries with it a* ton* of other baggage.

> Concern: The problem is not that big. Compilers could inline the
constructors and destructors and optimize the resulting code
> Resp: Unfortunately it is much harder to analyze the resulting code and
compilers fail in too many cases.

But you've presented no evidence that what you propose will make* any* of
those "too many cases" more optimal. There are no guarantees that the
compiler will optimize any of those.

Also, you never actually dealt with the main part of this argument: that "the
problem is not that big". Because it isn't that big.

--
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/924751e5-c880-42aa-95ab-99ef1050be2e%40isocpp.org.

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

<div dir=3D"ltr">On Monday, December 25, 2017 at 1:12:19 PM UTC-5, Antony P=
olukhin wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><div dir=3D"auto"><div><div><div class=3D"gmail_quote">On Dec 20, 2017 04:=
06, &quot;Nicol Bolas&quot; &lt;<a onmousedown=3D"this.href=3D&#39;javascri=
pt:&#39;;return true;" onclick=3D"this.href=3D&#39;javascript:&#39;;return =
true;" href=3D"javascript:" target=3D"_blank" rel=3D"nofollow" gdf-obfuscat=
ed-mailto=3D"HTMDmcZUCAAJ">jmck...@gmail.com</a>&gt; wrote:</div><div class=
=3D"gmail_quote">&lt;...&gt;<br><blockquote style=3D"margin:0px 0px 0px 0.8=
ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr=
"><div></div><div>Just within this thread, we have identified a number of l=
imitations on what you can do with such objects. Let&#39;s not go further t=
han merely what you&#39;ve already agree to: destruction of subobjects and =
layout. That is, this optimization is not possible if any of the following =
is true:</div><div><br></div><div>1) The containing type has a non-defaulte=
d destructor.</div><div>2) The containing object is not passed to another f=
unction by pointer or reference, since that requires the object&#39;s layou=
t to be consistent with what the standard says.</div><div>3) The user of th=
e containing object does not do anything layout-specific itself.</div><div>=
<br></div><div>Note that this is almost certainly<i> not</i> a complete lis=
t. It&#39;s merely the ones talked about thus far; there are almost certain=
ly others.</div></div></blockquote></div></div></div><div dir=3D"auto"><br>=
</div><div dir=3D"auto">Since late November paper concentrates on cases whe=
n the callee is inlined.</div></div></div></blockquote><div><br></div><div>=
OK, so now we&#39;ve added a fourth requirement: the function must be inlin=
able. Not declared `inline` or something that can be checked by actual C++ =
syntax, but some nebulous &quot;inlineable&quot;.</div><div><br></div><div>=
Why is this circumstance important enough to be <i>worth</i> all of this ha=
ssle?</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><d=
iv dir=3D"ltr"><div dir=3D"auto"><div dir=3D"auto">In that case there&#39;s=
 no need to mess with the object layout. But please, wait for a moment and =
read further. I know that this point rises even more questions.</div><div d=
ir=3D"auto"><div><div class=3D"gmail_quote"><blockquote style=3D"margin:0px=
 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><di=
v dir=3D"ltr"><div><i></i></div></div></blockquote></div></div></div><div d=
ir=3D"auto"><br></div><div dir=3D"auto"><br></div><div dir=3D"auto"><div><d=
iv class=3D"gmail_quote"><blockquote style=3D"margin:0px 0px 0px 0.8ex;bord=
er-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div>=
<i><br></i></div><div>Item #2 is particularly important. Why? Because that =
rules out calling<i> any member functions</i>, since all non-static member =
functions take the object by pointer. And that requires the object&#39;s la=
yout to be consistent with its definition.</div><div><br></div><div>Notice =
that &quot;<span style=3D"display:inline;float:none;background-color:transp=
arent;color:rgb(34,34,34);font-family:&quot;Arial&quot;,&quot;Helvetica&quo=
t;,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-wei=
ght:400;letter-spacing:normal;text-align:left;text-decoration:none;text-ind=
ent:0px;text-transform:none;white-space:normal;word-spacing:0px">Motivating=
 example #2&quot; doesn&#39;t qualify for this, since we call a function on=
 the object. That requires it to have a certain layout.</span></div><div><s=
pan style=3D"display:inline;float:none;background-color:transparent;color:r=
gb(34,34,34);font-family:&quot;Arial&quot;,&quot;Helvetica&quot;,sans-serif=
;font-size:13px;font-style:normal;font-variant:normal;font-weight:400;lette=
r-spacing:normal;text-align:left;text-decoration:none;text-indent:0px;text-=
transform:none;white-space:normal;word-spacing:0px"><br></span></div><div>S=
o, how much real code actually qualifies for such elision?</div><div><br></=
div><div>Because here&#39;s the thing the person behind that proposal just =
doesn&#39;t get. His proposal<i> doesn&#39;t work</i>. It does not solve th=
e problem. Why?</div><div><br></div><div>Because compilers can&#39;t do it =
in so many of these cases. RVO was very reliable; when compilers offered it=
, it worked for any case of returning a prvalue. NRVO is pretty reliable; d=
eclare the variable at the top of the function, return it whenever, and you=
&#39;re almost guaranteed to get the optimization.</div></div></blockquote>=
</div></div></div><div dir=3D"auto"><br></div><div dir=3D"auto">That&#39;s =
true. But let me put it other way around.</div><div dir=3D"auto"><br></div>=
<div dir=3D"auto">Compilers could do devirtualization. Does this optimizati=
on reliable? No, it is very dependent on the compiler abilities and flags. =
Does the C++ Standard forbids that optimization? No, because it&#39;s an op=
timization and users may benefit from it.</div><div dir=3D"auto"><br></div>=
<div dir=3D"auto">Just treat optimization from the &quot;subobject copy eli=
sion&quot; paper as some random optimization: not something you could rely =
on, but something that may help if compiler is clever enough.</div></div></=
div></blockquote><div><br></div><div>Then why take the time to change the s=
tandard to allow it?</div><div><br></div><blockquote class=3D"gmail_quote" =
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-l=
eft: 1ex;"><div dir=3D"ltr"><div dir=3D"auto"><div dir=3D"auto"><div><div c=
lass=3D"gmail_quote"><blockquote style=3D"margin:0px 0px 0px 0.8ex;border-l=
eft:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div>What=
 are the guidelines for getting this proposal&#39;s optimizations? What cir=
cumstances stop it, and what can be done to avoid them?</div><div><br></div=
><div>Because here&#39;s the thing: if I do this:</div><div><br></div><div =
style=3D"border-color:rgb(187,187,187);border-style:solid;border-width:1px;=
background-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,=
136)">string</span><span style=3D"color:rgb(0,0,0)"> foo</span><span style=
=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"><br></s=
pan><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0=
,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb(0,0,136)">string</span><s=
pan style=3D"color:rgb(0,0,0)"> str</span><span style=3D"color:rgb(102,102,=
0)">;</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 str </span><span st=
yle=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> </=
span><span style=3D"color:rgb(102,102,0)">...;</span><span style=3D"color:r=
gb(0,0,0)"><br>=C2=A0 </span><span style=3D"color:rgb(0,0,136)">return</spa=
n><span style=3D"color:rgb(0,0,0)"> str</span><span style=3D"color:rgb(102,=
102,0)">;</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"=
color:rgb(102,102,0)">}</span></div></code></div><div><br></div><div>If I d=
o that, and I<i> don&#39;t</i> get elision, it&#39;s still fine. Why? Becau=
se I still get automatic move support. `str` in the return statement is a r=
eference to an automatic variable in the function&#39;s scope, so it is mov=
ed from. I may not have gotten the best answer, but I got a good enough one=
..</div><div><br></div><div>In this case:</div><div><br></div><div style=3D"=
border-color:rgb(187,187,187);border-style:solid;border-width:1px;backgroun=
d-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,136)">str=
ing</span><span style=3D"color:rgb(0,0,0)"> foo</span><span style=3D"color:=
rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"><br></span><span =
style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"><br=
>=C2=A0 pair</span><span style=3D"color:rgb(102,102,0)">&lt;</span><span st=
yle=3D"color:rgb(0,0,136)">string</span><span style=3D"color:rgb(102,102,0)=
">,</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb=
(0,0,136)">string</span><span style=3D"color:rgb(102,102,0)">&gt;</span><sp=
an style=3D"color:rgb(0,0,0)"> pr </span><span style=3D"color:rgb(102,102,0=
)">=3D</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:=
rgb(102,102,0)">...;</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 </sp=
an><span style=3D"color:rgb(0,0,136)">return</span><span style=3D"color:rgb=
(0,0,0)"> pr</span><span style=3D"color:rgb(102,102,0)">.</span><span style=
=3D"color:rgb(0,0,0)">second</span><span style=3D"color:rgb(102,102,0)">;</=
span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(1=
02,102,0)">}</span></div></code></div><div><br></div><div>What happens if t=
his doesn&#39;t get elided? Well, you get a copy. The only way to get a mov=
e is to ask for it: `return std::move(pr.second)`.</div></div></blockquote>=
</div></div></div><div dir=3D"auto"><div><div class=3D"gmail_quote"><blockq=
uote style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,20=
4);padding-left:1ex"><div dir=3D"ltr"><div><br></div><div>So the proposal a=
ctually<i> encourages bad code</i>, on the assumption that the compiler wil=
l swoop in and save you.</div></div></blockquote><div dir=3D"ltr"><div><br>=
</div><div>You&#39;ve got that impression from the assumption that the opti=
mization is something you could rely on, which is not true.<br></div></div>=
</div></div></div></div></div></blockquote><div><br></div><div>But we do re=
ly on it.</div><div><br></div><div>When people write this code:</div><div><=
br></div><div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187=
, 187); word-wrap: break-word; background-color: rgb(250, 250, 250);"><code=
 class=3D"prettyprint"><div class=3D"subprettyprint"><span class=3D"styled-=
by-prettify" style=3D"color: #000;">T func</span><span class=3D"styled-by-p=
rettify" style=3D"color: #660;">()</span><span class=3D"styled-by-prettify"=
 style=3D"color: #000;"><br></span><span class=3D"styled-by-prettify" style=
=3D"color: #660;">{</span><span class=3D"styled-by-prettify" style=3D"color=
: #000;"><br>=C2=A0 T t</span><span class=3D"styled-by-prettify" style=3D"c=
olor: #660;">;</span><span class=3D"styled-by-prettify" style=3D"color: #00=
0;"><br>=C2=A0 t</span><span class=3D"styled-by-prettify" style=3D"color: #=
660;">.</span><span class=3D"styled-by-prettify" style=3D"color: #000;">som=
ething</span><span class=3D"styled-by-prettify" style=3D"color: #660;">();<=
/span><span class=3D"styled-by-prettify" style=3D"color: #000;"><br>=C2=A0 =
do_other_thing</span><span class=3D"styled-by-prettify" style=3D"color: #66=
0;">(</span><span class=3D"styled-by-prettify" style=3D"color: #000;">t</sp=
an><span class=3D"styled-by-prettify" style=3D"color: #660;">);</span><span=
 class=3D"styled-by-prettify" style=3D"color: #000;"><br>=C2=A0 </span><spa=
n class=3D"styled-by-prettify" style=3D"color: #008;">return</span><span cl=
ass=3D"styled-by-prettify" style=3D"color: #000;"> t</span><span class=3D"s=
tyled-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: #660;">};</span></div></code></div><div><br></div><div>=
It is written with the expectation that, on most compilers, this will not p=
erform unnecessary copies/moves. Pretty much every compiler still in use ge=
ts this code right.</div><div><br></div><div>It doesn&#39;t matter if `func=
` is &quot;inlineable&quot; from the site of where you call `func`. It does=
n&#39;t matter how big `T` is or whether its trivial or not (OK, some ABIs =
make trivial types under a certain size go into registers, but that&#39;s <=
i>better</i> than copy elision...). This being optimized depends on exactly=
 two factors: how you write `func`, and how your compiler compiles `func`. =
If you write `func` in a certain way, you have reasonable assurance that co=
mpilers worth using will optimize it.</div><div><br></div><div>There is no =
such guideline for the cases you describe. They&#39;re all based on various=
 nebulous properties and random code transformation and the like.</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 dir=3D"ltr"><d=
iv dir=3D"auto"><div dir=3D"auto"><div><div class=3D"gmail_quote"><div dir=
=3D"ltr"><div></div></div><div dir=3D"ltr">But the example with std::move t=
hat disables the copy elision is a good catch. I&#39;ve been thinking on th=
at problem a lot a few weeks ago and suddenly came up with a more generic s=
olution: <a onmousedown=3D"this.href=3D&#39;http://www.google.com/url?q\x3d=
http%3A%2F%2Fapolukhin.github.io%2Fpapers%2Fultimate_copy_elision.html\x26s=
a\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGKctCTQTa2Lt6fYMOA-sqoZHG2fQ&#39;;retur=
n true;" onclick=3D"this.href=3D&#39;http://www.google.com/url?q\x3dhttp%3A=
%2F%2Fapolukhin.github.io%2Fpapers%2Fultimate_copy_elision.html\x26sa\x3dD\=
x26sntz\x3d1\x26usg\x3dAFQjCNGKctCTQTa2Lt6fYMOA-sqoZHG2fQ&#39;;return true;=
" href=3D"http://apolukhin.github.io/papers/ultimate_copy_elision.html" tar=
get=3D"_blank" rel=3D"nofollow">http://apolukhin.github.io/<wbr>papers/ulti=
mate_copy_elision.<wbr>html</a></div><div><br></div><div>I&#39;d be gratefu=
l if you and other volunteers could take a look at it. It addresses most of=
 the above comments.<br></div></div></div></div></div></div></blockquote><d=
iv><br></div><div>It addresses them poorly.</div><div><br></div><div>&gt; C=
oncern: Eliding copy/move constructors could break user code<br>&gt; Resp: =
Yes, but only if the following constraint for copy constructor is not satis=
fied: &quot;After the definition T u =3D v;, u is equal to v&quot;.</div><d=
iv><br></div><div>What does &quot;equal to&quot; mean in this context? It i=
s perfectly legitimate for every instance of a `T` to have a unique identif=
ying integer. The comparison for `T` wouldn&#39;t compare this integer, but=
 it certainly<i> could</i> use the integer in other behavior (ie: strong vs=
.. weak equality in `operator&lt;=3D&gt;`).</div><div><br></div><div>Equally=
 importantly, you&#39;re missing the issue of extracting a subobject from a=
n object without actually <i>extracting it</i>. I can no longer assume that=
 the object I construct as a subobject is in any way part of myself, nor ca=
n it assume that any sibling subobjects will always be around. And there&#3=
9;s no way to declare that `T` is a type for which those subobjects still b=
eing around matters.</div><div><i><br></i></div><div>&gt;=C2=A0Concern: We =
want an emergency hatch to disable copy elision for particular places.<br>&=
gt; Resp: Usual practice to disable optimizations for a variable is to make=
 it volatile. This feature must be kept.</div><div><br></div><div>But `vola=
tile` carries with it a<i> ton</i> of other baggage.</div><div><br></div><d=
iv>&gt;=C2=A0Concern: The problem is not that big. Compilers could inline t=
he constructors and destructors and optimize the resulting code<br>&gt; Res=
p: Unfortunately it is much harder to analyze the resulting code and compil=
ers fail in too many cases.</div><div><br></div><div>But you&#39;ve present=
ed no evidence that what you propose will make<i> any</i> of those &quot;to=
o many cases&quot; more optimal. There are no guarantees that the compiler =
will optimize any of those.</div><div><br></div><div>Also, you never actual=
ly dealt with the main part of this argument: that &quot;<span style=3D"dis=
play: inline !important; float: none; background-color: transparent; color:=
 rgb(34, 34, 34); font-family: &quot;Arial&quot;,&quot;Helvetica&quot;,sans=
-serif; font-size: 13px; font-style: normal; font-variant: normal; font-wei=
ght: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decora=
tion: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-wid=
th: 0px; white-space: normal; word-spacing: 0px;">the </span>problem is not=
 that big&quot;. Because it isn&#39;t that big.</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/924751e5-c880-42aa-95ab-99ef1050be2e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/924751e5-c880-42aa-95ab-99ef1050be2e=
%40isocpp.org</a>.<br />

------=_Part_16496_647231060.1514229357821--

------=_Part_16495_1086335912.1514229357820--

.


Author: Eyal Rozenberg <eyalroz@technion.ac.il>
Date: Tue, 26 Dec 2017 10:05:43 +0100
Raw View

On 12/25/17 8:15 PM, Nicol Bolas wrote:
> On Monday, December 25, 2017 at 1:12:19 PM UTC-5, Antony Polukhin wrote:
>
> OK, so now we've added a fourth requirement: the function must be
> inlinable. Not declared `inline` or something that can be checked by
> actual C++ syntax, but some nebulous "inlineable".

The second "requirement" was not actually a requirement - and that's due
to the potential for inlining, as Antony has explained. If a function
call is avoided by inlining, then the compiler may figure out it the
caller+callee actually don't need the specific structuring of the
arguments to the callee.

> Why is this circumstance important enough to be /worth/ all of this hassle?

Because right now compilers are entirely-or-partially prevented from
applying a useful optimization in some relatively-common cases.

> Then why take the time to change the standard to allow it?

Because now it (seems to) prevent it, and definitely doesn't encourage it.

--
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/80bbb75a-2a62-537a-3733-898225325a41%40technion.ac.il.

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 26 Dec 2017 07:25:27 -0800 (PST)
Raw View
------=_Part_13377_1142503506.1514301927407
Content-Type: multipart/alternative;
 boundary="----=_Part_13378_1409979297.1514301927407"

------=_Part_13378_1409979297.1514301927407
Content-Type: text/plain; charset="UTF-8"

On Tuesday, December 26, 2017 at 4:05:52 AM UTC-5, Eyal Rozenberg wrote:
>
> On 12/25/17 8:15 PM, Nicol Bolas wrote:
> > On Monday, December 25, 2017 at 1:12:19 PM UTC-5, Antony Polukhin wrote:
> > Why is this circumstance important enough to be /worth/ all of this
> hassle?
>
> Because right now compilers are entirely-or-partially prevented from
> applying a useful optimization in some relatively-common cases.
>

I see little evidence that these cases are indeed "relatively-common"
enough to bother with this.

> Then why take the time to change the standard to allow it?
>
> Because now it (seems to) prevent it, and definitely doesn't encourage it.
>

Right, but that wasn't my question. My question was why we should take the
time to standardize something that's such a corner case. That compilers can
only apply such an optimization when the stars align just right.

--
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/83d8a425-fd2f-41b6-9941-2a5deb27806d%40isocpp.org.

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

<div dir=3D"ltr">On Tuesday, December 26, 2017 at 4:05:52 AM UTC-5, Eyal Ro=
zenberg wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 12/25/17 8:15=
 PM, Nicol Bolas wrote:
<br>&gt; On Monday, December 25, 2017 at 1:12:19 PM UTC-5, Antony Polukhin =
wrote:
<br>&gt; Why is this circumstance important enough to be /worth/ all of thi=
s hassle?
<br>
<br>Because right now compilers are entirely-or-partially prevented from
<br>applying a useful optimization in some relatively-common cases.<br></bl=
ockquote><div><br></div><div>I see little evidence that these cases are ind=
eed &quot;relatively-common&quot; enough to bother with this.</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;">&gt; Then why take the =
time to change the standard to allow it?
<br>
<br>Because now it (seems to) prevent it, and definitely doesn&#39;t encour=
age it.<br></blockquote><div><br></div><div>Right, but that wasn&#39;t my q=
uestion. My question was why we should take the time to standardize somethi=
ng that&#39;s such a corner case. That compilers can only apply such an opt=
imization when the stars align just right.</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/83d8a425-fd2f-41b6-9941-2a5deb27806d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/83d8a425-fd2f-41b6-9941-2a5deb27806d=
%40isocpp.org</a>.<br />

------=_Part_13378_1409979297.1514301927407--

------=_Part_13377_1142503506.1514301927407--

.


Author: David Krauss <potswa@gmail.com>
Date: Tue, 26 Dec 2017 23:33:47 +0100
Raw View
--Apple-Mail=_05AF0CC4-A682-48FE-B367-53B848E8527F
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="UTF-8"

Hi Antony,

This looks more like lifetime extension than copy elision. If the copy is e=
lided, then the complete object cannot be destroyed until the subobject is.=
 Quickly scanning through your =E2=80=9Cultimate=E2=80=9D paper, I don=E2=
=80=99t see this issue mentioned.

Since C++98 we already have a rule for lifetime extension when using a retu=
rn value subobject to initialize a scoped reference. So, does this feature =
not already exist with the syntax of declaring a reference? Also, the behav=
ior is required, not optional.

 - D


> On 2017=E2=80=9312=E2=80=9325, at 7:12 PM, Antony Polukhin <antoshkka@gma=
il.com> wrote:
>=20
>=20
>=20
> On Dec 20, 2017 04:06, "Nicol Bolas" <jmckesson@gmail.com <mailto:jmckess=
on@gmail.com>> wrote:
> <...>
> Just within this thread, we have identified a number of limitations on wh=
at you can do with such objects. Let's not go further than merely what you'=
ve already agree to: destruction of subobjects and layout. That is, this op=
timization is not possible if any of the following is true:
>=20
> 1) The containing type has a non-defaulted destructor.
> 2) The containing object is not passed to another function by pointer or =
reference, since that requires the object's layout to be consistent with wh=
at the standard says.
> 3) The user of the containing object does not do anything layout-specific=
 itself.
>=20
> Note that this is almost certainly not a complete list. It's merely the o=
nes talked about thus far; there are almost certainly others.
>=20
> Since late November paper concentrates on cases when the callee is inline=
d. In that case there's no need to mess with the object layout. But please,=
 wait for a moment and read further. I know that this point rises even more=
 questions.
>=20
>=20
>=20
>=20
> Item #2 is particularly important. Why? Because that rules out calling an=
y member functions, since all non-static member functions take the object b=
y pointer. And that requires the object's layout to be consistent with its =
definition.
>=20
> Notice that "Motivating example #2" doesn't qualify for this, since we ca=
ll a function on the object. That requires it to have a certain layout.
>=20
> So, how much real code actually qualifies for such elision?
>=20
> Because here's the thing the person behind that proposal just doesn't get=
.. His proposal doesn't work. It does not solve the problem. Why?
>=20
> Because compilers can't do it in so many of these cases. RVO was very rel=
iable; when compilers offered it, it worked for any case of returning a prv=
alue. NRVO is pretty reliable; declare the variable at the top of the funct=
ion, return it whenever, and you're almost guaranteed to get the optimizati=
on.
>=20
> That's true. But let me put it other way around.
>=20
> Compilers could do devirtualization. Does this optimization reliable? No,=
 it is very dependent on the compiler abilities and flags. Does the C++ Sta=
ndard forbids that optimization? No, because it's an optimization and users=
 may benefit from it.
>=20
> Just treat optimization from the "subobject copy elision" paper as some r=
andom optimization: not something you could rely on, but something that may=
 help if compiler is clever enough.
>=20
>=20
>=20
> What are the guidelines for getting this proposal's optimizations? What c=
ircumstances stop it, and what can be done to avoid them?
>=20
> Because here's the thing: if I do this:
>=20
> string foo()
> {
>   string str;
>   str =3D ...;
>   return str;
> }
>=20
> If I do that, and I don't get elision, it's still fine. Why? Because I st=
ill get automatic move support. `str` in the return statement is a referenc=
e to an automatic variable in the function's scope, so it is moved from. I =
may not have gotten the best answer, but I got a good enough one.
>=20
> In this case:
>=20
> string foo()
> {
>   pair<string, string> pr =3D ...;
>   return pr.second;
> }
>=20
> What happens if this doesn't get elided? Well, you get a copy. The only w=
ay to get a move is to ask for it: `return std::move(pr.second)`.
>=20
> So the proposal actually encourages bad code, on the assumption that the =
compiler will swoop in and save you.
>=20
> You've got that impression from the assumption that the optimization is s=
omething you could rely on, which is not true.
>=20
> But the example with std::move that disables the copy elision is a good c=
atch. I've been thinking on that problem a lot a few weeks ago and suddenly=
 came up with a more generic solution: http://apolukhin.github.io/papers/ul=
timate_copy_elision.html <http://apolukhin.github.io/papers/ultimate_copy_e=
lision.html>
>=20
> I'd be grateful if you and other volunteers could take a look at it. It a=
ddresses most of the above comments.
>=20
>=20
> --=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=
 email to std-proposals+unsubscribe@isocpp.org <mailto:std-proposals+unsubs=
cribe@isocpp.org>.
> To post to this group, send email to std-proposals@isocpp.org <mailto:std=
-proposals@isocpp.org>.
> To view this discussion on the web visit https://groups.google.com/a/isoc=
pp.org/d/msgid/std-proposals/CAKqmYPbdMjxUOp9u%2BErcx%2BeYjvUJvAn%2BCZe5EDp=
gGd4vaz47ag%40mail.gmail.com <https://groups.google.com/a/isocpp.org/d/msgi=
d/std-proposals/CAKqmYPbdMjxUOp9u%2BErcx%2BeYjvUJvAn%2BCZe5EDpgGd4vaz47ag%4=
0mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter>.

--=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/AD4FF975-B9C1-43C2-8214-07665ECDBA52%40gmail.com=
..

--Apple-Mail=_05AF0CC4-A682-48FE-B367-53B848E8527F
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset="UTF-8"

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D"">Hi Antony,<div cla=
ss=3D""><br class=3D""></div><div class=3D"">This looks more like lifetime =
extension than copy elision. If the copy is elided, then the complete objec=
t cannot be destroyed until the subobject is. Quickly scanning through your=
 =E2=80=9Cultimate=E2=80=9D paper, I don=E2=80=99t see this issue mentioned=
..</div><div class=3D""><br class=3D""></div><div class=3D"">Since C++98 we =
already have a rule for lifetime extension when using a return value subobj=
ect to initialize a scoped reference. So, does this feature not already exi=
st with the syntax of declaring a reference? Also, the behavior is required=
, not optional.</div><div class=3D""><br class=3D""></div><div class=3D""><=
span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>- D</div><d=
iv class=3D""><br class=3D""></div><div class=3D""><br class=3D""><div><blo=
ckquote type=3D"cite" class=3D""><div class=3D"">On 2017=E2=80=9312=E2=80=
=9325, at 7:12 PM, Antony Polukhin &lt;<a href=3D"mailto:antoshkka@gmail.co=
m" class=3D"">antoshkka@gmail.com</a>&gt; wrote:</div><br class=3D"Apple-in=
terchange-newline"><div class=3D""><div dir=3D"ltr" class=3D""><div dir=3D"=
auto" class=3D""><div class=3D""><br class=3D""><div class=3D"gmail_extra">=
<br class=3D""><div class=3D"gmail_quote">On Dec 20, 2017 04:06, "Nicol Bol=
as" &lt;<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank" class=3D""=
>jmckesson@gmail.com</a>&gt; wrote:</div><div class=3D"gmail_quote">&lt;...=
&gt;<br class=3D""><blockquote class=3D"gmail-m_7257956923552495514quote" s=
tyle=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);pad=
ding-left:1ex"><div dir=3D"ltr" class=3D""><div class=3D""></div><div class=
=3D"">Just within this thread, we have identified a number of limitations o=
n what you can do with such objects. Let's not go further than merely what =
you've already agree to: destruction of subobjects and layout. That is, thi=
s optimization is not possible if any of the following is true:</div><div c=
lass=3D""><br class=3D""></div><div class=3D"">1) The containing type has a=
 non-defaulted destructor.</div><div class=3D"">2) The containing object is=
 not passed to another function by pointer or reference, since that require=
s the object's layout to be consistent with what the standard says.</div><d=
iv class=3D"">3) The user of the containing object does not do anything lay=
out-specific itself.</div><div class=3D""><br class=3D""></div><div class=
=3D"">Note that this is almost certainly<i class=3D""> not</i> a complete l=
ist. It's merely the ones talked about thus far; there are almost certainly=
 others.</div></div></blockquote></div></div></div><div dir=3D"auto" class=
=3D""><br class=3D""></div><div dir=3D"auto" class=3D"">Since late November=
 paper concentrates on cases when the callee is inlined. In that case there=
's no need to mess with the object layout. But please, wait for a moment an=
d read further. I know that this point rises even more questions.</div><div=
 dir=3D"auto" class=3D""><div class=3D"gmail_extra"><div class=3D"gmail_quo=
te"><blockquote class=3D"gmail-m_7257956923552495514quote" style=3D"margin:=
0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">=
<div dir=3D"ltr" class=3D""><div class=3D""><i class=3D""></i></div></div><=
/blockquote></div></div></div><div dir=3D"auto" class=3D""><br class=3D""><=
/div><div dir=3D"auto" class=3D""><br class=3D""></div><div dir=3D"auto" cl=
ass=3D""><br class=3D""></div><div dir=3D"auto" class=3D""><div class=3D"gm=
ail_extra"><div class=3D"gmail_quote"><blockquote class=3D"gmail-m_72579569=
23552495514quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid r=
gb(204,204,204);padding-left:1ex"><div dir=3D"ltr" class=3D""><div class=3D=
""><i class=3D""><br class=3D""></i></div><div class=3D"">Item #2 is partic=
ularly important. Why? Because that rules out calling<i class=3D""> any mem=
ber functions</i>, since all non-static member functions take the object by=
 pointer. And that requires the object's layout to be consistent with its d=
efinition.</div><div class=3D""><br class=3D""></div><div class=3D"">Notice=
 that "<span style=3D"display:inline;float:none;background-color:transparen=
t;color:rgb(34,34,34);font-family:&quot;Arial&quot;,&quot;Helvetica&quot;,s=
ans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:=
400;letter-spacing:normal;text-align:left;text-decoration:none;text-indent:=
0px;text-transform:none;white-space:normal;word-spacing:0px" class=3D"">Mot=
ivating example #2" doesn't qualify for this, since we call a function on t=
he object. That requires it to have a certain layout.</span></div><div clas=
s=3D""><span style=3D"display:inline;float:none;background-color:transparen=
t;color:rgb(34,34,34);font-family:&quot;Arial&quot;,&quot;Helvetica&quot;,s=
ans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:=
400;letter-spacing:normal;text-align:left;text-decoration:none;text-indent:=
0px;text-transform:none;white-space:normal;word-spacing:0px" class=3D""><br=
 class=3D""></span></div><div class=3D"">So, how much real code actually qu=
alifies for such elision?</div><div class=3D""><br class=3D""></div><div cl=
ass=3D"">Because here's the thing the person behind that proposal just does=
n't get. His proposal<i class=3D""> doesn't work</i>. It does not solve the=
 problem. Why?</div><div class=3D""><br class=3D""></div><div class=3D"">Be=
cause compilers can't do it in so many of these cases. RVO was very reliabl=
e; when compilers offered it, it worked for any case of returning a prvalue=
.. NRVO is pretty reliable; declare the variable at the top of the function,=
 return it whenever, and you're almost guaranteed to get the optimization.<=
/div></div></blockquote></div></div></div><div dir=3D"auto" class=3D""><br =
class=3D""></div><div dir=3D"auto" class=3D"">That's true. But let me put i=
t other way around.</div><div dir=3D"auto" class=3D""><br class=3D""></div>=
<div dir=3D"auto" class=3D"">Compilers could do devirtualization. Does this=
 optimization reliable? No, it is very dependent on the compiler abilities =
and flags. Does the C++ Standard forbids that optimization? No, because it'=
s an optimization and users may benefit from it.</div><div dir=3D"auto" cla=
ss=3D""><br class=3D""></div><div dir=3D"auto" class=3D"">Just treat optimi=
zation from the "subobject copy elision" paper as some random optimization:=
 not something you could rely on, but something that may help if compiler i=
s clever enough.</div><div dir=3D"auto" class=3D""><br class=3D""></div><di=
v dir=3D"auto" class=3D""><br class=3D""></div><div dir=3D"auto" class=3D""=
><div class=3D"gmail_extra"><div class=3D"gmail_quote"><blockquote class=3D=
"gmail-m_7257956923552495514quote" style=3D"margin:0px 0px 0px 0.8ex;border=
-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr" class=
=3D""><div class=3D""><br class=3D""></div><div class=3D"">What are the gui=
delines for getting this proposal's optimizations? What circumstances stop =
it, and what can be done to avoid them?</div><div class=3D""><br class=3D""=
></div><div class=3D"">Because here's the thing: if I do this:</div><div cl=
ass=3D""><br class=3D""></div><div class=3D"gmail-m_7257956923552495514m_66=
61943320342599201prettyprint" style=3D"border-color:rgb(187,187,187);border=
-style:solid;border-width:1px;background-color:rgb(250,250,250)"><code clas=
s=3D"gmail-m_7257956923552495514m_6661943320342599201prettyprint"><div clas=
s=3D"gmail-m_7257956923552495514m_6661943320342599201subprettyprint"><span =
class=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify=
" style=3D"color:rgb(0,0,136)">string</span><span class=3D"gmail-m_72579569=
23552495514m_6661943320342599201styled-by-prettify" style=3D""> foo</span><=
span class=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-pre=
ttify" style=3D"color:rgb(102,102,0)">()</span><span class=3D"gmail-m_72579=
56923552495514m_6661943320342599201styled-by-prettify" style=3D""><br class=
=3D""></span><span class=3D"gmail-m_7257956923552495514m_666194332034259920=
1styled-by-prettify" style=3D"color:rgb(102,102,0)">{</span><span class=3D"=
gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify" style=
=3D""><br class=3D"">&nbsp; </span><span class=3D"gmail-m_72579569235524955=
14m_6661943320342599201styled-by-prettify" style=3D"color:rgb(0,0,136)">str=
ing</span><span class=3D"gmail-m_7257956923552495514m_6661943320342599201st=
yled-by-prettify" style=3D""> str</span><span class=3D"gmail-m_725795692355=
2495514m_6661943320342599201styled-by-prettify" style=3D"color:rgb(102,102,=
0)">;</span><span class=3D"gmail-m_7257956923552495514m_6661943320342599201=
styled-by-prettify" style=3D""><br class=3D"">&nbsp; str </span><span class=
=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify" sty=
le=3D"color:rgb(102,102,0)">=3D</span><span class=3D"gmail-m_72579569235524=
95514m_6661943320342599201styled-by-prettify" style=3D""> </span><span clas=
s=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify" st=
yle=3D"color:rgb(102,102,0)">...;</span><span class=3D"gmail-m_725795692355=
2495514m_6661943320342599201styled-by-prettify" style=3D""><br class=3D"">&=
nbsp; </span><span class=3D"gmail-m_7257956923552495514m_666194332034259920=
1styled-by-prettify" style=3D"color:rgb(0,0,136)">return</span><span class=
=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify" sty=
le=3D""> str</span><span class=3D"gmail-m_7257956923552495514m_666194332034=
2599201styled-by-prettify" style=3D"color:rgb(102,102,0)">;</span><span cla=
ss=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify" s=
tyle=3D""><br class=3D""></span><span class=3D"gmail-m_7257956923552495514m=
_6661943320342599201styled-by-prettify" style=3D"color:rgb(102,102,0)">}</s=
pan></div></code></div><div class=3D""><br class=3D""></div><div class=3D""=
>If I do that, and I<i class=3D""> don't</i> get elision, it's still fine. =
Why? Because I still get automatic move support. `str` in the return statem=
ent is a reference to an automatic variable in the function's scope, so it =
is moved from. I may not have gotten the best answer, but I got a good enou=
gh one.</div><div class=3D""><br class=3D""></div><div class=3D"">In this c=
ase:</div><div class=3D""><br class=3D""></div><div class=3D"gmail-m_725795=
6923552495514m_6661943320342599201prettyprint" style=3D"border-color:rgb(18=
7,187,187);border-style:solid;border-width:1px;background-color:rgb(250,250=
,250)"><code class=3D"gmail-m_7257956923552495514m_6661943320342599201prett=
yprint"><div class=3D"gmail-m_7257956923552495514m_6661943320342599201subpr=
ettyprint"><span class=3D"gmail-m_7257956923552495514m_6661943320342599201s=
tyled-by-prettify" style=3D"color:rgb(0,0,136)">string</span><span class=3D=
"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify" style=
=3D""> foo</span><span class=3D"gmail-m_7257956923552495514m_66619433203425=
99201styled-by-prettify" style=3D"color:rgb(102,102,0)">()</span><span clas=
s=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify" st=
yle=3D""><br class=3D""></span><span class=3D"gmail-m_7257956923552495514m_=
6661943320342599201styled-by-prettify" style=3D"color:rgb(102,102,0)">{</sp=
an><span class=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by=
-prettify" style=3D""><br class=3D"">&nbsp; pair</span><span class=3D"gmail=
-m_7257956923552495514m_6661943320342599201styled-by-prettify" style=3D"col=
or:rgb(102,102,0)">&lt;</span><span class=3D"gmail-m_7257956923552495514m_6=
661943320342599201styled-by-prettify" style=3D"color:rgb(0,0,136)">string</=
span><span class=3D"gmail-m_7257956923552495514m_6661943320342599201styled-=
by-prettify" style=3D"color:rgb(102,102,0)">,</span><span class=3D"gmail-m_=
7257956923552495514m_6661943320342599201styled-by-prettify" style=3D""> </s=
pan><span class=3D"gmail-m_7257956923552495514m_6661943320342599201styled-b=
y-prettify" style=3D"color:rgb(0,0,136)">string</span><span class=3D"gmail-=
m_7257956923552495514m_6661943320342599201styled-by-prettify" style=3D"colo=
r:rgb(102,102,0)">&gt;</span><span class=3D"gmail-m_7257956923552495514m_66=
61943320342599201styled-by-prettify" style=3D""> pr </span><span class=3D"g=
mail-m_7257956923552495514m_6661943320342599201styled-by-prettify" style=3D=
"color:rgb(102,102,0)">=3D</span><span class=3D"gmail-m_7257956923552495514=
m_6661943320342599201styled-by-prettify" style=3D""> </span><span class=3D"=
gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify" style=
=3D"color:rgb(102,102,0)">...;</span><span class=3D"gmail-m_725795692355249=
5514m_6661943320342599201styled-by-prettify" style=3D""><br class=3D"">&nbs=
p; </span><span class=3D"gmail-m_7257956923552495514m_6661943320342599201st=
yled-by-prettify" style=3D"color:rgb(0,0,136)">return</span><span class=3D"=
gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify" style=
=3D""> pr</span><span class=3D"gmail-m_7257956923552495514m_666194332034259=
9201styled-by-prettify" style=3D"color:rgb(102,102,0)">.</span><span class=
=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify" sty=
le=3D"">second</span><span class=3D"gmail-m_7257956923552495514m_6661943320=
342599201styled-by-prettify" style=3D"color:rgb(102,102,0)">;</span><span c=
lass=3D"gmail-m_7257956923552495514m_6661943320342599201styled-by-prettify"=
 style=3D""><br class=3D""></span><span class=3D"gmail-m_725795692355249551=
4m_6661943320342599201styled-by-prettify" style=3D"color:rgb(102,102,0)">}<=
/span></div></code></div><div class=3D""><br class=3D""></div><div class=3D=
"">What happens if this doesn't get elided? Well, you get a copy. The only =
way to get a move is to ask for it: `return std::move(pr.second)`.</div></d=
iv></blockquote></div></div></div><div dir=3D"auto" class=3D""><div class=
=3D"gmail_extra"><div class=3D"gmail_quote"><blockquote class=3D"gmail-m_72=
57956923552495514quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px s=
olid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr" class=3D""><div cl=
ass=3D""><br class=3D""></div><div class=3D"">So the proposal actually<i cl=
ass=3D""> encourages bad code</i>, on the assumption that the compiler will=
 swoop in and save you.</div></div></blockquote><div dir=3D"ltr" class=3D""=
><div class=3D""><br class=3D""></div><div class=3D"">You've got that impre=
ssion from the assumption that the optimization is something you could rely=
 on, which is not true.<br class=3D""></div></div><div dir=3D"ltr" class=3D=
""><br class=3D""></div><div class=3D"">But the example with std::move that=
 disables the copy elision is a good catch. I've been thinking on that prob=
lem a lot a few weeks ago and suddenly came up with a more generic solution=
: <a href=3D"http://apolukhin.github.io/papers/ultimate_copy_elision.html" =
class=3D"">http://apolukhin.github.io/papers/ultimate_copy_elision.html</a>=
</div><div class=3D""><br class=3D""></div><div class=3D"">I'd be grateful =
if you and other volunteers could take a look at it. It addresses most of t=
he above comments.<br class=3D""></div><div dir=3D"ltr" class=3D""><br clas=
s=3D""></div></div></div></div></div>
</div><div class=3D""><br class=3D"webkit-block-placeholder"></div>

-- <br class=3D"">
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.<br class=3D"">
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" class=3D"">=
std-proposals+unsubscribe@isocpp.org</a>.<br class=3D"">
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" class=3D"">std-proposals@isocpp.org</a>.<br class=3D"">
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAKqmYPbdMjxUOp9u%2BErcx%2BeYjvUJvAn%=
2BCZe5EDpgGd4vaz47ag%40mail.gmail.com?utm_medium=3Demail&amp;utm_source=3Df=
ooter" class=3D"">https://groups.google.com/a/isocpp.org/d/msgid/std-propos=
als/CAKqmYPbdMjxUOp9u%2BErcx%2BeYjvUJvAn%2BCZe5EDpgGd4vaz47ag%40mail.gmail.=
com</a>.<br class=3D"">
</div></blockquote></div><br class=3D""></div></body></html>

<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/AD4FF975-B9C1-43C2-8214-07665ECDBA52%=
40gmail.com?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/AD4FF975-B9C1-43C2-8214-07665ECDBA52%=
40gmail.com</a>.<br />

--Apple-Mail=_05AF0CC4-A682-48FE-B367-53B848E8527F--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 26 Dec 2017 16:29:54 -0800 (PST)
Raw View
------=_Part_19462_2109906277.1514334594111
Content-Type: multipart/alternative;
 boundary="----=_Part_19463_584074063.1514334594111"

------=_Part_19463_584074063.1514334594111
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Tuesday, December 26, 2017 at 5:33:51 PM UTC-5, David Krauss wrote:
>
> Hi Antony,
>
> This looks more like lifetime extension than copy elision. If the copy is=
=20
> elided, then the complete object cannot be destroyed until the subobject=
=20
> is. Quickly scanning through your =E2=80=9Cultimate=E2=80=9D paper, I don=
=E2=80=99t see this issue=20
> mentioned.
>

This was discussed earlier in the thread, but the general gist as I=20
understand it is that, if the destructor is non-trivial (perhaps=20
recursively?), then no elision can take place. Or to put it the right way=
=20
around, elision of this sort can only take place if the compiler can* prove=
*=20
that nothing in any of the destructors that need to be executed will notice=
=20
that the particular subobject's lifetime has not yet ended.

Basically, the idea is that compilers won't be able to do this except in=20
cases where the subobjects are all *definitively* independent of one=20
another.

Since C++98 we already have a rule for lifetime extension when using a=20
> return value subobject to initialize a scoped reference. So, does this=20
> feature not already exist with the syntax of declaring a reference?
>

.... hmm, that's interesting; you can perform lifetime extension on=20
subobjects of the main object.

But ultimately, you can't do it that way due to calling conventions. If a=
=20
function says that it returns a reference, then the ABI for the caller=20
probably only provides one pointer's worth of storage for the return value.=
=20
But if you have this "lifetime extension" idea, the caller would have to=20
provide sufficient space for the entire object that contains the subobject.=
=20
How will it know it needs to do that?

Basically, elision has to be able to work between two pieces of code=20
without any more knowledge between them than the function's signature.=20
That's why earlier parts of the thread discuss matters of having the=20
compiler separating out subobjects and so forth, since the function's=20
signature only contains the type of the subobject. So if elision were=20
possible on some subobject, the compiler would have to basically strip out=
=20
part of the object, such that part of it is in one place and part is in=20
another.

And therefore, if you ever pass a pointer/reference of the main object to=
=20
some other code, the optimization is not possible (since the other code=20
would only be aware of the object's original layout). And similarly, no=20
optimization can happen if you start doing pointer gymnastics to the object=
..

That's what makes this whole proposal dodgy. It paints itself into such a=
=20
corner that the optimization can only be providedin highly limited and not=
=20
easily definable circumstances.
=20

> Also, the behavior is required, not optional.
>

--=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/9f2b0bec-41ae-4463-a7e2-31a54886e1fc%40isocpp.or=
g.

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

<div dir=3D"ltr">On Tuesday, December 26, 2017 at 5:33:51 PM UTC-5, David K=
rauss wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word=
-wrap:break-word">Hi Antony,<div><br></div><div>This looks more like lifeti=
me extension than copy elision. If the copy is elided, then the complete ob=
ject cannot be destroyed until the subobject is. Quickly scanning through y=
our =E2=80=9Cultimate=E2=80=9D paper, I don=E2=80=99t see this issue mentio=
ned.</div></div></blockquote><div><br></div><div>This was discussed earlier=
 in the thread, but the general gist as I understand it is that, if the des=
tructor is non-trivial (perhaps recursively?), then no elision can take pla=
ce. Or to put it the right way around, elision of this sort can only take p=
lace if the compiler can<i> prove</i> that nothing in any of the destructor=
s that need to be executed will notice that the particular subobject&#39;s =
lifetime has not yet ended.</div><div><br></div><div>Basically, the idea is=
 that compilers won&#39;t be able to do this except in cases where the subo=
bjects are all <i>definitively</i> independent of one another.</div><div><b=
r></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wra=
p:break-word"><div>Since C++98 we already have a rule for lifetime extensio=
n when using a return value subobject to initialize a scoped reference. So,=
 does this feature not already exist with the syntax of declaring a referen=
ce?</div></div></blockquote><div><br></div><div>... hmm, that&#39;s interes=
ting; you can perform lifetime extension on subobjects of the main object.<=
/div><div><br></div><div>But ultimately, you can&#39;t do it that way due t=
o calling conventions. If a function says that it returns a reference, then=
 the ABI for the caller probably only provides one pointer&#39;s worth of s=
torage for the return value. But if you have this &quot;lifetime extension&=
quot; idea, the caller would have to provide sufficient space for the entir=
e object that contains the subobject. How will it know it needs to do that?=
</div><div><br></div><div>Basically, elision has to be able to work between=
 two pieces of code without any more knowledge between them than the functi=
on&#39;s signature. That&#39;s why earlier parts of the thread discuss matt=
ers of having the compiler separating out subobjects and so forth, since th=
e function&#39;s signature only contains the type of the subobject. So if e=
lision were possible on some subobject, the compiler would have to basicall=
y strip out part of the object, such that part of it is in one place and pa=
rt is in another.</div><div><br></div><div>And therefore, if you ever pass =
a pointer/reference of the main object to some other code, the optimization=
 is not possible (since the other code would only be aware of the object&#3=
9;s original layout). And similarly, no optimization can happen if you star=
t doing pointer gymnastics to the object.</div><div><br></div><div>That&#39=
;s what makes this whole proposal dodgy. It paints itself into such a corne=
r that the optimization can only be providedin highly limited and not easil=
y definable circumstances.</div><div>=C2=A0</div><blockquote class=3D"gmail=
_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;p=
adding-left: 1ex;"><div style=3D"word-wrap:break-word"><div>Also, the behav=
ior is required, not optional.<br></div></div></blockquote></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/9f2b0bec-41ae-4463-a7e2-31a54886e1fc%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/9f2b0bec-41ae-4463-a7e2-31a54886e1fc=
%40isocpp.org</a>.<br />

------=_Part_19463_584074063.1514334594111--

------=_Part_19462_2109906277.1514334594111--

.


Author: Antony Polukhin <antoshkka@gmail.com>
Date: Thu, 28 Dec 2017 10:01:21 +0300
Raw View
--94eb2c1c00f4670c1e056161151b
Content-Type: text/plain; charset="UTF-8"

2017-12-26 18:25 GMT+03:00 Nicol Bolas <jmckesson@gmail.com>:

> On Tuesday, December 26, 2017 at 4:05:52 AM UTC-5, Eyal Rozenberg wrote:
>>
>> On 12/25/17 8:15 PM, Nicol Bolas wrote:
>> > On Monday, December 25, 2017 at 1:12:19 PM UTC-5, Antony Polukhin
>> wrote:
>> > Why is this circumstance important enough to be /worth/ all of this
>> hassle?
>>
>> Because right now compilers are entirely-or-partially prevented from
>> applying a useful optimization in some relatively-common cases.
>>
>
> I see little evidence that these cases are indeed "relatively-common"
> enough to bother with this.
>

I've added an example where moving out std::string produces much worse
assembly than with move elision of subobjects. Is that example convincing?
It's in the "The problem is not that big" concern
http://apolukhin.github.io/papers/ultimate_copy_elision.html

--
Best regards,
Antony Polukhin

--
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/CAKqmYPYTBDjbzhuaNKZd54XqEx7W%3Dx4HrmP390CqMODNP7E0Rg%40mail.gmail.com.

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

<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">2017-12-26 18:25 GMT+03:00 Nicol Bolas <span dir=3D"ltr">&lt;<a href=3D=
"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>&gt;<=
/span>:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.=
8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"lt=
r"><span class=3D"gmail-">On Tuesday, December 26, 2017 at 4:05:52 AM UTC-5=
, Eyal Rozenberg wrote:</span><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:=
1ex"><span class=3D"gmail-">On 12/25/17 8:15 PM, Nicol Bolas wrote:
<br>&gt; On Monday, December 25, 2017 at 1:12:19 PM UTC-5, Antony Polukhin =
wrote:
<br></span><span class=3D"gmail-">&gt; Why is this circumstance important e=
nough to be /worth/ all of this hassle?
<br>
<br>Because right now compilers are entirely-or-partially prevented from
<br>applying a useful optimization in some relatively-common cases.<br></sp=
an></blockquote><div><br></div><div>I see little evidence that these cases =
are indeed &quot;relatively-common&quot; enough to bother with this.</div><=
/div></blockquote><div><br></div><div>I&#39;ve added an example where movin=
g out std::string produces much worse assembly than with move elision of su=
bobjects. Is that example convincing? It&#39;s in the &quot;The problem is =
not that big&quot; concern <a href=3D"http://apolukhin.github.io/papers/ult=
imate_copy_elision.html">http://apolukhin.github.io/papers/ultimate_copy_el=
ision.html</a><br></div><div><br></div></div>-- <br><div class=3D"gmail_sig=
nature">Best regards,<br>Antony Polukhin</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/CAKqmYPYTBDjbzhuaNKZd54XqEx7W%3Dx4Hrm=
P390CqMODNP7E0Rg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAKqmYPYTBDjbzh=
uaNKZd54XqEx7W%3Dx4HrmP390CqMODNP7E0Rg%40mail.gmail.com</a>.<br />

--94eb2c1c00f4670c1e056161151b--

.


Author: Antony Polukhin <antoshkka@gmail.com>
Date: Thu, 28 Dec 2017 11:02:32 +0300
Raw View
--f403045e9f503551d0056161f054
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

2017-12-27 1:33 GMT+03:00 David Krauss <potswa@gmail.com>:

> Hi Antony,
>
> This looks more like lifetime extension than copy elision. If the copy is
> elided, then the complete object cannot be destroyed until the subobject
> is. Quickly scanning through your =E2=80=9Cultimate=E2=80=9D paper, I don=
=E2=80=99t see this issue
> mentioned.
>
> Since C++98 we already have a rule for lifetime extension when using a
> return value subobject to initialize a scoped reference. So, does this
> feature not already exist with the syntax of declaring a reference? Also,
> the behavior is required, not optional.
>

That's different. The paper is mostly about removing copy/move+destructor
from the assembly or intermediate-representation. This does not extend the
lifetime of the objects as you see them in C++ code.

--=20
Best regards,
Antony Polukhin

--=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/CAKqmYPbnrh-dDTA7HAGuGZkgphtPRr6AYCXtuTUWesEBzbC=
UNQ%40mail.gmail.com.

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

<div dir=3D"ltr"><br><div class=3D"gmail_extra"><div class=3D"gmail_quote">=
2017-12-27 1:33 GMT+03:00 David Krauss <span dir=3D"ltr">&lt;<a href=3D"mai=
lto:potswa@gmail.com" target=3D"_blank">potswa@gmail.com</a>&gt;</span>:<br=
><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border=
-left:1px solid rgb(204,204,204);padding-left:1ex"><div style=3D"overflow-w=
rap: break-word;">Hi Antony,<div><br></div><div>This looks more like lifeti=
me extension than copy elision. If the copy is elided, then the complete ob=
ject cannot be destroyed until the subobject is. Quickly scanning through y=
our =E2=80=9Cultimate=E2=80=9D paper, I don=E2=80=99t see this issue mentio=
ned.</div><div><br></div><div>Since C++98 we already have a rule for lifeti=
me extension when using a return value subobject to initialize a scoped ref=
erence. So, does this feature not already exist with the syntax of declarin=
g a reference? Also, the behavior is required, not optional.<br clear=3D"al=
l"></div></div></blockquote><div><br></div><div>That&#39;s different. The p=
aper is mostly about removing copy/move+destructor from the assembly or int=
ermediate-representation. This does not extend the lifetime of the objects =
as you see them in C++ code.<br></div></div><br>-- <br><div class=3D"gmail_=
signature">Best regards,<br>Antony Polukhin</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/CAKqmYPbnrh-dDTA7HAGuGZkgphtPRr6AYCXt=
uTUWesEBzbCUNQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAKqmYPbnrh-dDTA7=
HAGuGZkgphtPRr6AYCXtuTUWesEBzbCUNQ%40mail.gmail.com</a>.<br />

--f403045e9f503551d0056161f054--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 28 Dec 2017 06:37:09 -0800 (PST)
Raw View
------=_Part_24263_1533839675.1514471829825
Content-Type: multipart/alternative;
 boundary="----=_Part_24264_1901850552.1514471829826"

------=_Part_24264_1901850552.1514471829826
Content-Type: text/plain; charset="UTF-8"

On Thursday, December 28, 2017 at 2:01:25 AM UTC-5, Antony Polukhin wrote:
>
> 2017-12-26 18:25 GMT+03:00 Nicol Bolas <jmck...@gmail.com <javascript:>>:
>
>> On Tuesday, December 26, 2017 at 4:05:52 AM UTC-5, Eyal Rozenberg wrote:
>>>
>>> On 12/25/17 8:15 PM, Nicol Bolas wrote:
>>> > On Monday, December 25, 2017 at 1:12:19 PM UTC-5, Antony Polukhin
>>> wrote:
>>> > Why is this circumstance important enough to be /worth/ all of this
>>> hassle?
>>>
>>> Because right now compilers are entirely-or-partially prevented from
>>> applying a useful optimization in some relatively-common cases.
>>>
>>
>> I see little evidence that these cases are indeed "relatively-common"
>> enough to bother with this.
>>
>
> I've added an example where moving out std::string produces much worse
> assembly than with move elision of subobjects. Is that example convincing?
>

No. It demonstrates nothing about how* common* this case is. My point here
was that the cases where this circumstance would be encountered, would
happen within a type where the compiler could actually implement elision,
and would be in a case where elision was possible within the rules we've
discussed, is such a rare occurrence that it's essentially irrelevant.

You can create all the artificial examples you want, but it doesn't show
how often this would matter in the real world.

Also, that example doesn't effectively demonstrate what the assembly would
look like, since it's not actually doing elision. Elision is not the same
thing as* inlining*.


> It's in the "The problem is not that big" concern
> http://apolukhin.github.io/papers/ultimate_copy_elision.html
>
>

--
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/2bcc2be2-fafb-4c9b-ab85-a22fca83e3d6%40isocpp.org.

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

<div dir=3D"ltr">On Thursday, December 28, 2017 at 2:01:25 AM UTC-5, Antony=
 Polukhin 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"><div><div class=3D"gmail_quote">2017-12-26 18:25 GMT+03:00 Nicol Bolas <=
span dir=3D"ltr">&lt;<a onmousedown=3D"this.href=3D&#39;javascript:&#39;;re=
turn true;" onclick=3D"this.href=3D&#39;javascript:&#39;;return true;" href=
=3D"javascript:" target=3D"_blank" rel=3D"nofollow" gdf-obfuscated-mailto=
=3D"D8sz_ucbCQAJ">jmck...@gmail.com</a>&gt;</span>:<br><blockquote class=3D=
"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(2=
04,204,204);padding-left:1ex"><div dir=3D"ltr"><span>On Tuesday, December 2=
6, 2017 at 4:05:52 AM UTC-5, Eyal Rozenberg wrote:</span><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rg=
b(204,204,204);padding-left:1ex"><span>On 12/25/17 8:15 PM, Nicol Bolas wro=
te:
<br>&gt; On Monday, December 25, 2017 at 1:12:19 PM UTC-5, Antony Polukhin =
wrote:
<br></span><span>&gt; Why is this circumstance important enough to be /wort=
h/ all of this hassle?
<br>
<br>Because right now compilers are entirely-or-partially prevented from
<br>applying a useful optimization in some relatively-common cases.<br></sp=
an></blockquote><div><br></div><div>I see little evidence that these cases =
are indeed &quot;relatively-common&quot; enough to bother with this.</div><=
/div></blockquote><div><br></div><div>I&#39;ve added an example where movin=
g out std::string produces much worse assembly than with move elision of su=
bobjects. Is that example convincing?</div></div></div></div></blockquote><=
div><br></div><div>No. It demonstrates nothing about how<i> common</i> this=
 case is. My point here was that the cases where this circumstance would be=
 encountered, would happen within a type where the compiler could actually =
implement elision, and would be in a case where elision was possible within=
 the rules we&#39;ve discussed, is such a rare occurrence that it&#39;s ess=
entially irrelevant.</div><div><br></div><div>You can create all the artifi=
cial examples you want, but it doesn&#39;t show how often this would matter=
 in the real world.</div><div><br></div><div>Also, that example doesn&#39;t=
 effectively demonstrate what the assembly would look like, since it&#39;s =
not actually doing elision. Elision is not the same thing as<i> inlining</i=
>.</div><div><i></i><i></i>=C2=A0</div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>It&#39;s in =
the &quot;The problem is not that big&quot; concern <a onmousedown=3D"this.=
href=3D&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fapolukhin.github.io=
%2Fpapers%2Fultimate_copy_elision.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAF=
QjCNGKctCTQTa2Lt6fYMOA-sqoZHG2fQ&#39;;return true;" onclick=3D"this.href=3D=
&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fapolukhin.github.io%2Fpape=
rs%2Fultimate_copy_elision.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGKc=
tCTQTa2Lt6fYMOA-sqoZHG2fQ&#39;;return true;" href=3D"http://apolukhin.githu=
b.io/papers/ultimate_copy_elision.html" target=3D"_blank" rel=3D"nofollow">=
http://apolukhin.github.io/<wbr>papers/ultimate_copy_elision.<wbr>html</a><=
br></div><div><br></div></div>
</div></div>
</blockquote></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/2bcc2be2-fafb-4c9b-ab85-a22fca83e3d6%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/2bcc2be2-fafb-4c9b-ab85-a22fca83e3d6=
%40isocpp.org</a>.<br />

------=_Part_24264_1901850552.1514471829826--

------=_Part_24263_1533839675.1514471829825--

.