Topic: Explicit temporary lifetime extension
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 14 Jan 2017 07:20:59 -0800 (PST)
Raw View
------=_Part_774_1699595751.1484407259554
Content-Type: multipart/alternative;
boundary="----=_Part_775_79585535.1484407259555"
------=_Part_775_79585535.1484407259555
Content-Type: text/plain; charset=UTF-8
This is something of a fork of the thread on unnamed variables through
structured binding. Several posts were made about using an explicit
lifetime extension mechanism to do more-or-less the same job.
I wanted to fork that discussion over here because a couple of interesting
points were brought up with regard to lifetime extension. Such points have
nothing to do with unnamed variables, but I felt that they needed to be
discussed:
1: A lifetime extended temporary can no longer be a prvalue. This is due to
guaranteed elision requirements; prvalues aren't necessarily temporaries.
Lifetime extension extends the lifetime of temporaries. So you need to
manifest a temporary when you extend a prvalue's lifetime. And thus the
result is not a prvalue.
2:
On Friday, January 13, 2017 at 1:43:20 PM UTC-5, Zhihao Yuan wrote:
>
> On Fri, Jan 13, 2017 at 10:23 AM, Matthew Woehlke
> <mwoehlk...@gmail.com> wrote:
> >
> > ...in particular, it would be nice for this to finally work:
> >
> > for (auto i : std::add_const(__extend_me make_me_a_list())
>
> `add_const` banned rvalue.
What is the value category of an extended temporary? It *cannot* be a
prvalue, as previously stated. So that leaves 3 options:
1: xvalue
2: lvalue
3: Some new value category. Please no; don't we have enough?
I would say that lifetime extension should be conceptually a conversion
from:
(__extend_me expr1) op expr2
to
auto &&unnamed = expr1
unnamed op expr2
If that is the meaning of lifetime extension, then it is quite clear that
the extended expression is an *lvalue*, not an xvalue. It isn't eXpiring;
it's just an unnamed variable that happens to reside in the middle of an
expression. And variables are lvalues.
Therefore, `as_const(__extend_me expr)` should work just fine. You can move
from an extended expression, but you need to use `std::move` for that
explicitly.
--
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/dac89450-71b1-4bf4-85e0-a217f0e69944%40isocpp.org.
------=_Part_775_79585535.1484407259555
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">This is something of a fork of the thread on unnamed varia=
bles through structured binding. Several posts were made about using an exp=
licit lifetime extension mechanism to do more-or-less the same job.<br><br>=
I wanted to fork that discussion over here because a couple of interesting =
points were brought up with regard to lifetime extension. Such points have =
nothing to do with unnamed variables, but I felt that they needed to be dis=
cussed:<br><br>1: A lifetime extended temporary can no longer be a prvalue.=
This is due to guaranteed elision requirements; prvalues aren't necess=
arily temporaries. Lifetime extension extends the lifetime of temporaries. =
So you need to manifest a temporary when you extend a prvalue's lifetim=
e. And thus the result is not a prvalue.<br><br>2:<br><br>On Friday, Januar=
y 13, 2017 at 1:43:20 PM UTC-5, Zhihao Yuan wrote:<blockquote class=3D"gmai=
l_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;=
padding-left: 1ex;">On Fri, Jan 13, 2017 at 10:23 AM, Matthew Woehlke
<br><<a target=3D"_blank" rel=3D"nofollow">mwoehlk...@gmail.com</a>> =
wrote:
<br>>
<br>> ...in particular, it would be nice for this to finally work:
<br>>
<br>> =C2=A0 for (auto i : std::add_const(__extend_me make_me_a_list())
<br>
<br>`add_const` banned rvalue.</blockquote><br>What is the value category o=
f an extended temporary? It <i>cannot</i> be a prvalue, as previously state=
d. So that leaves 3 options:<br><br>1: xvalue<br><br>2: lvalue<br><br>3: So=
me new value category. Please no; don't we have enough?<br><br>I would =
say that lifetime extension should be conceptually a conversion from:<br><b=
r><div style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187=
, 187, 187); border-style: solid; border-width: 1px; overflow-wrap: break-w=
ord;" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subpr=
ettyprint"><span style=3D"color: #660;" class=3D"styled-by-prettify">(</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">__extend_me exp=
r1</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> op expr2</span><=
/div></code></div><br>to<br><br><div style=3D"background-color: rgb(250, 25=
0, 250); border-color: rgb(187, 187, 187); border-style: solid; border-widt=
h: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"pr=
ettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=
=3D"styled-by-prettify">auto</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-p=
rettify">unnamed </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
expr1<br>unnamed op expr2</span></div></code></div><br>If that is the mean=
ing of lifetime extension, then it is quite clear that the extended express=
ion is an <i>lvalue</i>, not an xvalue. It isn't eXpiring; it's jus=
t an unnamed variable that happens to reside in the middle of an expression=
.. And variables are lvalues.<br><br>Therefore, `as_const(__extend_me expr)`=
should work just fine. You can move from an extended expression, but you n=
eed to use `std::move` for that explicitly.<br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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/dac89450-71b1-4bf4-85e0-a217f0e69944%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/dac89450-71b1-4bf4-85e0-a217f0e69944=
%40isocpp.org</a>.<br />
------=_Part_775_79585535.1484407259555--
------=_Part_774_1699595751.1484407259554--
.
Author: Zhihao Yuan <zy@miator.net>
Date: Sat, 14 Jan 2017 11:12:11 -0600
Raw View
On Sat, Jan 14, 2017 at 9:20 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> 1: A lifetime extended temporary can no longer be a prvalue. This is due to
> guaranteed elision requirements; prvalues aren't necessarily temporaries.
> Lifetime extension extends the lifetime of temporaries. So you need to
> manifest a temporary when you extend a prvalue's lifetime. And thus the
> result is not a prvalue.
>
Yes.
> On Friday, January 13, 2017 at 1:43:20 PM UTC-5, Zhihao Yuan wrote:
>>
>> `add_const` banned rvalue.
>
>
> What is the value category of an extended temporary? It cannot be a prvalue,
> as previously stated. So that leaves 3 options:
>
> 1: xvalue
>
> 2: lvalue
>
lvalue, but let me explain some details...
> I would say that lifetime extension should be conceptually a conversion
> from:
>
> (__extend_me expr1) op expr2
>
> to
>
> auto &&unnamed = expr1
> unnamed op expr2
>
Its semantics is equivalent to
decltype(auto) unnamed = expr1;
unnamed op expr2;
Note that when expr1 is a prvalue, decltype(expr1) = T,
decltype(unnamed) = T, but
decltype(__extend_me expr1) != decltype(unnamed),
because `__extend_me expr1` is an lvalue expression,
so the decltype(__extend_me expr1) = decltype((unnamed))
which is T&.
> Therefore, `as_const(__extend_me expr)` should work just fine. You can move
> from an extended expression, but you need to use `std::move` for that
> explicitly.
You are right. Me and my friends blueprinted __extend_me
(we call it `register`)'s semantics 2 months ago like what I
showed above, but during the discussion around `as_const`
I forgot. Sorry about that.
--
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
___________________________________________________
4BSD -- http://blog.miator.net/
--
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/CAGsORuBD4HT6cuu-z7%3Dmyq6NhrO7vYqsERKT_4gT4TZ_oiwSsg%40mail.gmail.com.
.
Author: "'Scott Dolim' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Sat, 14 Jan 2017 15:02:52 -0800 (PST)
Raw View
------=_Part_3313_1952947547.1484434972365
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
I think it is worth putting a stake in the ground and *defining* the term "=
lifetime extension" as the act of converting a temporary's value category t=
o lvalue. Since temporary variables are introduced by the compiler to hold=
transient intermediate values of a complex expression, those variables are=
xvalues already (materialized from prvalue, by necessity). Normally the t=
ransient value is meant to be immediately consumed by the operator of the t=
erm it appears in. As I recall, lifetime extension was added to C++ in ord=
er to handle cases the operator binds to the address of the temporary inste=
ad, so a dangling reference would result if it actually did expire immediat=
ely. The core idea being to delay the expiration past the point where any =
other part of the overall expression could witness it (which would mean see=
ing the temporary as an xvalue) so, as with the case of named rvalue refere=
nce variables, this therefore categorizes them as lvalue, for the duration =
the expression evaluation (or longer). =20
Basically, exactly what you said with the "auto&& unnamed" example, but fli=
pping the logic so that the definition "lifetime extension =3D temporary is=
now an lvalue" is the axiom which implies the example as an exposition of =
how the mechanism is implemented.
--=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/d34038aa-e4d4-4795-997f-f9eef1b2cf1d%40isocpp.or=
g.
------=_Part_3313_1952947547.1484434972365--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 14 Jan 2017 15:40:22 -0800 (PST)
Raw View
------=_Part_603_929364893.1484437223024
Content-Type: multipart/alternative;
boundary="----=_Part_604_1228958152.1484437223024"
------=_Part_604_1228958152.1484437223024
Content-Type: text/plain; charset=UTF-8
On Saturday, January 14, 2017 at 6:02:52 PM UTC-5, Scott Dolim wrote:
>
> I think it is worth putting a stake in the ground and *defining* the term
> "lifetime extension" as the act of converting a temporary's value category
> to lvalue.
An expression's value category does not determine its lifetime. A function
which returns a `T&` returns an expression who's value category is lvalue.
But that makes no statement about the lifetime of the object being
referenced.
Thus, simply declaring that lifetime extension is equivalent to converting
the expression to an lvalue is not sufficient.
--
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/631ea39b-dd1d-4711-912f-118b707c4341%40isocpp.org.
------=_Part_604_1228958152.1484437223024
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, January 14, 2017 at 6:02:52 PM UTC-5, Scott D=
olim wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">I think it is worth=
putting a stake in the ground and *defining* the term "lifetime exten=
sion" as the act of converting a temporary's value category to lva=
lue.</blockquote><div><br>An expression's value category does not deter=
mine its lifetime. A function which returns a `T&` returns an expressio=
n who's value category is lvalue. But that makes no statement about the=
lifetime of the object being referenced.<br><br>Thus, simply declaring tha=
t lifetime extension is equivalent to converting the expression to an lvalu=
e is not sufficient.</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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/631ea39b-dd1d-4711-912f-118b707c4341%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/631ea39b-dd1d-4711-912f-118b707c4341=
%40isocpp.org</a>.<br />
------=_Part_604_1228958152.1484437223024--
------=_Part_603_929364893.1484437223024--
.
Author: "'Scott Dolim' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Sat, 14 Jan 2017 16:16:08 -0800 (PST)
Raw View
------=_Part_1058_181908738.1484439368799
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Doesn't a subexpression of type T&, even if that is returned from f(), impl=
y that the value will not be destructed during the evaluation of the rest o=
f the expression it is in? Granted, there is the classic bug of returning =
a ref to a local from inside f(), but that was destructed before the functi=
on even yielded the result. That bug aside, C++ will not (of its own accor=
d) sequence an lvalue destruction during an expression the value appears in=
, even after it is consumed in a parent expression(that's what xvalues are =
for). =20
So I'm only referring to lifetime relative to the expression (or block, if =
we're talking about the explicit lifetime extension case). Meaning, an lva=
lue, if valid to begin with (on return from f, say) will continue to be val=
id for the duration of the subsequent evaluation where it is accessible, as=
far as the compiler inserting destructors is concerned. Or said another w=
ay, lvalue lifetimes are naturally scope-delimited. Compared to xvalues, w=
hich are disposable from the moment the containing expression is about to c=
onsume them, this is an extended lifetime. =20
I think I'm looking more at the validity of the T& "value" itself (the addr=
ess where a T lives) than the object therein - granted one could throw in a=
n explicit destructor call in the middle of the expression, but the idea is=
that when a temporary is created by the compiler, it is reserving space to=
hold a value, and we are (I think) talking about the lifetime of this rese=
rvation. An xvalue temporary's reservation is much shorter than an lvalue =
temporary's. Could be this correlation of value category to lifetime is ab=
out storage, not object, lifetime.
--=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/275d7a82-2c48-4139-b9e8-4339f4d49c8a%40isocpp.or=
g.
------=_Part_1058_181908738.1484439368799--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 14 Jan 2017 19:41:14 -0800 (PST)
Raw View
------=_Part_937_69229704.1484451674948
Content-Type: multipart/alternative;
boundary="----=_Part_938_1232631564.1484451674948"
------=_Part_938_1232631564.1484451674948
Content-Type: text/plain; charset=UTF-8
On Saturday, January 14, 2017 at 7:16:09 PM UTC-5, Scott Dolim wrote:
>
> Doesn't a subexpression of type T&, even if that is returned from f(),
> imply that the value will not be destructed during the evaluation of the
> rest of the expression it is in?
No:
auto &str = std::string("f00").replace(1, 2, "Something New");
The return value of `replace` is a reference to the `string` it was called
on. This is an lvalue. And yet, that does *nothing* to extend the lifetime
of the temporary `this` that `replace` was given. `replace` will return
`*this`, and therefore `str` will reference a deleted `string` after this
statement executes.
A reference return value has a lifetime which is effectively
in-determinant. Its lifetime (in code that works) is usually linked to the
lifetime of one of its parameters, but we cannot know which one just from
the function's parameters. You'd have to look at its
implementation/documentation.
Which BTW is about 90% of the reason why we need explicit lifetime
extension to begin with.
Granted, there is the classic bug of returning a ref to a local from inside
> f(), but that was destructed before the function even yielded the result.
> That bug aside, C++ will not (of its own accord) sequence an lvalue
> destruction during an expression the value appears in, even after it is
> consumed in a parent expression(that's what xvalues are for).
>
Unless an expression includes an explicit destructor call or delete, C++
will never invoke a destructor *during* an expression. Whether it's an
lvalue, prvalue, or xvalue, any object created during an expression will
continue to exist until that expression has finished its evaluation. Period.
xvalues are not "consumed in a parent expression" either. `replace` could
easily have returned an rvalue reference to `*this` via `std::move(*this)`.
That's perfectly legal, and its return value would be an xvalue.
And it would change *nothing* about the lifetime of its return value. There
is no correlation between object lifetime and value category.
An xvalue temporary's reservation is much shorter than an lvalue
> temporary's.
>
There's no such thing as an "xvalue temporary" or an "lvalue temporary".
Pre-C++17, temporaries are *always* prvalues. Post-C++17, temporaries only
exist as a result of the use of prvalue expressions. In neither case is a
temporary object *ever* an xvalue or lvalue.
--
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/fca3af02-db94-42c6-967b-87014014ed8c%40isocpp.org.
------=_Part_938_1232631564.1484451674948
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, January 14, 2017 at 7:16:09 PM UTC-5, Scott D=
olim wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Doesn't a subex=
pression of type T&, even if that is returned from f(), imply that the =
value will not be destructed during the evaluation of the rest of the expre=
ssion it is in?</blockquote><div><br>No:<br><br><div style=3D"background-co=
lor: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: so=
lid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><=
code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">&</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">str </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> std</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>::</span><span style=3D"color: #008;" class=3D"styled-by-prettify">string<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an style=3D"color: #080;" class=3D"styled-by-prettify">"f00"</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">).</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">replace</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #066;" class=3D"styled-by-prettify">1</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: #066;" class=3D"style=
d-by-prettify">2</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: #080;" class=3D"styled-by-prettify">"Someth=
ing New"</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">);</span></div></code></div><br>The return value of `replace` is a refer=
ence to the `string` it was called on. This is an lvalue. And yet, that doe=
s <i>nothing</i> to extend the lifetime of the temporary `this` that `repla=
ce` was given. `replace` will return `*this`, and therefore `str` will refe=
rence a deleted `string` after this statement executes.<br><br>A reference =
return value has a lifetime which is effectively in-determinant. Its lifeti=
me (in code that works) is usually linked to the lifetime of one of its par=
ameters, but we cannot know which one just from the function's paramete=
rs. You'd have to look at its implementation/documentation.<br><br>Whic=
h BTW is about 90% of the reason why we need explicit lifetime extension to=
begin with.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin=
: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Gran=
ted, there is the classic bug of returning a ref to a local from inside f()=
, but that was destructed before the function even yielded the result. =C2=
=A0That bug aside, C++ will not (of its own accord) sequence an lvalue dest=
ruction during an expression the value appears in, even after it is consume=
d in a parent expression(that's what xvalues are for).<br></blockquote>=
<div><br>Unless an expression includes an explicit destructor call or delet=
e, C++ will never invoke a destructor <i>during</i> an expression. Whether =
it's an lvalue, prvalue, or xvalue, any object created during an expres=
sion will continue to exist until that expression has finished its evaluati=
on. Period.<br><br>xvalues are not "consumed in a parent expression&qu=
ot; either. `replace` could easily have returned an rvalue reference to `*t=
his` via `std::move(*this)`. That's perfectly legal, and its return val=
ue would be an xvalue.<br><br>And it would change <i>nothing</i> about the =
lifetime of its return value. There is no correlation between object lifeti=
me and value category.<br><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><p>An xvalue temporary's reservation is much shorter than an lval=
ue temporary's.</p></blockquote><div><br>There's no such thing as a=
n "xvalue temporary" or an "lvalue temporary". Pre-C++1=
7, temporaries are <i>always</i> prvalues. Post-C++17, temporaries only exi=
st as a result of the use of prvalue expressions. In neither case is a temp=
orary object <i>ever</i> an xvalue or lvalue.<br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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/fca3af02-db94-42c6-967b-87014014ed8c%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/fca3af02-db94-42c6-967b-87014014ed8c=
%40isocpp.org</a>.<br />
------=_Part_938_1232631564.1484451674948--
------=_Part_937_69229704.1484451674948--
.
Author: "'Scott Dolim' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Sat, 14 Jan 2017 20:06:16 -0800 (PST)
Raw View
------=_Part_243_703960229.1484453176238
Content-Type: multipart/alternative;
boundary="----=_Part_244_118052493.1484453176238"
------=_Part_244_118052493.1484453176238
Content-Type: text/plain; charset=UTF-8
Ah. OK, I now realize that, as the saying goes, I've opened my mouth and
removed all doubt. But I don't think I'd ever have had a chance otherwise
to clear up my obviously muddled understanding of the standard on this
topic, particularly the terminology, without blurting it out. Thanks much
for the clear explanation.
On the point of your original post, your conclusion that the
lifetime-extended temporary ought to be treated like an unnamed variable
which is an lvalue, does seem correct even if my attempted justification
for it was total hogwash...
On Saturday, January 14, 2017 at 7:41:15 PM UTC-8, Nicol Bolas wrote:
>
> On Saturday, January 14, 2017 at 7:16:09 PM UTC-5, Scott Dolim wrote:
>>
>> Doesn't a subexpression of type T&, even if that is returned from f(),
>> imply that the value will not be destructed during the evaluation of the
>> rest of the expression it is in?
>
>
> No:
>
> auto &str = std::string("f00").replace(1, 2, "Something New");
>
> The return value of `replace` is a reference to the `string` it was called
> on. This is an lvalue. And yet, that does *nothing* to extend the
> lifetime of the temporary `this` that `replace` was given. `replace` will
> return `*this`, and therefore `str` will reference a deleted `string` after
> this statement executes.
>
> A reference return value has a lifetime which is effectively
> in-determinant. Its lifetime (in code that works) is usually linked to the
> lifetime of one of its parameters, but we cannot know which one just from
> the function's parameters. You'd have to look at its
> implementation/documentation.
>
> Which BTW is about 90% of the reason why we need explicit lifetime
> extension to begin with.
>
> Granted, there is the classic bug of returning a ref to a local from
>> inside f(), but that was destructed before the function even yielded the
>> result. That bug aside, C++ will not (of its own accord) sequence an
>> lvalue destruction during an expression the value appears in, even after it
>> is consumed in a parent expression(that's what xvalues are for).
>>
>
> Unless an expression includes an explicit destructor call or delete, C++
> will never invoke a destructor *during* an expression. Whether it's an
> lvalue, prvalue, or xvalue, any object created during an expression will
> continue to exist until that expression has finished its evaluation. Period.
>
> xvalues are not "consumed in a parent expression" either. `replace` could
> easily have returned an rvalue reference to `*this` via `std::move(*this)`.
> That's perfectly legal, and its return value would be an xvalue.
>
> And it would change *nothing* about the lifetime of its return value.
> There is no correlation between object lifetime and value category.
>
> An xvalue temporary's reservation is much shorter than an lvalue
>> temporary's.
>>
>
> There's no such thing as an "xvalue temporary" or an "lvalue temporary".
> Pre-C++17, temporaries are *always* prvalues. Post-C++17, temporaries
> only exist as a result of the use of prvalue expressions. In neither case
> is a temporary object *ever* an xvalue or lvalue.
>
--
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/dec5f0bb-ec88-412a-936c-6293713d966b%40isocpp.org.
------=_Part_244_118052493.1484453176238
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Ah. =C2=A0OK, I now realize that, as the saying goes, I=
9;ve opened my mouth and removed all doubt. =C2=A0But I don't think I&#=
39;d ever have had a chance otherwise to clear up my obviously muddled unde=
rstanding of the standard on this topic, particularly the terminology, with=
out blurting it out. =C2=A0Thanks much for the clear explanation. =C2=A0=C2=
=A0<div><br></div><div>On the point of your original post, your conclusion =
that the lifetime-extended temporary ought to be treated like an unnamed va=
riable which is an lvalue, does seem correct even if my attempted justifica=
tion for it was total hogwash... =C2=A0</div><div><br></div><div><br>On Sat=
urday, January 14, 2017 at 7:41:15 PM UTC-8, Nicol Bolas wrote:<blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On Saturday, January 14, =
2017 at 7:16:09 PM UTC-5, Scott Dolim wrote:<blockquote class=3D"gmail_quot=
e" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-l=
eft:1ex">Doesn't a subexpression of type T&, even if that is return=
ed from f(), imply that the value will not be destructed during the evaluat=
ion of the rest of the expression it is in?</blockquote><div><br>No:<br><br=
><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,1=
87);border-style:solid;border-width:1px"><code><div><span style=3D"color:#0=
08">auto</span><span style=3D"color:#000"> </span><span style=3D"color:#660=
">&</span><span style=3D"color:#000">str </span><span style=3D"color:#6=
60">=3D</span><span style=3D"color:#000"> std</span><span style=3D"color:#6=
60">::</span><span style=3D"color:#008">string</span><span style=3D"color:#=
660">(</span><span style=3D"color:#080">"f00"</span><span style=
=3D"color:#660">).</span><span style=3D"color:#000">replace</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#066">1</span><span style=3D=
"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#066">2</span><span style=3D"color:#660">,</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#080">"Something New"</span><span=
style=3D"color:#660">);</span></div></code></div><br>The return value of `=
replace` is a reference to the `string` it was called on. This is an lvalue=
.. And yet, that does <i>nothing</i> to extend the lifetime of the temporary=
`this` that `replace` was given. `replace` will return `*this`, and theref=
ore `str` will reference a deleted `string` after this statement executes.<=
br><br>A reference return value has a lifetime which is effectively in-dete=
rminant. Its lifetime (in code that works) is usually linked to the lifetim=
e of one of its parameters, but we cannot know which one just from the func=
tion's parameters. You'd have to look at its implementation/documen=
tation.<br><br>Which BTW is about 90% of the reason why we need explicit li=
fetime extension to begin with.<br><br></div><blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex">Granted, there is the classic bug of returning a ref to a local f=
rom inside f(), but that was destructed before the function even yielded th=
e result. =C2=A0That bug aside, C++ will not (of its own accord) sequence a=
n lvalue destruction during an expression the value appears in, even after =
it is consumed in a parent expression(that's what xvalues are for).<br>=
</blockquote><div><br>Unless an expression includes an explicit destructor =
call or delete, C++ will never invoke a destructor <i>during</i> an express=
ion. Whether it's an lvalue, prvalue, or xvalue, any object created dur=
ing an expression will continue to exist until that expression has finished=
its evaluation. Period.<br><br>xvalues are not "consumed in a parent =
expression" either. `replace` could easily have returned an rvalue ref=
erence to `*this` via `std::move(*this)`. That's perfectly legal, and i=
ts return value would be an xvalue.<br><br>And it would change <i>nothing</=
i> about the lifetime of its return value. There is no correlation between =
object lifetime and value category.<br><br></div><blockquote class=3D"gmail=
_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><p>An xvalue temporary's reservation is much shorter than=
an lvalue temporary's.</p></blockquote><div><br>There's no such th=
ing as an "xvalue temporary" or an "lvalue temporary". =
Pre-C++17, temporaries are <i>always</i> prvalues. Post-C++17, temporaries =
only exist as a result of the use of prvalue expressions. In neither case i=
s a temporary object <i>ever</i> an xvalue or lvalue.<br></div></div></bloc=
kquote></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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/dec5f0bb-ec88-412a-936c-6293713d966b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/dec5f0bb-ec88-412a-936c-6293713d966b=
%40isocpp.org</a>.<br />
------=_Part_244_118052493.1484453176238--
------=_Part_243_703960229.1484453176238--
.
Author: Jens Maurer <Jens.Maurer@gmx.net>
Date: Sun, 15 Jan 2017 10:45:56 +0100
Raw View
On 01/15/2017 12:02 AM, 'Scott Dolim' via ISO C++ Standard - Future Proposa=
ls wrote:
> I think it is worth putting a stake in the ground and *defining* the term=
"lifetime extension" as the act of converting a temporary's value category=
to lvalue. Since temporary variables are introduced by the compiler to ho=
ld transient intermediate values of a complex expression, those variables a=
re xvalues already (materialized from prvalue, by necessity). Normally the=
transient value is meant to be immediately consumed by the operator of the=
term it appears in. As I recall, lifetime extension was added to C++ in o=
rder to handle cases the operator binds to the address of the temporary ins=
tead, so a dangling reference would result if it actually did expire immedi=
ately. The core idea being to delay the expiration past the point where an=
y other part of the overall expression could witness it (which would mean s=
eeing the temporary as an xvalue) so, as with the case of named rvalue refe=
rence variables, this therefore categorizes them as lvalue, for the duratio=
n the expressio
n evaluation (or longer). =20
12.2p4 says that temporary objects are usually destructed at the
end of the full-expression, not "immediately".
"Temporary objects are destroyed as the last step in evaluating the full-
expression (1.9) that (lexically) contains the point where they were create=
d."
Jens
--=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/587B44D4.20602%40gmx.net.
.
Author: "'Scott Dolim' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Sun, 15 Jan 2017 10:36:16 -0800 (PST)
Raw View
------=_Part_3983_2009714850.1484505377080
Content-Type: text/plain; charset=UTF-8
Thanks Jens. I definitely had a misunderstanding of how temporary lifetimes are handled, thinking it was related somehow to the value category of the expression that the temporary was introduced for. Nicol cleared it up with some nice examples.
--
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/89684f60-b105-40c8-910d-6a5e242bce11%40isocpp.org.
------=_Part_3983_2009714850.1484505377080--
.