220 31114 <0f4944b0-11a6-4220-9d48-38086babc97a@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: P0577: No lifetime extension for xvalue .
Date: Fri, 24 Feb 2017 10:53:25 -0800 (PST)
Lines: 248
Approved: news@gmane.org
Message-ID: <0f4944b0-11a6-4220-9d48-38086babc97a@isocpp.org>
References: <e1dd36c5-58c4-4f20-870f-d806158b1187@isocpp.org>
 <CAGsORuD=UDBc7MPKcbyH7p4B-EpN8guiw9kOQHHOTmi+=gEqzQ@mail.gmail.com>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_307_21947750.1487962405198"
X-Trace: blaine.gmane.org 1487962405 27556 195.159.176.226 (24 Feb 2017 18:53:25 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Fri, 24 Feb 2017 18:53:25 +0000 (UTC)
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBCEKFTV6ZUMBBJMCYLCQKGQE7AQOA2A@isocpp.org Fri Feb 24 19:53:21 2017
Return-path: <std-proposals+bncBCEKFTV6ZUMBBJMCYLCQKGQE7AQOA2A@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-qt0-f198.google.com ([209.85.216.198])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBCEKFTV6ZUMBBJMCYLCQKGQE7AQOA2A@isocpp.org>)
	id 1chKzY-0006cK-M2
	for gclcip-std-proposals@m.gmane.org; Fri, 24 Feb 2017 19:53:20 +0100
Original-Received: by mail-qt0-f198.google.com with SMTP id b51sf8204474qta.4
        for <gclcip-std-proposals@m.gmane.org>; Fri, 24 Feb 2017 10:53:27 -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
         :x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=YCWMX5jZe2vS9J0UvE07OrNE9eXGR5Xgd6j29Ri1tEA=;
        b=nemIAV6HTcD4yFmSsg3ZBZb/PhQ5h/v9M/jEYiXiwCsTF5Vq6N9HinIAvom8xCgOjS
         fFqOzvuN2BzZTxzJ1eydZDfm28jTuzAi+blMEadrLhKZBcWDEXSNj1udnzlbwanWZ8Uo
         YXrY/FogFY0ZzaSLjxxty0IvTfghLn0ql4+nkl9mXtWM96x3Xnk1Cjl0fmtw6JuRYUB+
         ecaA6hKJPHXsDcQI3AmpyhBkup7q1EiRmITZKyHfm3PL3CjqQY9YVwpw/9BXi0AuvYLF
         BLfZHC1x6ewyiZQM6rM9f/FdQo0GT1da2hcqjyHxHcS4leS2mqesIfemrGGOq5h4yvAL
         6QKA==
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
         :x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=YCWMX5jZe2vS9J0UvE07OrNE9eXGR5Xgd6j29Ri1tEA=;
        b=jl8CS6sX04eSR0XLZQgKVi5S/e5UK3AxHeGmY6ijeIj29FdA7bqIQR+rVWsb71SGF0
         +OiawBozrTfb0Ep/i4+pC1AXYY3PbAMORcMtZnPUfwpXNOfZ830YlMog9PdF+1UGu9GW
         yHWYEx/Ulfj5+jEV5nKYV2eXNQyPmTuk9+VLppKfMqPcLiSKP6zL/d/m/awuRKy+cu07
         PioPLNystPBm+RQyhhQSYq4MNNAmk57mB27ZHHKf17P98xDa4eTN6obJmZjUa7FlRSe7
         eyc1iiCCjjtSb1b5fYGJCVMm9oT1KVCQYW4nxaUkX0pahsS9twpA1OH4MCuuT1e/zDVe
         a8fg==
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=YCWMX5jZe2vS9J0UvE07OrNE9eXGR5Xgd6j29Ri1tEA=;
        b=W7x/CjbkuDEl6Taw9tUOM374VXnC4yFU0taKBPA58jIFZWeSD7XvrikhDQKXbOaPr2
         8ouUGIJcNPlA8kIcIu7QL7uL2sq3qM2RVpsINiTfxdgMWdWP0IzPYtcjZKy4niwM0BKw
         gDScZ2Ky5ItLa2cXnKQegfbYYy6BDpYsgmnDOPq1H46hTd2goQNc97SRpJHi/AVbTFtF
         6z+VXyjYMPKXS/9Uc2Uia+2LxBU+pBN5eb9zheDjJM8DV6KwGn4Eyf9EQZwYCQg1yIzn
         t38MQq7VH8A5OnRSOW3TQqLnY0zp2FP6skCtls/jetepaYXSpaOuaa9/qySDVNhTloTI
         /MSg==
X-Gm-Message-State: AMke39nwdZ1oWh2inoFkbVFW2MOqGrlN7myEGSwgeq0hRFgj3ZQY9EUAVXa75ZVocemOCw==
X-Received: by 10.200.43.17 with SMTP id 17mr1225661qtu.11.1487962406482;
        Fri, 24 Feb 2017 10:53:26 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.157.61.70 with SMTP id a64ls7232298otc.35.gmail; Fri, 24 Feb
 2017 10:53:25 -0800 (PST)
X-Received: by 10.157.89.144 with SMTP id u16mr323375oth.16.1487962405708;
        Fri, 24 Feb 2017 10:53:25 -0800 (PST)
In-Reply-To: <CAGsORuD=UDBc7MPKcbyH7p4B-EpN8guiw9kOQHHOTmi+=gEqzQ@mail.gmail.com>
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-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:31114
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/31114>

------=_Part_307_21947750.1487962405198
Content-Type: multipart/alternative; 
	boundary="----=_Part_308_436960159.1487962405199"

------=_Part_308_436960159.1487962405199
Content-Type: text/plain; charset=UTF-8

On Friday, February 24, 2017 at 12:46:07 PM UTC-5, Zhihao Yuan wrote:
>
> On Fri, Feb 24, 2017 at 8:48 AM, Nicol Bolas <jmck...@gmail.com 
> <javascript:>> wrote: 
> > auto &&r2 = X().n; 
> > 
> > For `r1`, if `f` returns an rvalue reference that refers to its 
> parameter or 
> > a subobject thereof, this will be a dangling reference. 
> > 
> > But `r2` is perfectly fine. The lifetime of the prvalue temporary will 
> be 
> > extended even though we are not actually referencing it directly. 
> > [class.temporary]p6: 
> > 
> > [...] 
> > 
> > The idea of lifetime extension should not be that you provide lifetime 
> > extension for all xvalues. But it also shouldn't be that you provide 
> > lifetime extension for prvalues. It should be that you provide lifetime 
> > extension for any expression for which lifetime extension is currently 
> > valid. It should behave exactly as if you had created a reference 
> variable 
> > with that expression. 
>
> I think we can find some compromise here, that is to extend 
> lifetime for certain xvalues that we can, but not change any 
> xvalue's value category, making it useful to interfaces 
> which do not care about value categories, and still safe in 
> general.  Example: 
>
>   struct X { std::string s; }; 
>   string_view x = __extend_me X().s;  // fine, extending s 
>

I'm not sure why changing the value category would be problematic here. 
Consider `span`; it explicitly deletes rvalue reference constructors (and 
for good-yet-debatable reasons). But there should never be a case where 
`as_span(register <expr>)` would *not* work. Or at least, if `register 
<expr>` works, then `as_span<T>` of that should also work (assuming it's a 
`span`-able type).

I would say that if `register <expr>` is applied to an expression which 
*both* is not an lvalue expression and doesn't extend the lifetime of a 
temporary, then it should be flat-out ill-formed.

And therefore, the resulting expression from a valid instance of `register` 
is *always* an lvalue. Including `X().s`.

The idea needs to be that I can rewrite the expression as though I bound it 
to a reference:

auto &&temp = X().s;
string_span x = temp; //Assuming template deduction guides and so forth.

And the result will be exactly the same.

Now, I do recognize that this could potentially be problematic in template 
cases. But, at the same time, I would say that it is very rare that you 
encounter a function that returns an rvalue reference when you didn't 
*expect* this. When it isn't explicitly part of the function's purpose.

Also, by making it explicitly illegal to use it in such cases, we also make 
it so that users don't screw up like this:

//Given a Type::getFoo() which returns a `T&&` member of that type, when 
given a `this` &&.
Type().getFoo(); //Returns a dangling reference.
register Type().getFoo(); //Still returns a dangling reference, but 
silently compiles.

By making that last statement explicitly il-formed, we can prevent people 
from screwing that up. So while they may be confused why `register 
Type().x` works when `register Type().getX()` fails, at least the compiler 
tells them it won't do what they *think* it does.

Also, I thought of an interesting feature related to span: being able to 
qualify function members such that, if a user uses a temporary with that 
overload, then the temporary will automatically have its lifetime extended 
properly. And if they use something that isn't lifetime extendable (or is 
not an lvalue), then they get an error. This could be applied to `const&` 
parameters just like `&&` ones.

Note that I recognize that this could lead to temporaries that last longer 
than strictly necessary. But I think it's good to have a way for a function 
to enforce its rules and explicitly forbid the use of objects which cannot 
live beyond the lifetime of the function call.

Of course, we'd want to use the same keyword in the parameter list as we do 
in expressions for lifetime extension. Unfortunately, that takes `register` 
off the table. But on the plus side, the standards committee seems willing 
to add keywords for less useful features like control structures for `for`, 
so maybe they'd add one for this too.

-- 
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/0f4944b0-11a6-4220-9d48-38086babc97a%40isocpp.org.

------=_Part_308_436960159.1487962405199
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Friday, February 24, 2017 at 12:46:07 PM UTC-5, Zhihao =
Yuan wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Fri, Feb 24, 201=
7 at 8:48 AM, Nicol Bolas &lt;<a href=3D"javascript:" target=3D"_blank" gdf=
-obfuscated-mailto=3D"XDcpZt4TAgAJ" rel=3D"nofollow" onmousedown=3D"this.hr=
ef=3D&#39;javascript:&#39;;return true;" onclick=3D"this.href=3D&#39;javasc=
ript:&#39;;return true;">jmck...@gmail.com</a>&gt; wrote:
<br>&gt; auto &amp;&amp;r2 =3D X().n;
<br>&gt;
<br>&gt; For `r1`, if `f` returns an rvalue reference that refers to its pa=
rameter or
<br>&gt; a subobject thereof, this will be a dangling reference.
<br>&gt;
<br>&gt; But `r2` is perfectly fine. The lifetime of the prvalue temporary =
will be
<br>&gt; extended even though we are not actually referencing it directly.
<br>&gt; [class.temporary]p6:
<br>&gt;
<br>&gt; [...]
<br>&gt;
<br>&gt; The idea of lifetime extension should not be that you provide life=
time
<br>&gt; extension for all xvalues. But it also shouldn&#39;t be that you p=
rovide
<br>&gt; lifetime extension for prvalues. It should be that you provide lif=
etime
<br>&gt; extension for any expression for which lifetime extension is curre=
ntly
<br>&gt; valid. It should behave exactly as if you had created a reference =
variable
<br>&gt; with that expression.
<br>
<br>I think we can find some compromise here, that is to extend
<br>lifetime for certain xvalues that we can, but not change any
<br>xvalue&#39;s value category, making it useful to interfaces
<br>which do not care about value categories, and still safe in
<br>general. =C2=A0Example:
<br>
<br>=C2=A0 struct X { std::string s; };
<br>=C2=A0 string_view x =3D __extend_me X().s; =C2=A0// fine, extending s
<br></blockquote><div><br>I&#39;m not sure why changing the value category =
would be problematic here. Consider `span`; it explicitly deletes rvalue re=
ference constructors (and for good-yet-debatable reasons). But there should=
 never be a case where `as_span(register &lt;expr&gt;)` would <i>not</i> wo=
rk. Or at least, if `register &lt;expr&gt;` works, then `as_span&lt;T&gt;` =
of that should also work (assuming it&#39;s a `span`-able type).<br><br>I w=
ould say that if `register &lt;expr&gt;` is applied to an expression which =
<b>both</b> is not an lvalue expression and doesn&#39;t extend the lifetime=
 of a temporary, then it should be flat-out ill-formed.<br><br>And therefor=
e, the resulting expression from a valid instance of `register` is <i>alway=
s</i> an lvalue. Including `X().s`.<br><br>The idea needs to be that I can =
rewrite the expression as though I bound it to a reference:<br><br><div sty=
le=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187=
); border-style: solid; border-width: 1px; overflow-wrap: break-word;" clas=
s=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint"=
><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">&amp;&amp;</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">temp </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> X</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">().</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">s</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br>string_span x </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 temp</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #800;" class=3D"styled-by-prettify">//Assuming template ded=
uction guides and so forth.</span></div></code></div><br>And the result wil=
l be exactly the same.<br><br>Now, I do recognize that this could potential=
ly be problematic in template cases. But, at the same time, I would say tha=
t it is very rare that you encounter a function that returns an rvalue refe=
rence when you didn&#39;t <i>expect</i> this. When it isn&#39;t explicitly =
part of the function&#39;s purpose.<br><br>Also, by making it explicitly il=
legal to use it in such cases, we also make it so that users don&#39;t scre=
w up like this:<br><br><div style=3D"background-color: rgb(250, 250, 250); =
border-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; o=
verflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettyprint=
"><div class=3D"subprettyprint"><span style=3D"color: #800;" class=3D"style=
d-by-prettify">//Given a Type::getFoo() which returns a `T&amp;&amp;` membe=
r of that type, when given a `this` &amp;&amp;.</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #606;=
" class=3D"styled-by-prettify">Type</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">().</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">getFoo</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">();</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">//=
Returns a dangling reference.</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-=
by-prettify">register</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify=
">Type</span><span style=3D"color: #660;" class=3D"styled-by-prettify">().<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">getFoo</spa=
n><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">//Still returns a dangling refe=
rence, but silently compiles.</span></div></code></div><br>By making that l=
ast statement explicitly il-formed, we can prevent people from screwing tha=
t up. So while they may be confused why `register Type().x` works when `reg=
ister Type().getX()` fails, at least the compiler tells them it won&#39;t d=
o what they <i>think</i> it does.<br><br>Also, I thought of an interesting =
feature related to span: being able to qualify function members such that, =
if a user uses a temporary with that overload, then the temporary will auto=
matically have its lifetime extended properly. And if they use something th=
at isn&#39;t lifetime extendable (or is not an lvalue), then they get an er=
ror. This could be applied to `const&amp;` parameters just like `&amp;&amp;=
` ones.<br><br>Note that I recognize that this could lead to temporaries th=
at last longer than strictly necessary. But I think it&#39;s good to have a=
 way for a function to enforce its rules and explicitly forbid the use of o=
bjects which cannot live beyond the lifetime of the function call.<br><br>O=
f course, we&#39;d want to use the same keyword in the parameter list as we=
 do in expressions for lifetime extension. Unfortunately, that takes `regis=
ter` off the table. But on the plus side, the standards committee seems wil=
ling to add keywords for less useful features like control structures for `=
for`, so maybe they&#39;d add one for this too.<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/0f4944b0-11a6-4220-9d48-38086babc97a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/0f4944b0-11a6-4220-9d48-38086babc97a=
%40isocpp.org</a>.<br />

------=_Part_308_436960159.1487962405199--

------=_Part_307_21947750.1487962405198--

.
