Topic: Guarantee copy elision for complete objects


Author: Antonio Perez <antonio@perezexcelsior.com>
Date: Wed, 30 May 2018 15:19:53 -0700 (PDT)
Raw View
------=_Part_526_1798395223.1527718793571
Content-Type: multipart/alternative;
 boundary="----=_Part_527_595244410.1527718793571"

------=_Part_527_595244410.1527718793571
Content-Type: text/plain; charset="UTF-8"

*An error in the proposal*
As specified now, it would be impossible to return by copy elision in the
below situation:

Foo getFoo(bool b) {
    Foo A;
    if(b) {
        Foo B;
        return B;
    }
    return A;
}

The compiler has to know ahead of time whether to construct A or to
construct B in the memory location where Foo is going to be placed, but
because of the conditional, this can't happen

*Possible resolution*
*For copy/move elision to occur, none of the possible return values can
appear in the same scope. If this constraint is satisfied,
copy/move elision is guaranteed.*

Example:
Foo getFoo1(bool ABswitch)
{
    Foo C;
    if(switch) {
        Foo A;
        return A;
    } else {
        Foo B;
        return B;
    }
} //Copy elision guaranteed; C is not a possible return value

Foo getFoo2(bool ABswitch)
{
    Foo C;
    Foo A;
    if(ABswitch) {
        return A;
    } else {
        Foo B;
        return B;
    }
} //Copy elision NOT guaranteed; A and B appear in the same scope and both
are possible return values

Here, in getFoo1 the possible return values are A and B. C is not a
possible return value as there is no return statement returning C. In
getFoo1, A and B never appear in the same scope, so copy elision can be
guaranteed.

On the other hand, in getFoo2, the possible return values are (again) A and
B, but A and B appear in the same scope, so copy elision can't be
guaranteed.

--
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/6e799aae-f20e-429a-9abf-d8cec86cccb6%40isocpp.org.

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

<div dir=3D"ltr"><b>An error in the proposal</b><div>As specified now, it w=
ould be impossible to return by copy elision in the below situation:</div><=
div><br></div><div><div class=3D"prettyprint" style=3D"background-color: rg=
b(250, 250, 250); border: 1px solid rgb(187, 187, 187); word-wrap: break-wo=
rd;"><code class=3D"prettyprint"><div class=3D"subprettyprint" style=3D"car=
et-color: rgb(102, 0, 102);"><font color=3D"#000000"><span style=3D"color: =
#606;" class=3D"styled-by-prettify">Foo</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> getFoo</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">bool</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> b</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span=
><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> A</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">if</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">b</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #606;" class=3D"styled-b=
y-prettify">Foo</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> B</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> B</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <br>=C2=
=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>return</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> A<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">}</span></font></div></cod=
e></div><div><br></div>The compiler has to know ahead of time whether to co=
nstruct A or to construct B in the memory location where Foo is going to be=
 placed, but because of the conditional, this can&#39;t happen</div><div><b=
r></div><div><b>Possible resolution</b></div><div><b>For copy/move elision =
to occur, none of the possible return values can appear in the same scope. =
If this constraint is satisfied, copy/move=C2=A0elision is guaranteed.</b>=
=C2=A0</div><div><br></div><div>Example:</div><div><div class=3D"prettyprin=
t" style=3D"background-color: rgb(250, 250, 250); border: 1px solid rgb(187=
, 187, 187); word-wrap: break-word;"><code class=3D"prettyprint"><div class=
=3D"subprettyprint" style=3D"caret-color: rgb(102, 0, 102);"><font color=3D=
"#000088"><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</sp=
an></font><span style=3D"color: #000;" class=3D"styled-by-prettify"> getFoo=
1</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><=
font color=3D"#000000"><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">bool</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 </span><span style=3D"color: #606;" class=3D"styled-by-prettify">ABswitch<=
/span></font><span style=3D"color: #660;" class=3D"styled-by-prettify">)</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> <br></span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><s=
pan style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> C</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">if</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">switch</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #606;" class=3D"style=
d-by-prettify">Foo</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> A</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> A</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">else</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </spa=
n><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> B</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> <br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> B</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"style=
d-by-prettify">//Copy elision guaranteed; C is not a possible return value<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></s=
pan><font color=3D"#000088"><span style=3D"color: #606;" class=3D"styled-by=
-prettify">Foo</span></font><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> getFoo2</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">(</span><font color=3D"#000000"><span style=3D"color: #008;" class=
=3D"styled-by-prettify">bool</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-p=
rettify">ABswitch</span></font><span style=3D"color: #660;" class=3D"styled=
-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> <br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color: #606;" class=3D"styled-by-prettify"=
>Foo</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> C</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </spa=
n><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> A</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">if</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #606;"=
 class=3D"styled-by-prettify">ABswitch</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><font color=3D"#660066"><span style=
=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> A</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">;</span></font><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">else</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">Foo</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> B</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 <br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> B</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
 style=3D"color: #800;" class=3D"styled-by-prettify">//Copy elision NOT gua=
ranteed; A and B appear in the same scope and both are possible return valu=
es</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></sp=
an></div></code></div><br>Here, in getFoo1 the possible return values are A=
 and B. C is not a possible return value as there is no return statement re=
turning C. In getFoo1, A and B never appear in the same scope, so copy elis=
ion can be guaranteed.=C2=A0</div><div><br></div><div>On the other hand, in=
 getFoo2, the possible return values are (again) A and B, but A and B appea=
r in the same scope, so copy elision can&#39;t be guaranteed.=C2=A0<br><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/6e799aae-f20e-429a-9abf-d8cec86cccb6%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/6e799aae-f20e-429a-9abf-d8cec86cccb6=
%40isocpp.org</a>.<br />

------=_Part_527_595244410.1527718793571--

------=_Part_526_1798395223.1527718793571--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 30 May 2018 15:55:15 -0700 (PDT)
Raw View
------=_Part_773_153621449.1527720915757
Content-Type: multipart/alternative;
 boundary="----=_Part_774_615354869.1527720915757"

------=_Part_774_615354869.1527720915757
Content-Type: text/plain; charset="UTF-8"



On Wednesday, May 30, 2018 at 5:49:25 PM UTC-4, Antonio Perez wrote:
>
> *Proposal*
> Copy/move elision for objects returned from a function is mandatory, even
> if the move or copy constructors of that object have side-effects.
>

Elision is not turned off just because copy/move constructors have side
effects. Indeed, the reason why elision as a rule exists is to *specifically
allow* compilers to generate code that does not exhibit those side effects.

Further, the address of the returned object must be identical in the
> function returning it and the calling function:
>

Why would this ever be useful?

*How this could kinda-sorta be achieved now*
> This section is a demonstration that compilers have the capacity to do
> this.
>

We already know compilers can perform elision.

On Wednesday, May 30, 2018 at 6:19:53 PM UTC-4, Antonio Perez wrote:

> *An error in the proposal*
> As specified now, it would be impossible to return by copy elision in the
> below situation:
>
> Foo getFoo(bool b) {
>     Foo A;
>     if(b) {
>         Foo B;
>         return B;
>     }
>     return A;
> }
>
>
It's not impossible. If the compiler can detect if `Foo A`'s default
constructor does nothing, then it can effectively move the construction of
`Foo` to after the condition.

You should look at my draft/idea for return value variables
<https://github.com/NicolBolas/Proposal-Ideas/blob/master/Named%20Return%20Value%20Variables.md>.
Same basic idea, except that the requirements are enforced by the compiler
directly. Even if the syntax for declaring such a variable is just an
attribute, the compiler can at least let you know when you failed to uphold
your part of the agreement.

--
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/28079f1b-b884-4402-8fcd-4f058e03a221%40isocpp.org.

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

<div dir=3D"ltr"><div><br><br>On Wednesday, May 30, 2018 at 5:49:25 PM UTC-=
4, Antonio Perez wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div di=
r=3D"ltr"><div><span><b><font color=3D"#444444">Proposal</font></b></span><=
/div><div><span><font color=3D"#444444">Copy/move
 elision for objects returned from a function is mandatory, even if the=20
move or copy constructors of that object have side-effects.</font></span></=
div></div></blockquote><div><br></div><div>Elision is not turned off just b=
ecause copy/move constructors have side effects. Indeed, the reason why eli=
sion as a rule exists is to <i>specifically allow</i> compilers to generate=
 code that does not exhibit those side effects.<br></div><div><br></div><bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><span></spa=
n></div><div><span><div style=3D"background-color:rgb(250,250,250);border:1=
px solid rgb(187,187,187);word-wrap:break-word"><code><div><span style=3D"c=
olor:#606"></span><span style=3D"color:#660"></span></div></code></div></sp=
an>Further, the address of the returned object must be identical in the fun=
ction returning it and the calling function:</div></div></blockquote><div><=
br></div><div>Why would this ever be useful?<br></div><div><br></div><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><b>How this co=
uld kinda-sorta be achieved now</b></div><div>This section is a demonstrati=
on that compilers have the capacity to do this.</div></div></blockquote><di=
v><br></div><div>We already know compilers can perform elision.</div></div>=
<div><br></div><div>On Wednesday, May 30, 2018 at 6:19:53 PM UTC-4, Antonio=
 Perez wrote:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr"><b>An error in the proposal</b><div>As specified now, it would be imp=
ossible to return by copy elision in the below situation:</div><div><br></d=
iv><div><div style=3D"background-color:rgb(250,250,250);border:1px solid rg=
b(187,187,187);word-wrap:break-word"><code><div><font color=3D"#000000"><sp=
an style=3D"color:#606">Foo</span><span style=3D"color:#000"> getFoo</span>=
<span style=3D"color:#660">(</span><span style=3D"color:#008">bool</span><s=
pan style=3D"color:#000"> b</span><span style=3D"color:#660">)</span><span =
style=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#606">Foo</sp=
an><span style=3D"color:#000"> A</span><span style=3D"color:#660">;</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#00=
8">if</span><span style=3D"color:#660">(</span><span style=3D"color:#000">b=
</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#606">Foo</span><span styl=
e=3D"color:#000"> B</span><span style=3D"color:#660">;</span><span style=3D=
"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#0=
08">return</span><span style=3D"color:#000"> B</span><span style=3D"color:#=
660">;</span><span style=3D"color:#000"> <br>=C2=A0 =C2=A0 </span><span sty=
le=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </sp=
an><span style=3D"color:#008">return</span><span style=3D"color:#000"> A</s=
pan><span style=3D"color:#660">;</span><span style=3D"color:#000"><br></spa=
n><span style=3D"color:#660">}</span></font></div></code></div><div><br></d=
iv></div></div></blockquote><div><br></div><div>It&#39;s not impossible. If=
 the compiler can detect if `Foo A`&#39;s default constructor does nothing,=
 then it can effectively move the construction of `Foo` to after the condit=
ion.</div><div><br></div><div>You should look at <a href=3D"https://github.=
com/NicolBolas/Proposal-Ideas/blob/master/Named%20Return%20Value%20Variable=
s.md">my draft/idea for return value variables</a>. Same basic idea, except=
 that the requirements are enforced by the compiler directly. Even if the s=
yntax for declaring such a variable is just an attribute, the compiler can =
at least let you know when you failed to uphold your part of the agreement.=
<br></div><div></div><br></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/28079f1b-b884-4402-8fcd-4f058e03a221%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/28079f1b-b884-4402-8fcd-4f058e03a221=
%40isocpp.org</a>.<br />

------=_Part_774_615354869.1527720915757--

------=_Part_773_153621449.1527720915757--

.


Author: Antonio Perez <antonio@perezexcelsior.com>
Date: Wed, 30 May 2018 18:27:01 -0700 (PDT)
Raw View
------=_Part_1258_1777323851.1527730021463
Content-Type: multipart/alternative;
 boundary="----=_Part_1259_812725183.1527730021464"

------=_Part_1259_812725183.1527730021464
Content-Type: text/plain; charset="UTF-8"


>
> Why would this ever be useful?
>

Suppose that I create a object that stores the head of a doubly-linked
list. If copy elision doesn't preserve the address of the value
being returned, then suddenly the linked list is an invalid state.

This requirement isn't difficult to implement. Space for the returned
object is allocated on the stack prior to the function call, and then the
function instantiates the object it's going to return within the space
allocated prior to the function call. When the function exits, anything
added to the stack over the course of the function call is deallocated, and
everyone's happy. Due to the "as-if" principle, if no one ever takes the
address of the returned object, then the compiler is free to keep it
entirely in the CPU's registers.

It's not impossible. If the compiler can detect if `Foo A`'s default
> constructor does nothing, then it can effectively move the construction of
> `Foo` to after the condition.

In that specific instance, yes, however in the general case it's not always
possible. If A is created, has some operations performed on it, then B is
created and B depends on A, the compiler can't re-order the construction of
A and B, meaning that if either A or B could be returned based on what
happens at runtime, one of them can be returned by copy elision, and the
other one would have to be copied.

You should look at my draft/idea for return value variables
> <https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2FNicolBolas%2FProposal-Ideas%2Fblob%2Fmaster%2FNamed%2520Return%2520Value%2520Variables.md&sa=D&sntz=1&usg=AFQjCNFDfTNeTK6LoZJ0o0kIeY4_C4y5tA>.
> Same basic idea, except that the requirements are enforced by the compiler
> directly. Even if the syntax for declaring such a variable is just an
> attribute, the compiler can at least let you know when you failed to uphold
> your part of the agreement.
>

Thank you for sharing your proposal! I think that the goal of my proposal
aligns with yours: we both want to expand the scope within which copy
elision can take place, to allow the return of immobile values from a
function.

*My proposal, in terms of yours: *any complete object, let's call it X,
that is potentially returned from a function whose type matches the return
type of the function is *automatically* a Return Value Variable unless (1)
there is another compete object within the scope of X that has already been
determined to be a Return Value Variable OR (2) a prvalue is potentially
returned from the function after X is instantiated. Here "is potentially"
means "could occur based on what happens at runtime".

*Examples:*
Foo foo() {
   Foo A; //A is automatically the RVV
   if( /* some condition */ ) {
      //B is not a RVV because A already got that designation
      Foo B;
      return B;
   }
   return A;
}

Foo foo() {
   Foo A; //A would have been a RVV except the function might still return
a prvalue
   if( /* some condition */ ) {
      return Foo(); //return prvalue after A is instantiated
   }
   return A;
}

Foo foo() {
   if( /* some condition */ ) {
      return Foo(); //return prvalue
   }
   //A is automatically the RVV because if instantiated, it's definitely
returned,
   //And a RVV doesn't already exist in A's scope.
   Foo A;
   return A;
}

Foo foo() {
   if( /* some condition */ ) {
      Foo B; //B is automatically the RVV in this scope;
      return B; //return prvalue
   }
   //A is automatically the RVV because if instantiated, it's definitely
returned
   //And B falls outside of A's scope, so A can be safely created in the
space occupied by B
   Foo A;
   return A;
}


--
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/515d0d91-f5a5-404f-b278-f4b75d974cc8%40isocpp.org.

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

<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px=
 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-c=
olor: rgb(204, 204, 204); padding-left: 1ex;">Why would this ever be useful=
?<br></blockquote><div><br></div>S<span style=3D"color: rgb(0, 0, 0); caret=
-color: rgb(136, 136, 136);">uppose that I create a object that stores the =
head of a doubly-linked list. If copy=C2=A0elision doesn&#39;t preserve the=
 address of the value being=C2=A0returned, then suddenly the linked list is=
 an invalid state.=C2=A0</span><br><div><font color=3D"#000000"><span style=
=3D"caret-color: rgb(136, 136, 136);"><br></span></font></div><div><font co=
lor=3D"#000000"><span style=3D"caret-color: rgb(136, 136, 136);">This requi=
rement isn&#39;t difficult to implement. Space for the returned object is a=
llocated on the stack prior to the function call, and then the function ins=
tantiates the object it&#39;s going to return within the space allocated pr=
ior to the function call. When the function exits, anything added to the=C2=
=A0stack over the course of the function call is deallocated, and everyone&=
#39;s happy. Due to the &quot;as-if&quot; principle, if no one ever takes t=
he address of the returned object, then the compiler is free to keep it ent=
irely in the CPU&#39;s registers.=C2=A0</span></font></div><div><font color=
=3D"#000000"><span style=3D"caret-color: rgb(136, 136, 136);"><br></span></=
font></div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0=
..8ex; border-left-width: 1px; border-left-style: solid; border-left-color: =
rgb(204, 204, 204); padding-left: 1ex;">It&#39;s not impossible. If the com=
piler can detect if `Foo A`&#39;s default constructor does nothing, then it=
 can effectively move the construction of `Foo` to after the condition.</bl=
ockquote><div>In that specific instance, yes, however in the general case i=
t&#39;s not always possible. If A is created, has some operations performed=
 on it, then B is created and B depends on A, the compiler can&#39;t re-ord=
er the construction of A and B, meaning that if either A or B could be retu=
rned based on what happens at runtime, one of them can be returned by copy =
elision, and the other one would have to be copied.=C2=A0</div><div><br></d=
iv><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; bo=
rder-left-width: 1px; border-left-style: solid; border-left-color: rgb(204,=
 204, 204); padding-left: 1ex;">You should look at=C2=A0<a href=3D"https://=
www.google.com/url?q=3Dhttps%3A%2F%2Fgithub.com%2FNicolBolas%2FProposal-Ide=
as%2Fblob%2Fmaster%2FNamed%2520Return%2520Value%2520Variables.md&amp;sa=3DD=
&amp;sntz=3D1&amp;usg=3DAFQjCNFDfTNeTK6LoZJ0o0kIeY4_C4y5tA" target=3D"_blan=
k" rel=3D"nofollow" style=3D"cursor: pointer;">my draft/idea for return val=
ue variables</a>. Same basic idea, except that the requirements are enforce=
d by the compiler directly. Even if the syntax for declaring such a variabl=
e is just an attribute, the compiler can at least let you know when you fai=
led to uphold your part of the agreement.<br></blockquote><div><br></div><d=
iv>Thank you for sharing your proposal! I think that the goal of my proposa=
l aligns with yours: we both want to expand the scope within which copy eli=
sion can take place, to allow the return of immobile values from a function=
..=C2=A0</div><div><br></div><div><b>My proposal, in terms of yours: </b>any=
 complete object, let&#39;s call it X, that is potentially returned from a =
function whose type matches the return type of the function is <i>automatic=
ally</i> a Return Value Variable unless (1) there is another compete object=
 within the scope of X that has already been determined to be a Return Valu=
e Variable OR (2) a prvalue is potentially returned from the function after=
 X is instantiated. Here &quot;is potentially&quot; means &quot;could occur=
 based on what happens at runtime&quot;.=C2=A0</div><div><br></div><div><b>=
Examples:</b></div><div><div class=3D"prettyprint" style=3D"background-colo=
r: rgb(250, 250, 250); border: 1px solid rgb(187, 187, 187); word-wrap: bre=
ak-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint" style=
=3D"caret-color: rgb(102, 0, 102);"><span style=3D"color: #606;" class=3D"s=
tyled-by-prettify">Foo</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> foo</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0</s=
pan><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> A</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" =
class=3D"styled-by-prettify">//A is automatically the RVV</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0</span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">if</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><font color=3D"#666600"><span=
 style=3D"color: #800;" class=3D"styled-by-prettify">/* some condition */</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span></font><span s=
tyle=3D"color: rgb(136, 0, 0);"><span style=3D"color: #800;" class=3D"style=
d-by-prettify">//B is not a RVV because A already got that designation</spa=
n></span><font color=3D"#666600"><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span></font><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #606;" c=
lass=3D"styled-by-prettify">Foo</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> B</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> <br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> B</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br>=C2=A0 =C2=A0</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>=C2=A0 =C2=A0</span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">return</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 A</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> =C2=A0 =C2=A0<br=
></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><=
/div></code></div><div><br></div><div class=3D"prettyprint" style=3D"backgr=
ound-color: rgb(250, 250, 250); border: 1px solid rgb(187, 187, 187); word-=
wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint=
"><font><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> foo</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0</span><span style=3D"color: =
#606;" class=3D"styled-by-prettify">Foo</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> A</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><font color=3D"#880000"><span style=3D"caret-color: rgb=
(102, 0, 102);"><span style=3D"color: #800;" class=3D"styled-by-prettify">/=
/A would have been a RVV except the function might still return a prvalue</=
span></span></font><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br>=C2=A0 =C2=A0</span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">if</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #800;" class=3D"styled-by-prettify">/* some condition=
 */</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
06;" class=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">();</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by=
-prettify">//return prvalue after A is instantiated</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> A</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br></span></font></div></code></div><br><div class=3D"prettypri=
nt" style=3D"background-color: rgb(250, 250, 250); border: 1px solid rgb(18=
7, 187, 187); word-wrap: break-word;"><code class=3D"prettyprint"><div clas=
s=3D"subprettyprint"><span style=3D"color: #606;" class=3D"styled-by-pretti=
fy">Foo</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> fo=
o</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">if</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D=
"styled-by-prettify">/* some condition */</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">F=
oo</span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #800;" class=3D"styled-by-prettify">//return prvalue</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0</s=
pan><span style=3D"caret-color: rgb(102, 0, 102); color: rgb(136, 0, 0);"><=
span style=3D"color: #800;" class=3D"styled-by-prettify">//A is automatical=
ly the RVV because if instantiated, it&#39;s definitely returned,</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">=C2=A0 =C2=A0</span=
><span style=3D"color: #800;" class=3D"styled-by-prettify">//And a RVV does=
n&#39;t already exist in A&#39;s scope. </span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0</span><span style=3D"color:=
 #606;" class=3D"styled-by-prettify">Foo</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> A</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> <br>=C2=A0 =C2=A0</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> A</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><=
/div></code></div><br><div class=3D"prettyprint" style=3D"background-color:=
 rgb(250, 250, 250); border: 1px solid rgb(187, 187, 187); word-wrap: break=
-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span sty=
le=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> foo</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 =C2=A0</span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">if</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 </span><span style=3D"color: #800;" class=3D"styled-by-prettify">/* some c=
ondition */</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><sp=
an style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> B</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">//B is automatically the RVV in this scope;</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">ret=
urn</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><font color=3D"#660066"><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify">B</span></font><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #800;" class=3D"styled-by-prettify">//return prv=
alue</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0</span><span style=3D"caret-color: rgb(102, 0, 102); color: rg=
b(136, 0, 0);"><span style=3D"color: #800;" class=3D"styled-by-prettify">//=
A is automatically the RVV because if instantiated, it&#39;s definitely ret=
urned</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span></span><span style=3D"color: #000;" class=3D"styled-by-prettify">=C2=
=A0 =C2=A0</span><span style=3D"color: #800;" class=3D"styled-by-prettify">=
//And B falls outside of A&#39;s scope, so A can be safely created in the s=
pace occupied by B</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br>=C2=A0 =C2=A0</span><span style=3D"color: #606;" class=3D"style=
d-by-prettify">Foo</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> A</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <br>=C2=
=A0 =C2=A0</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
return</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> A</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br></span></div></code></div><br><b=
r></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/515d0d91-f5a5-404f-b278-f4b75d974cc8%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/515d0d91-f5a5-404f-b278-f4b75d974cc8=
%40isocpp.org</a>.<br />

------=_Part_1259_812725183.1527730021464--

------=_Part_1258_1777323851.1527730021463--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 30 May 2018 20:33:16 -0700 (PDT)
Raw View
------=_Part_1730_1231868501.1527737597005
Content-Type: multipart/alternative;
 boundary="----=_Part_1731_1712970117.1527737597006"

------=_Part_1731_1712970117.1527737597006
Content-Type: text/plain; charset="UTF-8"

On Wednesday, May 30, 2018 at 9:27:01 PM UTC-4, Antonio Perez wrote:
>
> Why would this ever be useful?
>>
>
> Suppose that I create a object that stores the head of a doubly-linked
> list. If copy elision doesn't preserve the address of the value
> being returned, then suddenly the linked list is an invalid state.
>

I'm not sure I understand. If you have object A, which stores a pointer to
"the head of a doubly-linked list", which we will call object B, what's the
problem? Are you saying that you create an object B on the stack and pass
its pointer off to some other object A, which will now rely upon it to
exist in that location? Even though such an object can *easily* stop
existing simply by the user not storing the return value of the function?

That sounds like a pointlessly and *dangerously* fragile interface,
regardless of whether you could do it or not. We don't want to encourage
people to store pointers to stack objects like this.

Oh, and here's a show-stopper for this idea: the Itanium ABI forbids it.

If your function returns an `int`, that `int` will be a register under the
Itanium ABI. You can take the address of an `int` stack variable, but you
can't take the address of a register. So if you take the `int`'s address,
the compiler must make the stack variable take up actual stack space. But
stack variable cannot truly be the `int` return value object because that
object *has no address* under the Itanium ABI.

Note that this is a problem for my idea too... probably. Mine never
directly states that the address of the return value variable will be the
address of whatever the prvalue return is used to initialize. But by
calling it "the return value object", that is the implication.

You should look at my draft/idea for return value variables
>> <https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2FNicolBolas%2FProposal-Ideas%2Fblob%2Fmaster%2FNamed%2520Return%2520Value%2520Variables.md&sa=D&sntz=1&usg=AFQjCNFDfTNeTK6LoZJ0o0kIeY4_C4y5tA>.
>> Same basic idea, except that the requirements are enforced by the compiler
>> directly. Even if the syntax for declaring such a variable is just an
>> attribute, the compiler can at least let you know when you failed to uphold
>> your part of the agreement.
>>
>
> Thank you for sharing your proposal! I think that the goal of my proposal
> aligns with yours: we both want to expand the scope within which copy
> elision can take place, to allow the return of immobile values from a
> function.
>

OK, time to be pedantic.

Expanding copy elision cannot make immobile values returnable from
functions.

Copy elision is a rule in the C++ standard which allows a compiler to forgo
making copy/move constructor and destructor calls under certain conditions.
Essentially, where the standard would say that there were two objects, one
which gets copied/moved from and deleted, copy elision allows the compiler
the freedom to only create one object.

But the rules of copy elision, whether guaranteed or not, only work if the
type has those operations which were elided. That's what makes it an
optimization; your code still has to be able to work as if it weren't
happening.

The "Guaranteed copy elision" proposal is lying with its title. It doesn't
guarantee an optimization; it redefines the nature of prvalues so that
there is *nothing to optimize* at all. It redefines prvalues as
initializers rather than objects. This means that there are no copies or
moves to elide. It didn't "expand" elision; it *eliminated* elision.

My idea about return value variables works very much the same way. You are
declaring a variable with a special storage class that *explicitly states*
that it is the return value object. As such, there is never a copy/move to
the return value at all; like "guaranteed copy elision", there is nothing
to be elided.

Your proposal talks about things through the lens of elision: elision
always happens under these conditions. But that means you're still playing
by the rules of elision: the type must have an accessible copy/move
constructor.

That's why my idea declares return value variables. Because the object is
specifically declared to be the return value object, constructed within the
return value object's storage, it permits behavior outside of the rules of
elision. This also has *explicit* consequences for things like stack
unwinding; the RVO does not necessarily get destroyed in reverse
declaration order with automatic objects.

So it's important to recognize the difference between "this optimization is
enforced" and "there is nothing to optimize".

Another thing this "enforced optimization" idea forces on us is that it's
all transparent. In your proposal, adding a couple of lines can change code
that doesn't move a stack variable into code that does.

By contrast, if you have some special syntax to say "this is the return
value object", then you can make it a compile error for the user to do
things which would make it impossible for that to be the return value
object. If I genuinely care to have this "enforced optimization", I don't
want it to silently break due to a seemingly innocuous change. I want the
compiler to complain and stop me.

Because without that, the status quo is fine. After all, it's not like NRVO
is some phantasmal optimization, provided only by the most intelligent and
sophisticated of compilers. It's reality for a lot of code, and it works.

So... what do you gain here? That all the cases where compilers make it
work... continue to work? No; if it's going to be useful, then it needs to
be a formal part of the language that users can explicitly ask for and the
compiler can complain if they do something that breaks it. And which has
clear behavior differences distinct from mere "elision".

--
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/f0add840-6fd9-494f-82c6-17de462b2e0e%40isocpp.org.

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

<div dir=3D"ltr">On Wednesday, May 30, 2018 at 9:27:01 PM UTC-4, Antonio Pe=
rez wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-lef=
t-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padd=
ing-left:1ex">Why would this ever be useful?<br></blockquote><div><br></div=
>S<span style=3D"color:rgb(0,0,0)">uppose that I create a object that store=
s the head of a doubly-linked list. If copy=C2=A0elision doesn&#39;t preser=
ve the address of the value being=C2=A0returned, then suddenly the linked l=
ist is an invalid state.</span></div></blockquote><div><br></div><div>I&#39=
;m not sure I understand. If you have object A, which stores a pointer to &=
quot;the head of a doubly-linked list&quot;, which we will call object B, w=
hat&#39;s the problem? Are you saying that you create an object B on the st=
ack and pass its pointer off to some other object A, which will now rely up=
on it to exist in that location? Even though such an object can <i>easily</=
i> stop existing simply by the user not storing the return value of the fun=
ction?<br></div><div><br></div><div>That sounds like a pointlessly and <i>d=
angerously</i> fragile interface, regardless of whether you could do it or =
not. We don&#39;t want to encourage people to store pointers to stack objec=
ts like this.</div><div><br></div><div>Oh, and here&#39;s a show-stopper fo=
r this idea: the Itanium ABI forbids it.</div><div><br></div><div>If your f=
unction returns an `int`, that `int` will be a register under the Itanium A=
BI. You can take the address of an `int` stack variable, but you can&#39;t =
take the address of a register. So if you take the `int`&#39;s address, the=
 compiler must make the stack variable take up actual stack space. But stac=
k variable cannot truly be the `int` return value object because that objec=
t <i>has no address</i> under the Itanium ABI.<br></div><div><br></div><div=
>Note that this is a problem for my idea too... probably. Mine never direct=
ly states that the address of the return value variable will be the address=
 of whatever the prvalue return is used to initialize. But by calling it &q=
uot;the return value object&quot;, that is the implication.<br></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"><div=
><font color=3D"#000000"><span></span></font></div><div></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1p=
x;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1=
ex">You should look at=C2=A0<a href=3D"https://www.google.com/url?q=3Dhttps=
%3A%2F%2Fgithub.com%2FNicolBolas%2FProposal-Ideas%2Fblob%2Fmaster%2FNamed%2=
520Return%2520Value%2520Variables.md&amp;sa=3DD&amp;sntz=3D1&amp;usg=3DAFQj=
CNFDfTNeTK6LoZJ0o0kIeY4_C4y5tA" rel=3D"nofollow" target=3D"_blank" onmoused=
own=3D"this.href=3D&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithu=
b.com%2FNicolBolas%2FProposal-Ideas%2Fblob%2Fmaster%2FNamed%2520Return%2520=
Value%2520Variables.md\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFDfTNeTK6LoZ=
J0o0kIeY4_C4y5tA&#39;;return true;" onclick=3D"this.href=3D&#39;https://www=
..google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FNicolBolas%2FProposal-Ideas=
%2Fblob%2Fmaster%2FNamed%2520Return%2520Value%2520Variables.md\x26sa\x3dD\x=
26sntz\x3d1\x26usg\x3dAFQjCNFDfTNeTK6LoZJ0o0kIeY4_C4y5tA&#39;;return true;"=
>my draft/idea for return value variables</a>. Same basic idea, except that=
 the requirements are enforced by the compiler directly. Even if the syntax=
 for declaring such a variable is just an attribute, the compiler can at le=
ast let you know when you failed to uphold your part of the agreement.<br><=
/blockquote><div><br></div><div>Thank you for sharing your proposal! I thin=
k that the goal of my proposal aligns with yours: we both want to expand th=
e scope within which copy elision can take place, to allow the return of im=
mobile values from a function.</div></div></blockquote><div><br></div><div>=
OK, time to be pedantic.</div><div><br></div><div>Expanding copy elision ca=
nnot make immobile values returnable from functions.</div><div><br></div><d=
iv>Copy elision is a rule in the C++ standard which allows a compiler to fo=
rgo making copy/move constructor and destructor calls under certain conditi=
ons. Essentially, where the standard would say that there were two objects,=
 one which gets copied/moved from and deleted, copy elision allows the comp=
iler the freedom to only create one object.</div><div><br></div><div>But th=
e rules of copy elision, whether guaranteed or not, only work if the type h=
as those operations which were elided. That&#39;s what makes it an optimiza=
tion; your code still has to be able to work as if it weren&#39;t happening=
..<br></div><div><br></div><div>The &quot;Guaranteed copy elision&quot; prop=
osal is lying with its title. It doesn&#39;t guarantee an optimization; it =
redefines the nature of prvalues so that there is <i>nothing to optimize</i=
> at all. It redefines prvalues as initializers rather than objects. This m=
eans that there are no copies or moves to elide. It didn&#39;t &quot;expand=
&quot; elision; it <i>eliminated</i> elision.</div><div></div><br><div>My i=
dea about return value variables works very much the same way. You are decl=
aring a variable with a special storage class that <i>explicitly states</i>=
 that it is the return value object. As such, there is never a copy/move to=
 the return value at all; like &quot;guaranteed copy elision&quot;, there i=
s nothing to be elided.</div><div><br></div><div>Your proposal talks about =
things through the lens of elision: elision always happens under these cond=
itions. But that means you&#39;re still playing by the rules of elision: th=
e type must have an accessible copy/move constructor.</div><div><br></div><=
div>That&#39;s why my idea declares return value variables. Because the obj=
ect is specifically declared to be the return value object, constructed wit=
hin the return value object&#39;s storage, it permits behavior outside of t=
he rules of elision. This also has <i>explicit</i> consequences for things =
like stack unwinding; the RVO does not necessarily get destroyed in reverse=
 declaration order with automatic objects.</div><div><br></div><div>So it&#=
39;s important to recognize the difference between &quot;this optimization =
is enforced&quot; and &quot;there is nothing to optimize&quot;.<br></div><d=
iv></div><br><div>Another thing this &quot;enforced optimization&quot; idea=
 forces on us is that it&#39;s all transparent. In your proposal, adding a =
couple of lines can change code that doesn&#39;t move a stack variable into=
 code that does.</div><div><br></div><div>By contrast, if you have some spe=
cial syntax to say &quot;this is the return value object&quot;, then you ca=
n make it a compile error for the user to do things which would make it imp=
ossible for that to be the return value object. If I genuinely care to have=
 this &quot;enforced optimization&quot;, I don&#39;t want it to silently br=
eak due to a seemingly innocuous change. I want the compiler to complain an=
d stop me.</div><div><br></div><div>Because without that, the status quo is=
 fine. After all, it&#39;s not like NRVO is some phantasmal optimization, p=
rovided only by the most intelligent and sophisticated of compilers. It&#39=
;s reality for a lot of code, and it works.</div><div><br></div><div>So... =
what do you gain here? That all the cases where compilers make it=20
work... continue to work? No; if it&#39;s going to be useful, then it needs=
=20
to be a formal part of the language that users can explicitly ask for=20
and the compiler can complain if they do something that breaks it. And whic=
h has clear behavior differences distinct from mere &quot;elision&quot;.</d=
iv></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/f0add840-6fd9-494f-82c6-17de462b2e0e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/f0add840-6fd9-494f-82c6-17de462b2e0e=
%40isocpp.org</a>.<br />

------=_Part_1731_1712970117.1527737597006--

------=_Part_1730_1231868501.1527737597005--

.


Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 30 May 2018 21:24:48 -0700
Raw View
On Wednesday, 30 May 2018 18:27:01 PDT Antonio Perez wrote:
> This requirement isn't difficult to implement. Space for the returned
> object is allocated on the stack prior to the function call, and then the
> function instantiates the object it's going to return within the space
> allocated prior to the function call. When the function exits, anything
> added to the stack over the course of the function call is deallocated, and
> everyone's happy. Due to the "as-if" principle, if no one ever takes the
> address of the returned object, then the compiler is free to keep it
> entirely in the CPU's registers.

Which is an interesting and important aspect: what if the object is returned
in registers, not by implicit reference parameter? In this case, the called
function cannot know the address of where the caller would store the object
(even assuming it would store anywhere) because that information isn't
included in the ABI.

In order to achieve this, you need to decorate the function itself.

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



--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/22826106.3Capc8sSYx%40tjmaciei-mobl1.

.


Author: Jens Maurer <Jens.Maurer@gmx.net>
Date: Thu, 31 May 2018 08:46:00 +0200
Raw View
On 05/30/2018 11:49 PM, Antonio Perez wrote:
> *Proposal*
> Copy/move elision for objects returned from a function is mandatory, even=
 if the move or copy constructors of that object have side-effects.=20

This is already the case since P0135 got adopted:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0135r1.html

Jens


>=20
> ||
> FoogetFoo(){
>     // code before foo definition
>     Foofoo(/*other args*/);
>     // code after foo definition
>     returnfoo;//Will result in copy elision
> }
>=20
> Further, the address of the returned object must be identical in the func=
tion returning it and the calling function:
>=20
> ||
> Foo*MY_GLOBAL_FOO_PTR;
> FoogetFoo(){
>     // code before foo definition
>     Foofoo(/*other args*/);
>     // code after foo definition
>     MY_GLOBAL_FOO_PTR =3D&foo;
>     returnfoo;//Will result in copy elision
> }
>=20
> intmain(){
>     Foofoo =3DgetFoo();
>     //&foo =3D=3D MY_GLOBAL_FOO_PTR after call to getFoo
> }
>=20
> *How this could kinda-sorta be achieved now*
> This section is a demonstration that compilers have the capacity to do th=
is. Let's create a class that wraps a single instance of an arbitrary type.
>=20
> ||
> template<classT>
> structElisionObj{
>    T value;
>    ElisionObj():value {}{}
>    ElisionObj(constT&value):value {value } {}
>    ElisionObj(T&&value):value {std::move(value)} {}
>    ElisionObj(constElisionObj&obj)=3Ddefault;
>    ElisionObj(ElisionObj&&obj)=3Ddefault;
>    template<classF,class...Args>
>    ElisionObj(F&&func,Args&&...args):value {std::forward<decltype(args)>(=
args)...}{func(value);}
>    operatorT&(){returnvalue;}
>    operatorconstT&()const{returnvalue;}
> };
>=20
> Internally, returning foo by copy elision is identical to returning Elisi=
onObj<Foo> with the code after Foo's definition given as a closure to the E=
lisionObj<Foo> constructor. =20
>=20
> ||
> Foo*MY_GLOBAL_FOO_PTR;
> ElisionObj<Foo>getFoo2(){
>     // code before foo definition
>     returnElisionObj<Foo>(
>         [&](Foo&foo){
>             // code after foo definition
>         },
>         /*other args*/
>     );//Currently results in copy elision under C++17 standard.
> }
>=20
> *Explanation*
> ElisionObj<T> has (or can be trivially implemented with) the exact same m=
emory layout as T, and therefore the compiler may implement copy elision fo=
r a complete object of type T in the same way that it would for an ElisionO=
bj<T>. The only situation where copy elision can't occur is when returning =
a subobject, and thus *the only requirement for return with copy elision is=
 that the object being returned is a complete object. *
>=20
> (I submitted another proposal for this, although that one imposed a compl=
icated set of restrictions I realized were unnecessary.)
>=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/93a53178-93b0-48ef-92c4-1f9b24130e1c%40isocpp.=
org <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/93a53178-=
93b0-48ef-92c4-1f9b24130e1c%40isocpp.org?utm_medium=3Demail&utm_source=3Dfo=
oter>.

--=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/5B0F9A28.6050406%40gmx.net.

.