220 36082 <1c6eff77-d71f-4dd7-8c13-f609460a03f0@isocpp.org> article
Path: news.gmane.org!.POSTED!not-for-mail
From: Nicol Bolas <jmckesson@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Sub-objects and their copy ellision
Date: Tue, 19 Dec 2017 12:10:15 -0800 (PST)
Lines: 333
Approved: news@gmane.org
Message-ID: <1c6eff77-d71f-4dd7-8c13-f609460a03f0@isocpp.org>
References: <caca241d-3498-b79b-fbf3-e57d8b7c3518@technion.ac.il>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_31022_491329282.1513714215421"
X-Trace: blaine.gmane.org 1513714100 24594 195.159.176.226 (19 Dec 2017 20:08:20 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Tue, 19 Dec 2017 20:08:20 +0000 (UTC)
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBCEKFTV6ZUMBBKHE4XIQKGQEUB3JPOI@isocpp.org Tue Dec 19 21:08:16 2017
Return-path: <std-proposals+bncBCEKFTV6ZUMBBKHE4XIQKGQEUB3JPOI@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-vk0-f71.google.com ([209.85.213.71])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBCEKFTV6ZUMBBKHE4XIQKGQEUB3JPOI@isocpp.org>)
	id 1eROBT-0005zU-Kl
	for gclcip-std-proposals@m.gmane.org; Tue, 19 Dec 2017 21:08:16 +0100
Original-Received: by mail-vk0-f71.google.com with SMTP id b143sf10035954vka.8
        for <gclcip-std-proposals@m.gmane.org>; Tue, 19 Dec 2017 12:10:18 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=date:from:to:message-id:in-reply-to:references:subject:mime-version
         :x-original-sender:reply-to:precedence:mailing-list:list-id
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=L4fpCMehYBkf5Y4ZT6fCVS+zwCLhKUe/4Gub+7dWDOg=;
        b=JeEZz3rX+5r5q503zXqXM8ZcHFmnAUsqZyQlQeAlrZyPoknhpK6Wv6wBLXiii2njK/
         jZ8XDtbOjpu3Lw/kHePc/r6nZM6GUEDY9rdMJzisJo/5dflmD/1G2pqMqApAvzynA15G
         Gmdc/qSf87SimB5ruxR3pDjzljWkfYGDs0tyvd1KcthTIHMClkJ+rbgJ8y0U6QBsjBI0
         LIPwH3kEcOhBeO+38lrYBPiuhVHOVymP6gCymZ1AkYGDsAhE45+nooDaiePQDVpyOnej
         ulUxOkQ1PH9rfidtw6BT8FHnRKT262gdHa+QXC1OlgnRXpZLgAyHQT1zhtbnjG5TYpb3
         GNUQ==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20161025;
        h=date:from:to:message-id:in-reply-to:references:subject:mime-version
         :x-original-sender:reply-to:precedence:mailing-list:list-id
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=L4fpCMehYBkf5Y4ZT6fCVS+zwCLhKUe/4Gub+7dWDOg=;
        b=lLv8r7T1Sp3y0JIbIkEv6oUu5d6hAXnNtjHfNa7gbkS7PApq3/sOAug2Uzw8dqDoV2
         mN+T1l90u1pxFjl7ngj8K/rEGKYJm9uJlKM+GRO3620xiKfw2Ylq+IwAEN4gMKULt0Jp
         OzLslrNuWrxKmoYtEPS61m4M+bpYK3bZiirlojBNK4Xu7cb3LzXnXyNuwo0KcWOCfp9j
         QmCfS+2x3vqJLlPtxh8/Kzw1CeGpMWd/0lA8gIHtkzv1zZBBM3Dv+8QRcm6fC5MuAju/
         RuL5NVaWLcNtXel79B9YJAjqrEmJ3lbl0aCITqsMWyeoUGUOoi5t9nfxfGtL795Le3Ny
         4E/A==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:date:from:to:message-id:in-reply-to:references
         :subject:mime-version:x-original-sender:reply-to:precedence
         :mailing-list:list-id:x-spam-checked-in-group:list-post:list-help
         :list-archive:list-subscribe:list-unsubscribe;
        bh=L4fpCMehYBkf5Y4ZT6fCVS+zwCLhKUe/4Gub+7dWDOg=;
        b=c57NOFBzC2U8izyZQiYnTIld4YiXvaCSIEKdeo8WX8aPQ1AKYN/tfVGrLqW2t4W4Lv
         PQLI+HSUl9Kw8s5gFPC9HgE4hI6UgZoeP5yJJd+2HwIbPTZrGfGGfmHzVqMCEcYNhpcM
         uC6uBrXXe5gp/m4MKyzEdzTWwoSgNEpVN3kyGDxouTk0q//5ERQXaZqqBDY95gdW35rZ
         bb4GqHTGdlaujO7QvN3BmThXGRogh7shjZnCfDwgfik+wvDKwU3v0SEv2VBbZvNC+hzu
         HGDc38C1UupdpI2A7+//qL8SjOdj68TWnU6f1LMGjpQgq+Dc6xfxvfNIENy7ukj5WPwp
         orGA==
X-Gm-Message-State: AKGB3mLpTrNYF0bv+lJ+bbqzjWwapdDhoJAfWhZiTFU1xHauK657hqae
	Dl86RQFm3YnDL6L9k1MDvU1k+Q==
X-Google-Smtp-Source: ACJfBos+VKRu5oAV5ZxEN6CoFmj5DPAlSEy6dmlEajQmWAdLAgc9IGj4BGVTvI/OKPSzi/2RmvkSag==
X-Received: by 10.31.69.5 with SMTP id s5mr1877759vka.37.1513714217747;
        Tue, 19 Dec 2017 12:10:17 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.31.54.140 with SMTP id d134ls2233421vka.15.gmail; Tue, 19 Dec
 2017 12:10:16 -0800 (PST)
X-Received: by 10.31.178.196 with SMTP id b187mr432946vkf.8.1513714216111;
        Tue, 19 Dec 2017 12:10:16 -0800 (PST)
In-Reply-To: <caca241d-3498-b79b-fbf3-e57d8b7c3518@technion.ac.il>
X-Original-Sender: jmckesson@gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Spam-Checked-In-Group: std-proposals@isocpp.org
X-Google-Group-Id: 399137483710
List-Post: <https://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <https://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <https://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:36082
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/36082>

------=_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--

.
