Topic: parameters passed by "expression":
Author: Nicolas Lesser <blitzrakete@gmail.com>
Date: Mon, 14 May 2018 16:01:57 +0200
Raw View
--000000000000928ca9056c2aee60
Content-Type: text/plain; charset="UTF-8"
On Mon, May 14, 2018, 3:41 PM Nicol Bolas <jmckesson@gmail.com> wrote:
> On Monday, May 14, 2018 at 9:16:07 AM UTC-4, floria...@gmail.com wrote:
>>
>> Hello everyone,
>>
>> I would want to propose a new way to pass parameters to functions.
>> Currently, we have 2 way to pass parameters: by value, and by reference.
>> (Passing by pointer is really passing by value the address)
>>
>> However, none of those allow delayed evaluation of parameters.
>>
>
> P0927 covers this general idea. <http://wg21.link/P0927> I'm not sure if
> it was discussed at Jacksonville.
>
It wasn't, there wasn't enough time. It will probably be discussed in
Raspperwil.
>
--
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/CALmDwq3M8eo%3Dehr%3D7P5688neP8Db2Gc5RwaAoSaEXR%2B6U%2B_HxA%40mail.gmail.com.
--000000000000928ca9056c2aee60
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"auto"><div><div class=3D"gmail_quote"><div dir=3D"ltr">On Mon, =
May 14, 2018, 3:41 PM Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.com=
">jmckesson@gmail.com</a>> wrote:<br></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr">On Monday, May 14, 2018 at 9:16:07 AM UTC-4, <a href=3D"=
mailto:floria...@gmail.com" target=3D"_blank" rel=3D"noreferrer">floria...@=
gmail.com</a> wrote:<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=
">Hello everyone,<br><br>I would want to propose a new way to pass paramete=
rs to functions.<br>Currently, we have 2 way to pass parameters: by value, =
and by reference.<br>(Passing by pointer is really passing by value the add=
ress)<br><br>However, none of those allow delayed evaluation of parameters.=
<br></div></blockquote><div><br><a href=3D"http://wg21.link/P0927" target=
=3D"_blank" rel=3D"noreferrer">P0927 covers this general idea.</a> I'm =
not sure if it was discussed at Jacksonville.</div></div></blockquote></div=
></div><div dir=3D"auto"><br></div><div dir=3D"auto">It wasn't, there w=
asn't enough time. It will probably be discussed in Raspperwil.</div><d=
iv dir=3D"auto"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote=
" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote></div></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/CALmDwq3M8eo%3Dehr%3D7P5688neP8Db2Gc5=
RwaAoSaEXR%2B6U%2B_HxA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoo=
ter">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CALmDwq3M=
8eo%3Dehr%3D7P5688neP8Db2Gc5RwaAoSaEXR%2B6U%2B_HxA%40mail.gmail.com</a>.<br=
/>
--000000000000928ca9056c2aee60--
.
Author: Dilip Ranganathan <misc.usage@gmail.com>
Date: Mon, 14 May 2018 10:07:34 -0400
Raw View
--000000000000e7a1aa056c2b01e3
Content-Type: text/plain; charset="UTF-8"
On Mon, May 14, 2018 at 9:41 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Monday, May 14, 2018 at 9:16:07 AM UTC-4, floria...@gmail.com wrote:
>>
>> Hello everyone,
>>
>> I would want to propose a new way to pass parameters to functions.
>> Currently, we have 2 way to pass parameters: by value, and by reference.
>> (Passing by pointer is really passing by value the address)
>>
>> However, none of those allow delayed evaluation of parameters.
>>
>
> P0927 covers this general idea. <http://wg21.link/P0927> I'm not sure if
> it was discussed at Jacksonville.
>
It was also discussed at length in this forum a while ago:
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/DnxRfo_uQl8/anZ8bFXi4QwJ
--
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/CALEPxfu0YpdOWbqcWjsvUU52Jh6kmM-G4Qf_fOimNJ%3DZGydSpQ%40mail.gmail.com.
--000000000000e7a1aa056c2b01e3
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">=
On Mon, May 14, 2018 at 9:41 AM, Nicol Bolas <span dir=3D"ltr"><<a href=
=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>&g=
t;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0=
px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div =
dir=3D"ltr"><span class=3D"gmail-">On Monday, May 14, 2018 at 9:16:07 AM UT=
C-4, <a href=3D"mailto:floria...@gmail.com" target=3D"_blank">floria...@gma=
il.com</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px =
0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=
=3D"ltr">Hello everyone,<br><br>I would want to propose a new way to pass p=
arameters to functions.<br>Currently, we have 2 way to pass parameters: by =
value, and by reference.<br>(Passing by pointer is really passing by value =
the address)<br><br>However, none of those allow delayed evaluation of para=
meters.<br></div></blockquote></span><div><br><a href=3D"http://wg21.link/P=
0927" target=3D"_blank">P0927 covers this general idea.</a> I'm not sur=
e if it was discussed at Jacksonville.</div></div></blockquote><div><br></d=
iv><div>It was also discussed at length in this forum a while ago:<br><a hr=
ef=3D"https://groups.google.com/a/isocpp.org/d/msg/std-proposals/DnxRfo_uQl=
8/anZ8bFXi4QwJ">https://groups.google.com/a/isocpp.org/d/msg/std-proposals/=
DnxRfo_uQl8/anZ8bFXi4QwJ</a><br></div></div></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/CALEPxfu0YpdOWbqcWjsvUU52Jh6kmM-G4Qf_=
fOimNJ%3DZGydSpQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CALEPxfu0YpdOWb=
qcWjsvUU52Jh6kmM-G4Qf_fOimNJ%3DZGydSpQ%40mail.gmail.com</a>.<br />
--000000000000e7a1aa056c2b01e3--
.
Author: florian.csdt@gmail.com
Date: Mon, 14 May 2018 07:49:18 -0700 (PDT)
Raw View
------=_Part_13181_1440263712.1526309358687
Content-Type: multipart/alternative;
boundary="----=_Part_13182_1433036159.1526309358688"
------=_Part_13182_1433036159.1526309358688
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le lundi 14 mai 2018 16:07:36 UTC+2, Dilip R a =C3=A9crit :
>
>
> On Mon, May 14, 2018 at 9:41 AM, Nicol Bolas <jmck...@gmail.com=20
> <javascript:>> wrote:
>
>> On Monday, May 14, 2018 at 9:16:07 AM UTC-4, floria...@gmail.com wrote:
>>>
>>> Hello everyone,
>>>
>>> I would want to propose a new way to pass parameters to functions.
>>> Currently, we have 2 way to pass parameters: by value, and by reference=
..
>>> (Passing by pointer is really passing by value the address)
>>>
>>> However, none of those allow delayed evaluation of parameters.
>>>
>>
>> P0927 covers this general idea. <http://wg21.link/P0927> I'm not sure if=
=20
>> it was discussed at Jacksonville.
>>
>
> It was also discussed at length in this forum a while ago:
>
> https://groups.google.com/a/isocpp.org/d/msg/std-proposals/DnxRfo_uQl8/an=
Z8bFXi4QwJ
>
Thank you for the links.
The proposal is exactly what I had in mind (except for the slightly=20
different syntax).
I'm glad to see a well written proposal.
The previous discussion is also interesting.
--=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/7fb13c92-2d15-44a0-8aa1-848539f8658d%40isocpp.or=
g.
------=_Part_13182_1433036159.1526309358688
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>Le lundi 14 mai 2018 16:07:36 UTC+2, Dilip R a =C3=A9c=
rit=C2=A0:<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"><di=
v><br><div class=3D"gmail_quote">On Mon, May 14, 2018 at 9:41 AM, Nicol Bol=
as <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfu=
scated-mailto=3D"9lsG3v-nCAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D=
'javascript:';return true;" onclick=3D"this.href=3D'javascript:=
';return true;">jmck...@gmail.com</a>></span> wrote:<br><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px sol=
id rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><span>On Monday, May=
14, 2018 at 9:16:07 AM UTC-4, <a>floria...@gmail.com</a> wrote:<blockquote=
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px so=
lid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr">Hello everyone,<br>=
<br>I would want to propose a new way to pass parameters to functions.<br>C=
urrently, we have 2 way to pass parameters: by value, and by reference.<br>=
(Passing by pointer is really passing by value the address)<br><br>However,=
none of those allow delayed evaluation of parameters.<br></div></blockquot=
e></span><div><br><a href=3D"http://wg21.link/P0927" target=3D"_blank" rel=
=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.com/url?q\x=
3dhttp%3A%2F%2Fwg21.link%2FP0927\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFt=
Gq853ZpeahOSmCdpp95qxeiG6g';return true;" onclick=3D"this.href=3D'h=
ttp://www.google.com/url?q\x3dhttp%3A%2F%2Fwg21.link%2FP0927\x26sa\x3dD\x26=
sntz\x3d1\x26usg\x3dAFQjCNFtGq853ZpeahOSmCdpp95qxeiG6g';return true;">P=
0927 covers this general idea.</a> I'm not sure if it was discussed at =
Jacksonville.</div></div></blockquote><div><br></div><div>It was also discu=
ssed at length in this forum a while ago:<br><a href=3D"https://groups.goog=
le.com/a/isocpp.org/d/msg/std-proposals/DnxRfo_uQl8/anZ8bFXi4QwJ" target=3D=
"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'https://groups.go=
ogle.com/a/isocpp.org/d/msg/std-proposals/DnxRfo_uQl8/anZ8bFXi4QwJ';ret=
urn true;" onclick=3D"this.href=3D'https://groups.google.com/a/isocpp.o=
rg/d/msg/std-proposals/DnxRfo_uQl8/anZ8bFXi4QwJ';return true;">https://=
groups.google.com/a/<wbr>isocpp.org/d/msg/std-<wbr>proposals/DnxRfo_uQl8/<w=
br>anZ8bFXi4QwJ</a></div></div></div></div></blockquote><div><br></div><div=
>Thank you for the links.</div><div>The proposal is exactly what I had in m=
ind (except for the slightly different syntax).</div><div>I'm glad to s=
ee a well written proposal.</div><div><br></div><div>The previous discussio=
n is also interesting.<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/7fb13c92-2d15-44a0-8aa1-848539f8658d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/7fb13c92-2d15-44a0-8aa1-848539f8658d=
%40isocpp.org</a>.<br />
------=_Part_13182_1433036159.1526309358688--
------=_Part_13181_1440263712.1526309358687--
.
Author: Corentin <corentin.jabot@gmail.com>
Date: Mon, 14 May 2018 17:49:22 +0200
Raw View
--000000000000a4ed58056c2c6e03
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
While it is a more involved work ( as it depends on reflection and code
injection - aka the underlying mechanisms of the meta class proposal), I do
think that use-site parameter evaluation can be achieved more generally by
having a combination of generalized reflection on arbitrary expression and
named code fragments - neither of these things having been proposed yet.
They would however be implementable reasonably easily on top of the code
injection facilities the metaclasses proposal calls for, as we are
basically just shuffling and copying AST nodes around.
I did not write a paper, because I'm trying to see if I can apply the
design to more macro usages - which is a pain because macro are worse than
token soup - but I hope to present that work someday depending on how the
reflection and code injections papers evolve.I do however have a blog post
about it
https://cor3ntin.github.io/posts/undef_preprocessor/#6-to-get-rid-of-macros=
-we-need-a-new-kind-of-macros
It might also be interesting to see how languages such as rust solve these
kind of problems. (Rust uses a full blown token tree for their macros - do
not mind the word "macro", it's a loaded word in the C++ world but there
are all kind of macros in other languages that do not involve a
preprocessor).
Note that this approach would be different than lazy evaluation in that it
would be a compile time mechanism whereas your solution has a runtime cost.
Both approaches have advantages and draw backs(compile time code expansion
leads to bigger binaries, but you don't pay for an extra call at runtime
(which might be inline in lot of cases)) , so both approach are certainly
worth exploring.
However, it might be interesting that a lambda-based solution be applied
to more than this particular issue.
This paper for a short-lambda syntax ( that unfortunately failed to meet
its audience if i remember correctly) might be a good place to
start wg21.link/p0573
Le lun. 14 mai 2018 =C3=A0 16:49, <florian.csdt@gmail.com> a =C3=A9crit :
>
> Le lundi 14 mai 2018 16:07:36 UTC+2, Dilip R a =C3=A9crit :
>
>>
>> On Mon, May 14, 2018 at 9:41 AM, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>> On Monday, May 14, 2018 at 9:16:07 AM UTC-4, floria...@gmail.com wrote:
>>>>
>>>> Hello everyone,
>>>>
>>>> I would want to propose a new way to pass parameters to functions.
>>>> Currently, we have 2 way to pass parameters: by value, and by referenc=
e.
>>>> (Passing by pointer is really passing by value the address)
>>>>
>>>> However, none of those allow delayed evaluation of parameters.
>>>>
>>>
>>> P0927 covers this general idea. <http://wg21.link/P0927> I'm not sure
>>> if it was discussed at Jacksonville.
>>>
>>
>> It was also discussed at length in this forum a while ago:
>>
>> https://groups.google.com/a/isocpp.org/d/msg/std-proposals/DnxRfo_uQl8/a=
nZ8bFXi4QwJ
>>
>
> Thank you for the links.
> The proposal is exactly what I had in mind (except for the slightly
> different syntax).
> I'm glad to see a well written proposal.
>
> The previous discussion is also interesting.
>
> --
> 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/7fb13c92-2d1=
5-44a0-8aa1-848539f8658d%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/7fb13c92-2d=
15-44a0-8aa1-848539f8658d%40isocpp.org?utm_medium=3Demail&utm_source=3Dfoot=
er>
> .
>
--=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/CA%2BOm%2BSjKNEJk3cs6N%2BmOnnbddJD2gYRKWZXJz3a28=
3QOAy-zgA%40mail.gmail.com.
--000000000000a4ed58056c2c6e03
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">While it is a more involved work ( as it depends on reflec=
tion and code injection - aka the underlying mechanisms of the meta class p=
roposal), I do think that use-site parameter evaluation can be achieved mor=
e generally by having a combination of generalized reflection on arbitrary =
expression and named code fragments - neither of these things having been p=
roposed yet.<div>They would however be implementable reasonably easily on t=
op of the code injection facilities the metaclasses proposal calls for,=C2=
=A0 as we are basically just shuffling and copying AST nodes around.<br><di=
v><br></div><div>I did not write a paper, because I'm trying to see if =
I can apply the design to more macro usages - which is a pain because macro=
are worse than token soup - but I hope to present that work someday depend=
ing on how the reflection and code injections papers evolve.I do however ha=
ve a blog post about it=C2=A0<a href=3D"https://cor3ntin.github.io/posts/un=
def_preprocessor/#6-to-get-rid-of-macros-we-need-a-new-kind-of-macros">http=
s://cor3ntin.github.io/posts/undef_preprocessor/#6-to-get-rid-of-macros-we-=
need-a-new-kind-of-macros</a></div><div><br></div><div>It might also be int=
eresting to see how languages such as rust solve these kind of problems. (R=
ust uses a full blown token tree for their macros - do not mind the word &q=
uot;macro", it's a loaded word in the C++ world but there are all =
kind of macros in other languages that do not involve a preprocessor).</div=
><div><br></div><div>Note that this approach would be different than lazy e=
valuation in that it would be a compile time mechanism whereas your solutio=
n has a runtime cost. Both approaches have advantages and draw backs(compil=
e time code expansion leads to bigger binaries, but you don't pay for a=
n extra call at runtime (which might be inline in lot of cases)) , so both =
approach are certainly worth exploring.</div><div><br></div><div>However,=
=C2=A0 it might be interesting that a lambda-based solution be applied to m=
ore than this particular issue.<br></div><div>This paper for a short-lambda=
syntax ( that unfortunately failed to meet its audience if i remember corr=
ectly) might be a good place to start=C2=A0wg21.link/p0573</div><div><br></=
div><div><br></div><div><br><div><br></div><div><br></div></div></div></div=
><br><div class=3D"gmail_quote"><div dir=3D"ltr">Le=C2=A0lun. 14 mai 2018 =
=C3=A0=C2=A016:49, <<a href=3D"mailto:florian.csdt@gmail.com">florian.cs=
dt@gmail.com</a>> a =C3=A9crit=C2=A0:<br></div><blockquote class=3D"gmai=
l_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left=
:1ex"><div dir=3D"ltr"><br>Le lundi 14 mai 2018 16:07:36 UTC+2, Dilip R a =
=C3=A9crit=C2=A0:</div><div dir=3D"ltr"><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:=
1ex"><div dir=3D"ltr"><div><br><div class=3D"gmail_quote">On Mon, May 14, 2=
018 at 9:41 AM, Nicol Bolas <span dir=3D"ltr"><<a rel=3D"nofollow">jmck.=
...@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);paddi=
ng-left:1ex"><div dir=3D"ltr"><span>On Monday, May 14, 2018 at 9:16:07 AM U=
TC-4, <a>floria...@gmail.com</a> wrote:<blockquote class=3D"gmail_quote" st=
yle=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padd=
ing-left:1ex"><div dir=3D"ltr">Hello everyone,<br><br>I would want to propo=
se a new way to pass parameters to functions.<br>Currently, we have 2 way t=
o pass parameters: by value, and by reference.<br>(Passing by pointer is re=
ally passing by value the address)<br><br>However, none of those allow dela=
yed evaluation of parameters.<br></div></blockquote></span><div><br><a href=
=3D"http://wg21.link/P0927" rel=3D"nofollow" target=3D"_blank">P0927 covers=
this general idea.</a> I'm not sure if it was discussed at Jacksonvill=
e.</div></div></blockquote><div><br></div><div>It was also discussed at len=
gth in this forum a while ago:<br><a href=3D"https://groups.google.com/a/is=
ocpp.org/d/msg/std-proposals/DnxRfo_uQl8/anZ8bFXi4QwJ" rel=3D"nofollow" tar=
get=3D"_blank">https://groups.google.com/a/isocpp.org/d/msg/std-proposals/D=
nxRfo_uQl8/anZ8bFXi4QwJ</a></div></div></div></div></blockquote><div><br></=
div></div><div dir=3D"ltr"><div>Thank you for the links.</div><div>The prop=
osal is exactly what I had in mind (except for the slightly different synta=
x).</div><div>I'm glad to see a well written proposal.</div><div><br></=
div><div>The previous discussion is also interesting.<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" target=3D"_=
blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">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/7fb13c92-2d15-44a0-8aa1-848539f8658d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank">=
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/7fb13c92-2d15-=
44a0-8aa1-848539f8658d%40isocpp.org</a>.<br>
</blockquote></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/CA%2BOm%2BSjKNEJk3cs6N%2BmOnnbddJD2gY=
RKWZXJz3a283QOAy-zgA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BOm%2BS=
jKNEJk3cs6N%2BmOnnbddJD2gYRKWZXJz3a283QOAy-zgA%40mail.gmail.com</a>.<br />
--000000000000a4ed58056c2c6e03--
.
Author: florian.csdt@gmail.com
Date: Thu, 17 May 2018 01:12:31 -0700 (PDT)
Raw View
------=_Part_3607_851821404.1526544751391
Content-Type: multipart/alternative;
boundary="----=_Part_3608_1513155920.1526544751391"
------=_Part_3608_1513155920.1526544751391
Content-Type: text/plain; charset="UTF-8"
After reading the P0927 proposal, it seems that this mechanism + RVO would
supersede the piecewise_construct for tuples (and maps):
The construction of the elements will be delayed until the actual
destination address is known and where RVO will be applied.
Am I correct with this interpretation?
--
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/5927ec22-94ad-4d03-a955-b87edd762a0e%40isocpp.org.
------=_Part_3608_1513155920.1526544751391
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">After reading the P0927 proposal, it seems that this mecha=
nism + RVO would supersede the piecewise_construct for tuples (and maps):<b=
r>The construction of the elements will be delayed until the actual destina=
tion address is known and where RVO will be applied.<br><br>Am I correct wi=
th this interpretation?<br><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/5927ec22-94ad-4d03-a955-b87edd762a0e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5927ec22-94ad-4d03-a955-b87edd762a0e=
%40isocpp.org</a>.<br />
------=_Part_3608_1513155920.1526544751391--
------=_Part_3607_851821404.1526544751391--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 29 May 2018 15:44:31 +0100
Raw View
--000000000000b136ea056d59452d
Content-Type: text/plain; charset="UTF-8"
On Tue, May 29, 2018 at 3:36 PM, <mihailnajdenov@gmail.com> wrote:
>
>
> On Tuesday, May 29, 2018 at 5:09:43 PM UTC+3, Edward Catmur wrote:
>>
>>
>>
>> On Sunday, 27 May 2018 17:19:31 UTC+1, Florian Lemaitre wrote:
>>>
>>> Lazy arguments are compatible with terse lambda. Having one will not
>>> remove the need for the other.
>>>
>>> You seem to miss one crucial point with this proposal (P0927): it will
>>> not create anonymous classes at all: it will always use a function pointer
>>> like this: T (*)(void*)
>>>
>>> If I give an example with the proposal syntax, this will be:
>>> int foo([] -> int i) {
>>> return i();
>>> }
>>>
>>> int bar(int j) {
>>> return foo(j+2);
>>> }
>>> int foobar(int j) {
>>> return foo(2*j);
>>> }
>>>
>>> With lambdas, you will have two instantiation of foo, but in this
>>> proposal, you will have a single symbol for foo, which would be equivalent
>>> to int foo(int (*)(void*), void*).
>>>
>>> So the previous example will be strictly equivalent to:
>>> int foo(int (*i)(void*), void* stack_p) {
>>> return i(stack_p);
>>> }
>>>
>>> int bar(int j) {
>>> int closure(void* stack_p) {
>>> int j = *static_cast<int*>(stack_p + /* offset j */);
>>> return j+2;
>>> }
>>> return foo(&closure, __builtin_frame_address(0));
>>> }
>>>
>>> int foobar(int j) {
>>> int closure(void* stack_p) {
>>> int j = *static_cast<int*>(stack_p + /* offset j */);
>>> return 2*j;
>>> }
>>> return foo(&closure, __builtin_frame_address(0));
>>> }
>>>
>>> This will not lead to code bloat, nor create any anonymous types.
>>> It will create anonymous functions, sure, but with a known and fixed
>>> type. And those functions will be created anyway if you want any form of
>>> lazyness delayed evaluation. Even if the call site is aware that it is
>>> creating those functions.
>>>
>>> As you can see, it is even mush simpler and lighter than creating a
>>> std::function std::function_ref. There is no extra burden on the compiler
>>> to optimize this: it is just inlining a function pointer when this pointer
>>> is known: no heap allocation!
>>>
>>
>> This seems inefficient; if I have n lazy parameters, the address of the
>> enclosing frame is passed n times when it needs to be passed at most once
>> and (for most ABIs) it does not need to be passed at all, since the called
>> function can just save the stack pointer on entry. Would it not be better
>> to just pass a bare code pointer?
>>
>> I suppose this would complicate taking the address of such lazy types,
>> but perhaps it would be better if this operation were also forbidden? We
>> don't allow taking the address of a reference per se, after all. If one
>> needs to pass a lazy argument around, one can pass it as another lazy
>> argument, or capture it into a closure type:
>>
>> int bar([] -> int i) { return i(); }
>> int baz(std::function_ref<int()> f) { return f(); }
>> int foo([] -> int i) {
>> return bar(i()) + baz([&] { return i(); };
>> }
>>
>> Indeed (and perhaps controversially), if the parentheses-suffixed form is
>> the only way to use the identifier of the parameter, then the parentheses
>> are redundant and can (should) be omitted, such that any use of the
>> identifier (in evaluated context) represents an evaluation of the argument
>> expression (and thus a call through the code pointer):
>>
>> int bar([] -> int i) { return i; }
>> int baz(std::function_ref<int()> f) { return f(); }
>> int foo([] -> int i) {
>> return bar(i) + baz([&] { return i; };
>> }
>>
>> The address-of operation would return the address of the result of the
>> argument expression, if the lazy parameter has a reference type, and would
>> otherwise be ill-formed (since a [] -> T lazy parameter would be a prvalue):
>>
>> int* foo([] -> int& i) { return &i; } // OK
>> int* bar([] -> int i) { return &i; } // ill-formed, taking address of a
>> prvalue
>>
>> Again, this would be similar to references, where any use of an
>> identifier of reference type in evaluated context represents a load or
>> store to the bound object and the address-of operation gives the address of
>> the bound object rather than the reference itself.
>>
>> This would certainly make translation from existing code simple, but
>> maybe it is a step too far?
>>
>
> Question: Why would you ever want to use [] -> int instead of std::function_ref<int()>
> as a parameter?
>
[] -> int is transparent at the call site; std::function_ref<int()>
requires the calling code to write a lambda. It is also lighter weight.
--
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/CAJnLdOZqRaQ%3DaoOGqXOtf09%3D%3Dd2ABdeLNzk%2BTordA_023KGwrQ%40mail.gmail.com.
--000000000000b136ea056d59452d
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Tue, May 29, 2018 at 3:36 PM, <span dir=3D"ltr"><<a href=3D"mail=
to:mihailnajdenov@gmail.com" target=3D"_blank">mihailnajdenov@gmail.com</a>=
></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0=
0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><=
br>On Tuesday, May 29, 2018 at 5:09:43 PM UTC+3, Edward Catmur wrote:<block=
quote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left=
:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><br>On Sunday, 27 Ma=
y 2018 17:19:31 UTC+1, Florian Lemaitre wrote:<blockquote class=3D"gmail_q=
uote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddin=
g-left:1ex">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<p>Lazy arguments are compatible with terse lambda. Having one will
not remove the need for the other.<br>
<br>
You seem to miss one crucial point with this proposal (P0927): it
will not create anonymous classes at all: it will always use a
function pointer like this: T (*)(void*)<br>
<br>
If I give an example with the proposal syntax, this will be:<br>
</p>
<div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,18=
7,187);border-style:solid;border-width:1px"><code>
<div><span style=3D"color:#008">int</span><span style=3D"color:#000=
"> foo</span><span style=3D"color:#660">([]</span><span style=3D"color:#000=
"> </span><span style=3D"color:#660">-></span><span style=3D"color:#000"=
> </span><span style=3D"color:#008">int</span><span style=3D"color:#000"> i=
</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 </span><span style=3D"color:#008">return</span><span sty=
le=3D"color:#000"> i</span><span style=3D"color:#660">();</span><span style=
=3D"color:#000"><br>
</span><span style=3D"color:#660">}</span><span style=3D"color:#0=
00"><br>
<br>
</span><span style=3D"color:#008">int</span><span style=3D"color:=
#000"> bar</span><span style=3D"color:#660">(</span><span style=3D"color:#0=
08">int</span><span style=3D"color:#000"> j</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 </span><span style=3D"color:#008">return</span><span sty=
le=3D"color:#000"> foo</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">j</span><span style=3D"color:#660">+</span><span style=3D"c=
olor:#066">2</span><span style=3D"color:#660">);</span><span style=3D"color=
:#000"><br>
</span><span style=3D"color:#660">}</span><span style=3D"color:#0=
00"><br>
</span><span style=3D"color:#008">int</span><span style=3D"color:=
#000"> foobar</span><span style=3D"color:#660">(</span><span style=3D"color=
:#008">int</span><span style=3D"color:#000"> j</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 </span><span style=3D"color:#008">return</span><span sty=
le=3D"color:#000"> foo</span><span style=3D"color:#660">(</span><span style=
=3D"color:#066">2</span><span style=3D"color:#660">*</span><span style=3D"c=
olor:#000">j</span><span style=3D"color:#660">);</span><span style=3D"color=
:#000"><br>
</span><span style=3D"color:#660">}</span><span style=3D"color:#0=
00"><br>
</span></div>
</code></div>
<br>
With lambdas, you will have two instantiation of foo, but in this
proposal, you will have a single symbol for foo, which would be
equivalent to <span style=3D"font-family:courier new,monospace">int
foo(int (*)(void*), void*)</span>.<br>
<br>
So the previous example will be strictly equivalent to:<br>
<div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,18=
7,187);border-style:solid;border-width:1px"><code>
<div><span style=3D"color:#008">int</span><span style=3D"color:#000=
"> foo</span><span style=3D"color:#660">(</span><span style=3D"color:#008">=
int</span><span style=3D"color:#000"> </span><span style=3D"color:#660">(*<=
/span><span style=3D"color:#000">i</span><span style=3D"color:#660">)(</spa=
n><span style=3D"color:#008">void</span><span style=3D"color:#660">*),</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#008">void</span>=
<span style=3D"color:#660">*</span><span style=3D"color:#000"> stack_p</spa=
n><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#660">{</span><span style=3D"color:#000"><br>
=C2=A0 </span><span style=3D"color:#008">return</span><span sty=
le=3D"color:#000"> i</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">stack_p</span><span style=3D"color:#660">);</span><span sty=
le=3D"color:#000"><br>
</span><span style=3D"color:#660">}</span><span style=3D"color:#0=
00"><br>
<br>
</span><span style=3D"color:#008">int</span><span style=3D"color:=
#000"> bar</span><span style=3D"color:#660">(</span><span style=3D"color:#0=
08">int</span><span style=3D"color:#000"> j</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 </span><span style=3D"color:#008">int</span><span style=
=3D"color:#000"> closure</span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#008">void</span><span style=3D"color:#660">*</span><span style=
=3D"color:#000"> stack_p</span><span style=3D"color:#660">)</span><span sty=
le=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:#008">int</span><span=
style=3D"color:#000"> j </span><span style=3D"color:#660">=3D</span><span =
style=3D"color:#000"> </span><span style=3D"color:#660">*</span><span style=
=3D"color:#008">static_cast</span><span style=3D"color:#660"><</span><sp=
an style=3D"color:#008">int</span><span style=3D"color:#660">*>(</span><=
span style=3D"color:#000">stack_p </span><span style=3D"color:#660">+</span=
><span style=3D"color:#000"> </span><span style=3D"color:#800">/* offset j
*/</span><span style=3D"color:#660">);</span><span style=3D"col=
or:#000"><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><s=
pan style=3D"color:#000"> j</span><span style=3D"color:#660">+</span><span =
style=3D"color:#066">2</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br>
=C2=A0 </span><span style=3D"color:#660">}</span><span style=3D=
"color:#000"><br>
=C2=A0 </span><span style=3D"color:#008">return</span><span sty=
le=3D"color:#000"> foo</span><span style=3D"color:#660">(&</span><span =
style=3D"color:#000">closure</span><span style=3D"color:#660">,</span><span=
style=3D"color:#000">
__builtin_frame_address</span><span style=3D"color:#660">(</spa=
n><span style=3D"color:#066">0</span><span style=3D"color:#660">));</span><=
span style=3D"color:#000"><br>
</span><span style=3D"color:#660">}</span><br>
<span style=3D"color:#000"><code><span style=3D"color:#000"><br>
</span><span style=3D"color:#008">int</span><span style=3D"co=
lor:#000"> foobar</span><span style=3D"color:#660">(</span><span style=3D"c=
olor:#008">int</span><span style=3D"color:#000"> j</span><span style=3D"col=
or:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#6=
60">{</span><span style=3D"color:#000"><br>
=C2=A0 </span><span style=3D"color:#008">int</span><span st=
yle=3D"color:#000"> closure</span><span style=3D"color:#660">(</span><span =
style=3D"color:#008">void</span><span style=3D"color:#660">*</span><span st=
yle=3D"color:#000"> stack_p</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:#008">int</span><=
span style=3D"color:#000"> j </span><span style=3D"color:#660">=3D</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">*</span><span s=
tyle=3D"color:#008">static_cast</span><span style=3D"color:#660"><</span=
><span style=3D"color:#008">int</span><span style=3D"color:#660">*>(</sp=
an><span style=3D"color:#000">stack_p
</span><span style=3D"color:#660">+</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#800">/*
offset j */</span><span style=3D"color:#660">);</span><span=
style=3D"color:#000"><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#008">return</spa=
n><span style=3D"color:#000"> 2*j</span><span style=3D"color:#660"></span><=
span style=3D"color:#066"></span><span style=3D"color:#660">;</span><span s=
tyle=3D"color:#000"><br>
=C2=A0 </span><span style=3D"color:#660">}</span><span styl=
e=3D"color:#000"><br>
=C2=A0 </span><span style=3D"color:#008">return</span><span=
style=3D"color:#000"> foo</span><span style=3D"color:#660">(&</span><s=
pan style=3D"color:#000">closure</span><span style=3D"color:#660">,</span><=
span style=3D"color:#000">
__builtin_frame_address</span><span style=3D"color:#660">(<=
/span><span style=3D"color:#066">0</span><span style=3D"color:#660">));</sp=
an><span style=3D"color:#000"><br>
</span><span style=3D"color:#660">}</span><span style=3D"colo=
r:#000"><br>
</span></code></span></div>
</code></div>
<br>
This will not lead to code bloat, nor create any anonymous types.<br>
It will create anonymous functions, sure, but with a known and fixed
type. And those functions will be created anyway if you want any
form of lazyness delayed evaluation. Even if the call site is aware
that it is creating those functions.<br>
<br>
As you can see, it is even mush simpler and lighter than creating a
std::function std::function_ref. There is no extra burden on the
compiler to optimize this: it is just inlining a function pointer
when this pointer is known: no heap allocation!<br></div></blockquote><=
div><br></div><div>This seems inefficient; if I have n lazy parameters, the=
address of the enclosing frame is passed n times when it needs to be passe=
d at most once and (for most ABIs) it does not need to be passed at all, si=
nce the called function can just save the stack pointer on entry. Would it =
not be better to just pass a bare code pointer?<br></div><div><br></div><di=
v>I suppose this would complicate taking the address of such lazy types, bu=
t perhaps it would be better if this operation were also forbidden? We don&=
#39;t allow taking the address of a reference per se, after all. If one nee=
ds to pass a lazy argument around, one can pass it as another lazy argument=
, or capture it into a closure type:</div><div><br></div><div style=3D"back=
ground-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:so=
lid;border-width:1px;word-wrap:break-word"><code><div><span style=3D"color:=
#008">int</span><span style=3D"color:#000"> bar</span><span style=3D"color:=
#660">([]</span><span style=3D"color:#000"> </span><span style=3D"color:#66=
0">-></span><span style=3D"color:#000"> </span><span style=3D"color:#008=
">int</span><span style=3D"color:#000"> i</span><font color=3D"#000000"><sp=
an style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#660">{</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">return</span><span style=3D"color:#000"> i</span><span styl=
e=3D"color:#660">();</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">}</span></font><span style=3D"color:#000"><br></span><span =
style=3D"color:#008">int</span><span style=3D"color:#000"> baz</span><span =
style=3D"color:#660">(</span><span style=3D"color:#000">std</span><span sty=
le=3D"color:#660">::</span><span style=3D"color:#000">function_ref</span><s=
pan style=3D"color:#660"><</span><span style=3D"color:#008">int</span><s=
pan style=3D"color:#660">()></span><span style=3D"color:#000"> f</span><=
span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><font =
color=3D"#666600"><span style=3D"color:#660">{</span><span style=3D"color:#=
000"> </span><span style=3D"color:#008">return</span><span style=3D"color:#=
000"> f</span><span style=3D"color:#660">();</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">}</span></font><span style=3D"color:#=
000"><br></span><span style=3D"color:#008">int</span><span style=3D"color:#=
000"> foo</span><span style=3D"color:#660">([]</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">-></span><span style=3D"color:#0=
00"> </span><span style=3D"color:#008">int</span><span style=3D"color:#000"=
> i</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:#008">return</span><span style=3D"co=
lor:#000"> bar</span><span style=3D"color:#660">(</span><span style=3D"colo=
r:#000">i</span><span style=3D"color:#660">())</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">+</span><span style=3D"color:#000">=
baz</span><span style=3D"color:#660">([&]</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#000">=
</span><span style=3D"color:#008">return</span><span style=3D"color:#000">=
i</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></=
span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br></sp=
an></div></code></div><div><span style=3D"font-family:monospace;background-=
color:rgb(250,250,250);color:rgb(102,102,0)"><br></span></div><div>Indeed (=
and perhaps controversially), if the parentheses-suffixed form is the only =
way to use the identifier of the parameter, then the parentheses are redund=
ant and can (should) be omitted, such that any use of the identifier (in ev=
aluated context) represents an evaluation of the argument expression (and t=
hus a call through the code pointer):<span style=3D"font-family:monospace;b=
ackground-color:rgb(250,250,250);color:rgb(102,102,0)"><br></span></div><di=
v><br></div><div><div style=3D"border-width:1px;border-style:solid;border-c=
olor:rgb(187,187,187);background-color:rgb(250,250,250);word-wrap:break-wor=
d"><code><div><span style=3D"color:#008">int</span><span style=3D"color:#00=
0"> bar</span><span style=3D"color:#660">([]</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">-></span><span style=3D"color:#000=
"> </span><span style=3D"color:#008">int</span><span style=3D"color:#000"> =
i</span><font color=3D"#000000"><span style=3D"color:#660">)</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">return</span><span style=
=3D"color:#000"> i</span><span style=3D"color:#660">;</span><span style=3D"=
color:#000"> </span><span style=3D"color:#660">}</span></font><span style=
=3D"color:#000"><br></span><span style=3D"color:#008">int</span><span style=
=3D"color:#000"> baz</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#000">function_ref</span><span style=3D"color:#660"><</span><s=
pan style=3D"color:#008">int</span><span style=3D"color:#660">()></span>=
<span style=3D"color:#000"> f</span><span style=3D"color:#660">)</span><spa=
n style=3D"color:#000"> </span><font color=3D"#666600"><span style=3D"color=
:#660">{</span><span style=3D"color:#000"> </span><span style=3D"color:#008=
">return</span><span style=3D"color:#000"> f</span><span style=3D"color:#66=
0">();</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
}</span></font><span style=3D"color:#000"><br></span><span style=3D"color:#=
008">int</span><span style=3D"color:#000"> foo</span><span style=3D"color:#=
660">([]</span><span style=3D"color:#000"> </span><span style=3D"color:#660=
">-></span><span style=3D"color:#000"> </span><span style=3D"color:#008"=
>int</span><span style=3D"color:#000"> i</span><span style=3D"color:#660">)=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{</spa=
n><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:=
#008">return</span><span style=3D"color:#000"> bar</span><span style=3D"col=
or:#660">(</span><span style=3D"color:#000">i</span><span style=3D"color:#6=
60">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">+=
</span><span style=3D"color:#000"> baz</span><span style=3D"color:#660">([&=
amp;]</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{=
</span><span style=3D"color:#000"> </span><span style=3D"color:#008">return=
</span><span style=3D"color:#000"> i</span><span style=3D"color:#660">;</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#660">};</span><=
span style=3D"color:#000"><br></span><span style=3D"color:#660">}</span></d=
iv></code></div></div><div><br></div><div>The address-of operation would re=
turn the address of the result of the argument expression, if the lazy para=
meter has a reference type, and would otherwise be ill-formed (since a [] -=
> T lazy parameter would be a prvalue):</div><div><br></div><div style=
=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-=
style:solid;border-width:1px;word-wrap:break-word"><code><div><span style=
=3D"color:#008">int</span><span style=3D"color:#660">*</span><span style=3D=
"color:#000"> foo</span><span style=3D"color:#660">([]</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">-></span><span style=3D"=
color:#000"> </span><span style=3D"color:#008">int</span><span style=3D"col=
or:#660">&</span><span style=3D"color:#000"> i</span><span style=3D"col=
or:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#6=
60">{</span><span style=3D"color:#000"> </span><span style=3D"color:#008">r=
eturn</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&=
amp;</span><span style=3D"color:#000">i</span><span style=3D"color:#660">;<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#660">}</span=
><span style=3D"color:#000"> </span><span style=3D"color:#800">// OK</span>=
<span style=3D"color:#000"><br></span><span style=3D"color:#008">int</span>=
<span style=3D"color:#660">*</span><span style=3D"color:#000"> bar</span><s=
pan style=3D"color:#660">([]</span><span style=3D"color:#000"> </span><span=
style=3D"color:#660">-></span><span style=3D"color:#000"> </span><span =
style=3D"color:#008">int</span><span style=3D"color:#000"> i</span><span st=
yle=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#008">return</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">&</span><span style=3D"color:#000">i</span><span style=3D"co=
lor:#660">;</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660">}</span><span style=3D"color:#000"> </span><span style=3D"color:#800">=
// ill-formed, taking address of a prvalue</span><span style=3D"color:#000"=
><br></span></div></code></div><div><br></div><div>Again, this would be sim=
ilar to references, where any use of an identifier of reference type in eva=
luated context represents a load or store to the bound object and the addre=
ss-of operation gives the address of the bound object rather than the refer=
ence itself.</div><div><br></div><div>This would certainly make translation=
from existing code simple, but maybe it is a step too far?</div></div></bl=
ockquote><div><br></div><div>Question: Why would you ever want to use=C2=A0=
<font face=3D"courier new,monospace">[] -> int</font><span> instead of=
=C2=A0<span></span><font face=3D"courier new,monospace">std::function_ref&l=
t;int()> </font><font face=3D"arial,sans-serif">as a parameter?=C2=A0</f=
ont></span></div></div></blockquote><div><br></div><div>[] -> int is tra=
nsparent at the call site; std::function_ref<int()> requires the call=
ing code to write a lambda. It is also lighter weight.</div></div></div></d=
iv>
<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/CAJnLdOZqRaQ%3DaoOGqXOtf09%3D%3Dd2ABd=
eLNzk%2BTordA_023KGwrQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoo=
ter">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdOZq=
RaQ%3DaoOGqXOtf09%3D%3Dd2ABdeLNzk%2BTordA_023KGwrQ%40mail.gmail.com</a>.<br=
/>
--000000000000b136ea056d59452d--
.
Author: Hyman Rosen <hyman.rosen@gmail.com>
Date: Tue, 29 May 2018 10:51:52 -0400
Raw View
--000000000000950d7f056d596054
Content-Type: text/plain; charset="UTF-8"
On Sat, May 26, 2018 at 4:52 AM <mihailnajdenov@gmail.com> wrote:
> - On the call site I really doubt not be able to see you are NOT
> constructing the argument on function call is a good idea
>
This is the way it's done by the language, and this facility should
therefore imitate it.
When I say a() && b(), I do not know at the call site whether b() will be
evaluated,
and if this construct is inside generic code, I have no way of figuring it
out - if the type
of a() is user-defined, b() will always be evaluated, and if it is
built-in, that evaluation
will be conditional. If this proposal does not allow user-defined
implementations of
operator&& and operator|| that work just like the built-in ones, then it is
a failure.
Constructs that conditionally evaluate are as old as the hills, like Lisp's
cond,
(cond (c1 e1) (c2 e2) (c3 e3)), in which at most one of the e*n* is ever
evaluated. Confusion is averted by naming or familiarity.
--
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/CAHSYqdZyMh7JO_aEvEExpgC38HsYnMU%3DLJqkdDUUc5Cg4jv76Q%40mail.gmail.com.
--000000000000950d7f056d596054
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_quote"><div dir=3D"ltr">On Sat, May 26=
, 2018 at 4:52 AM <<a href=3D"mailto:mihailnajdenov@gmail.com">mihailnaj=
denov@gmail.com</a>> wrote:</div><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div>=C2=A0- On the call site I really doubt not be able to see yo=
u are NOT constructing the argument on function call is a good idea</div></=
div></blockquote><div><br>This is the way it's done by the language, an=
d this facility should therefore imitate it.<br>When I say <font face=3D"mo=
nospace, monospace">a() && b()</font>, I do not know at the call si=
te whether <font face=3D"monospace, monospace">b()</font> will be evaluated=
,<br>and if this construct is inside generic code, I have no way of figurin=
g it out - if the type<br>of <font face=3D"monospace, monospace">a()</font>=
is user-defined, <font face=3D"monospace, monospace">b()</font> will alway=
s be evaluated, and if it is built-in, that evaluation</div><div>will be co=
nditional.=C2=A0 If this proposal does not allow user-defined implementatio=
ns of</div><div><font face=3D"monospace, monospace">operator&&</fon=
t> and=C2=A0<font face=3D"monospace, monospace">operator||</font><font face=
=3D"arial, helvetica, sans-serif">=C2=A0</font>that work just like the buil=
t-in ones, then it is a failure.</div><div><br>Constructs that conditionall=
y evaluate are as old as the hills, like Lisp's <font face=3D"monospace=
, monospace">cond</font>,<br><font face=3D"monospace, monospace">(cond (c1 =
e1) (c2 e2) (c3 e3))</font>, in which at most one of the <font face=3D"mono=
space, monospace">e<i>n</i></font> is ever</div><div>evaluated.=C2=A0 Confu=
sion is averted by naming or familiarity.</div></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/CAHSYqdZyMh7JO_aEvEExpgC38HsYnMU%3DLJ=
qkdDUUc5Cg4jv76Q%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAHSYqdZyMh7JO_=
aEvEExpgC38HsYnMU%3DLJqkdDUUc5Cg4jv76Q%40mail.gmail.com</a>.<br />
--000000000000950d7f056d596054--
.
Author: mihailnajdenov@gmail.com
Date: Tue, 29 May 2018 07:53:45 -0700 (PDT)
Raw View
------=_Part_39154_351448413.1527605625416
Content-Type: multipart/alternative;
boundary="----=_Part_39155_727102685.1527605625416"
------=_Part_39155_727102685.1527605625416
Content-Type: text/plain; charset="UTF-8"
On Tuesday, May 29, 2018 at 5:44:34 PM UTC+3, Edward Catmur wrote:
>
>
>
> On Tue, May 29, 2018 at 3:36 PM, <mihailn...@gmail.com <javascript:>>
> wrote:
>
>>
>>
>> On Tuesday, May 29, 2018 at 5:09:43 PM UTC+3, Edward Catmur wrote:
>>>
>>> ...
>>>
>>
>> Question: Why would you ever want to use [] -> int instead of std::function_ref<int()>
>> as a parameter?
>>
>
> [] -> int is transparent at the call site; std::function_ref<int()>
> requires the calling code to write a lambda. It is also lighter weight.
>
What if the user decides to upgrade the call and write a lambda? What if
the user wants to pass a callable instance variable? Overloads?
--
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/4ea5ab67-438a-4cbc-8b94-ef990ac4810e%40isocpp.org.
------=_Part_39155_727102685.1527605625416
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, May 29, 2018 at 5:44:34 PM UTC+3, Edwa=
rd Catmur wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt=
r"><br><div><br><div class=3D"gmail_quote">On Tue, May 29, 2018 at 3:36 PM,=
<span dir=3D"ltr"><<a onmousedown=3D"this.href=3D'javascript:'=
;return true;" onclick=3D"this.href=3D'javascript:';return true;" h=
ref=3D"javascript:" target=3D"_blank" rel=3D"nofollow" gdf-obfuscated-mailt=
o=3D"14acgujdBgAJ">mihailn...@gmail.com</a>></span> wrote:<br><blockquot=
e class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc sol=
id;padding-left:1ex"><div dir=3D"ltr"><br><br>On Tuesday, May 29, 2018 at 5=
:09:43 PM UTC+3, Edward Catmur wrote:<blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr">...</div></blockquote><div><br></div><div>Question: Why =
would you ever want to use=C2=A0<font face=3D"courier new,monospace">[] -&g=
t; int</font><span> instead of=C2=A0<span></span><font face=3D"courier new,=
monospace">std::function_ref<int()> </font><font face=3D"arial,sans-s=
erif">as a parameter?=C2=A0</font></span></div></div></blockquote><div><br>=
</div><div>[] -> int is transparent at the call site; std::function_ref&=
lt;int()> requires the calling code to write a lambda. It is also lighte=
r weight.</div></div></div></div></blockquote><div><br></div><div>What if t=
he user decides to upgrade the call and write a lambda? What if the user wa=
nts to pass a callable instance variable? Overloads?=C2=A0</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/4ea5ab67-438a-4cbc-8b94-ef990ac4810e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4ea5ab67-438a-4cbc-8b94-ef990ac4810e=
%40isocpp.org</a>.<br />
------=_Part_39155_727102685.1527605625416--
------=_Part_39154_351448413.1527605625416--
.
Author: Hyman Rosen <hyman.rosen@gmail.com>
Date: Tue, 29 May 2018 11:00:15 -0400
Raw View
--000000000000986ef9056d597e45
Content-Type: text/plain; charset="UTF-8"
On Tue, May 29, 2018 at 10:48 AM Nicol Bolas <jmckesson@gmail.com> wrote:
> On Tuesday, May 29, 2018 at 10:40:53 AM UTC-4, mihailn...@gmail.com wrote:
>>
>> Question: Why would you ever want to use [] -> int instead of std::function_ref<int()>
>> as a parameter?
>>
>
> Because I don't really want to call a function to get a value. I want you
> to give me an expression that I will evaluate later to produce a value of
> that type. That this happens through "a function" is an *implementation
> detail*, one that I have no interest in as the writer of that function.
>
It may be an implementation detail, but the function is the implementation!
If we're providing the possibility of unevaluated parameters, with the
function
in charge of whether they're evaluated, it seems valuable to let the
evaluation
look deliberate. It also sidesteps the question of whether an unevaluated
parameter can be evaluated at most once or more than once, by making
evaluations manifest in the code.
The worst case would be to to have the compiler decide behind the scenes
whether to do the evaluation based on its detection of the first use of the
parameter.
--
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/CAHSYqdYxcX5OxF1QPt71K-gi0XCVf-Y%2B8YzMOSMZktKfBs%3DUhA%40mail.gmail.com.
--000000000000986ef9056d597e45
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_quote"><div dir=3D"ltr">On Tue, May 29=
, 2018 at 10:48 AM Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.com">j=
mckesson@gmail.com</a>> wrote:<br></div><blockquote class=3D"gmail_quote=
" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><=
div dir=3D"ltr">On Tuesday, May 29, 2018 at 10:40:53 AM UTC-4, <a href=3D"m=
ailto:mihailn...@gmail.com" target=3D"_blank">mihailn...@gmail.com</a> wrot=
e:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div></div><div>=
<span style=3D"display:inline!important;float:none;background-color:transpa=
rent;color:rgb(34,34,34);font-family:"Arial","Helvetica"=
;,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weig=
ht:400;letter-spacing:normal;text-align:left;text-decoration:none;text-inde=
nt:0px;text-transform:none;white-space:normal;word-spacing:0px">Question: W=
hy would you ever want to use=C2=A0</span><font style=3D"background-color:t=
ransparent;border-bottom-color:rgb(34,34,34);border-bottom-style:none;borde=
r-bottom-width:0px;border-left-color:rgb(34,34,34);border-left-style:none;b=
order-left-width:0px;border-right-color:rgb(34,34,34);border-right-style:no=
ne;border-right-width:0px;border-top-color:rgb(34,34,34);border-top-style:n=
one;border-top-width:0px;color:rgb(34,34,34);font-family:courier new,monosp=
ace;font-size:13px;font-style:normal;font-variant:normal;font-weight:400;le=
tter-spacing:normal;margin-bottom:0px;margin-left:0px;margin-right:0px;marg=
in-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-to=
p:0px;text-align:left;text-decoration:none;text-indent:0px;text-transform:n=
one;white-space:normal;word-spacing:0px" face=3D"courier new,monospace">[] =
-> int</font><span> instead of=C2=A0<span style=3D"border-bottom-color:r=
gb(34,34,34);border-bottom-style:none;border-bottom-width:0px;border-left-c=
olor:rgb(34,34,34);border-left-style:none;border-left-width:0px;border-righ=
t-color:rgb(34,34,34);border-right-style:none;border-right-width:0px;border=
-top-color:rgb(34,34,34);border-top-style:none;border-top-width:0px;margin-=
bottom:0px;margin-left:0px;margin-right:0px;margin-top:0px;padding-bottom:0=
px;padding-left:0px;padding-right:0px;padding-top:0px"></span><font style=
=3D"border-bottom-color:rgb(34,34,34);border-bottom-style:none;border-botto=
m-width:0px;border-left-color:rgb(34,34,34);border-left-style:none;border-l=
eft-width:0px;border-right-color:rgb(34,34,34);border-right-style:none;bord=
er-right-width:0px;border-top-color:rgb(34,34,34);border-top-style:none;bor=
der-top-width:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;margin=
-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:=
0px" face=3D"courier new,monospace">std::function_ref<int()> </font><=
font style=3D"border-bottom-color:rgb(34,34,34);border-bottom-style:none;bo=
rder-bottom-width:0px;border-left-color:rgb(34,34,34);border-left-style:non=
e;border-left-width:0px;border-right-color:rgb(34,34,34);border-right-style=
:none;border-right-width:0px;border-top-color:rgb(34,34,34);border-top-styl=
e:none;border-top-width:0px;margin-bottom:0px;margin-left:0px;margin-right:=
0px;margin-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;pa=
dding-top:0px" face=3D"arial,sans-serif">as a parameter?=C2=A0</font></span=
></div></div></blockquote><div><br></div><div>Because I don't really wa=
nt to call a function to get a value. I want you to give me an expression t=
hat I will evaluate later to produce a value of that type. That this happen=
s through "a function" is an <i>implementation detail</i>, one th=
at I have no interest in as the writer of that function.</div></div></block=
quote><div><br>It may be an implementation detail, but the function is the =
implementation!<br>If we're providing the possibility of unevaluated pa=
rameters, with the function<br>in charge of whether they're evaluated, =
it seems valuable to let the evaluation<br>look deliberate.=C2=A0 It also s=
idesteps the question of whether an unevaluated<br>parameter can be evaluat=
ed at most once or more than once, by making<br>evaluations manifest in the=
code.<br><br>The worst case would be to to have the compiler decide behind=
the scenes<br>whether to do the evaluation based on its detection of the f=
irst use of the<br>parameter.</div></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/CAHSYqdYxcX5OxF1QPt71K-gi0XCVf-Y%2B8Y=
zMOSMZktKfBs%3DUhA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAHSYqdYxcX5O=
xF1QPt71K-gi0XCVf-Y%2B8YzMOSMZktKfBs%3DUhA%40mail.gmail.com</a>.<br />
--000000000000986ef9056d597e45--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 29 May 2018 08:03:29 -0700 (PDT)
Raw View
------=_Part_28194_2111477002.1527606209508
Content-Type: multipart/alternative;
boundary="----=_Part_28195_36668637.1527606209508"
------=_Part_28195_36668637.1527606209508
Content-Type: text/plain; charset="UTF-8"
On Tuesday, May 29, 2018 at 10:53:45 AM UTC-4, mihailn...@gmail.com wrote:
>
>
>
> On Tuesday, May 29, 2018 at 5:44:34 PM UTC+3, Edward Catmur wrote:
>>
>>
>>
>> On Tue, May 29, 2018 at 3:36 PM, <mihailn...@gmail.com> wrote:
>>
>>>
>>>
>>> On Tuesday, May 29, 2018 at 5:09:43 PM UTC+3, Edward Catmur wrote:
>>>>
>>>> ...
>>>>
>>>
>>> Question: Why would you ever want to use [] -> int instead of std::function_ref<int()>
>>> as a parameter?
>>>
>>
>> [] -> int is transparent at the call site; std::function_ref<int()>
>> requires the calling code to write a lambda. It is also lighter weight.
>>
>
> What if the user decides to upgrade the call and write a lambda? What if
> the user wants to pass a callable instance variable? Overloads?
>
What happens when a user decides to stop using `std::string` and start
trying to pass a `std::vector<char>`? They get a compile error for not
providing the thing they were told by the API to provide.
How is that any different? You said "give me an expression that results in
an integer". You instead tries to give a lambda. That's not "an expression
that results in an integer", so you get a compile error.
You can turn any function-that-results-in-an-integer into an
expresion-that-results-in-an-integer simply by calling it in-situ:
func([]() -> int{...}());
That makes it clear to everyone that the function *call* is the expression
being captured, not the function itself.
--
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/3964f817-090f-454a-ab08-4e15058a23f7%40isocpp.org.
------=_Part_28195_36668637.1527606209508
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, May 29, 2018 at 10:53:45 AM UTC-4, mih=
ailn...@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div d=
ir=3D"ltr"><br><br>On Tuesday, May 29, 2018 at 5:44:34 PM UTC+3, Edward Cat=
mur 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"><br><div=
><br><div class=3D"gmail_quote">On Tue, May 29, 2018 at 3:36 PM, <span dir=
=3D"ltr"><<a rel=3D"nofollow">mihailn...@gmail.com</a>></span> wrote:=
<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><br>On Tuesday, May=
29, 2018 at 5:09:43 PM UTC+3, Edward Catmur wrote:<blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr">...</div></blockquote><div><br></div><div>=
Question: Why would you ever want to use=C2=A0<font face=3D"courier new,mon=
ospace">[] -> int</font><span> instead of=C2=A0<span></span><font face=
=3D"courier new,monospace">std::function_ref<int()> </font><font face=
=3D"arial,sans-serif">as a parameter?=C2=A0</font></span></div></div></bloc=
kquote><div><br></div><div>[] -> int is transparent at the call site; st=
d::function_ref<int()> requires the calling code to write a lambda. I=
t is also lighter weight.</div></div></div></div></blockquote><div><br></di=
v><div>What if the user decides to upgrade the call and write a lambda? Wha=
t if the user wants to pass a callable instance variable? Overloads?=C2=A0<=
/div></div></blockquote><div><br></div><div>What happens when a user decide=
s to stop using `std::string` and start trying to pass a `std::vector<ch=
ar>`? They get a compile error for not providing the thing they were tol=
d by the API to provide.</div><div><br></div><div>How is that any different=
? You said "give me an expression that results in an integer". Yo=
u instead tries to give a lambda. That's not "an expression that r=
esults in an integer", so you get a compile error.</div><div><br></div=
><div>You can turn any function-that-results-in-an-integer into an expresio=
n-that-results-in-an-integer simply by calling it in-situ:</div><div><br></=
div><div><div style=3D"background-color: rgb(250, 250, 250); border-color: =
rgb(187, 187, 187); border-style: solid; border-width: 1px; overflow-wrap: =
break-word;" class=3D"prettyprint"><code class=3D"prettyprint"><div class=
=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">func</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"> </span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">{...}());</span></div></code></div><br=
></div><div>That makes it clear to everyone that the function <i>call</i> i=
s the expression being captured, not the function itself.<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/3964f817-090f-454a-ab08-4e15058a23f7%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/3964f817-090f-454a-ab08-4e15058a23f7=
%40isocpp.org</a>.<br />
------=_Part_28195_36668637.1527606209508--
------=_Part_28194_2111477002.1527606209508--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 29 May 2018 16:12:49 +0100
Raw View
--000000000000dc74cb056d59aae5
Content-Type: text/plain; charset="UTF-8"
On Tue, May 29, 2018 at 4:00 PM, Hyman Rosen <hyman.rosen@gmail.com> wrote:
> If we're providing the possibility of unevaluated parameters, with the
> function
> in charge of whether they're evaluated, it seems valuable to let the
> evaluation
> look deliberate. It also sidesteps the question of whether an unevaluated
> parameter can be evaluated at most once or more than once, by making
> evaluations manifest in the code.
>
> The worst case would be to to have the compiler decide behind the scenes
> whether to do the evaluation based on its detection of the first use of the
> parameter.
>
Thanks, I think those are pretty strong arguments in favor of
`identifier()` as the invocation syntax and against bare `identifier`.
(I'd still hope that the committee would consider and reject the bare
syntax for posterity, but I recognise that may not be the best use of time.)
--
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/CAJnLdOZNXN-B7BHhCNa783xb0TnmCLN6WUfjgd0Pcip-oHF22g%40mail.gmail.com.
--000000000000dc74cb056d59aae5
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
ue, May 29, 2018 at 4:00 PM, Hyman Rosen <span dir=3D"ltr"><<a href=3D"m=
ailto:hyman.rosen@gmail.com" target=3D"_blank">hyman.rosen@gmail.com</a>>=
;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 =
..8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div cla=
ss=3D"gmail_quote"><div dir=3D"ltr">If we're providing the possibility =
of unevaluated parameters, with the function<br></div><div>in charge of whe=
ther they're evaluated, it seems valuable to let the evaluation<br>look=
deliberate.=C2=A0 It also sidesteps the question of whether an unevaluated=
<br>parameter can be evaluated at most once or more than once, by making<br=
>evaluations manifest in the code.<br><br>The worst case would be to to hav=
e the compiler decide behind the scenes<br>whether to do the evaluation bas=
ed on its detection of the first use of the<br>parameter.</div></div></div>=
</blockquote><div><br></div><div>Thanks, I think those are pretty strong ar=
guments in favor of `identifier()` as the invocation syntax and against bar=
e `identifier`.=C2=A0</div><div><br></div><div>(I'd still hope that the=
committee would consider and reject the bare syntax for posterity, but I r=
ecognise that may not be the best use of time.)</div></div></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/CAJnLdOZNXN-B7BHhCNa783xb0TnmCLN6WUfj=
gd0Pcip-oHF22g%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdOZNXN-B7BHh=
CNa783xb0TnmCLN6WUfjgd0Pcip-oHF22g%40mail.gmail.com</a>.<br />
--000000000000dc74cb056d59aae5--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 29 May 2018 08:33:28 -0700 (PDT)
Raw View
------=_Part_38930_790257061.1527608008390
Content-Type: multipart/alternative;
boundary="----=_Part_38931_230135040.1527608008391"
------=_Part_38931_230135040.1527608008391
Content-Type: text/plain; charset="UTF-8"
On Tuesday, May 29, 2018 at 11:12:51 AM UTC-4, Edward Catmur wrote:
>
> On Tue, May 29, 2018 at 4:00 PM, Hyman Rosen <hyman...@gmail.com
> <javascript:>> wrote:
>
>> If we're providing the possibility of unevaluated parameters, with the
>> function
>> in charge of whether they're evaluated, it seems valuable to let the
>> evaluation
>> look deliberate. It also sidesteps the question of whether an unevaluated
>> parameter can be evaluated at most once or more than once, by making
>> evaluations manifest in the code.
>>
>> The worst case would be to to have the compiler decide behind the scenes
>> whether to do the evaluation based on its detection of the first use of
>> the
>> parameter.
>>
>
> Thanks, I think those are pretty strong arguments in favor of
> `identifier()` as the invocation syntax and against bare `identifier`.
>
They're arguments for *an* "evaluation syntax"; not for `identifier()` as
that syntax. Yes, we need a way to tell the difference between talking
about the captured expression (which you might defer to some other
function) and evaluating it. And maybe `identifier()` would be OK.
But I don't like the idea of allowing the user to use `identifier` as if it
were a function or functor. Or even as if it were an *object*. It should be
a completely different order of things, fundamentally distinct from
anything else in C++. Much like braced-init-lists aren't expressions,
captured expressions identifiers should not be objects or functions.
--
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/0a27de1f-9ae2-4723-9583-9a50bf1a3fe7%40isocpp.org.
------=_Part_38931_230135040.1527608008391
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, May 29, 2018 at 11:12:51 AM UTC-4, Edward Catm=
ur 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"><div=
><div class=3D"gmail_quote">On Tue, May 29, 2018 at 4:00 PM, Hyman Rosen <s=
pan dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscate=
d-mailto=3D"E18pmHPfBgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'=
javascript:';return true;" onclick=3D"this.href=3D'javascript:'=
;return true;">hyman...@gmail.com</a>></span> wrote:<br><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_quote"><div dir=3D"ltr"=
>If we're providing the possibility of unevaluated parameters, with the=
function<br></div><div>in charge of whether they're evaluated, it seem=
s valuable to let the evaluation<br>look deliberate.=C2=A0 It also sidestep=
s the question of whether an unevaluated<br>parameter can be evaluated at m=
ost once or more than once, by making<br>evaluations manifest in the code.<=
br><br>The worst case would be to to have the compiler decide behind the sc=
enes<br>whether to do the evaluation based on its detection of the first us=
e of the<br>parameter.</div></div></div></blockquote><div><br></div><div>Th=
anks, I think those are pretty strong arguments in favor of `identifier()` =
as the invocation syntax and against bare `identifier`.</div></div></div></=
div></blockquote><div><br></div><div>They're arguments for <i>an</i> &q=
uot;evaluation syntax"; not for `identifier()` as that syntax. Yes, we=
need a way to tell the difference between talking about the captured expre=
ssion (which you might defer to some other function) and evaluating it. And=
maybe `identifier()` would be OK.<br></div><div><br></div><div>But I don&#=
39;t like the idea of allowing the user to use `identifier` as if it were a=
function or functor. Or even as if it were an <i>object</i>. It should be =
a completely different order of things, fundamentally distinct from anythin=
g else in C++. Much like braced-init-lists aren't expressions, captured=
expressions identifiers should not be objects or functions.</div><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/0a27de1f-9ae2-4723-9583-9a50bf1a3fe7%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/0a27de1f-9ae2-4723-9583-9a50bf1a3fe7=
%40isocpp.org</a>.<br />
------=_Part_38931_230135040.1527608008391--
------=_Part_38930_790257061.1527608008390--
.
Author: Hyman Rosen <hyman.rosen@gmail.com>
Date: Tue, 29 May 2018 11:44:08 -0400
Raw View
--00000000000090b142056d5a1b8d
Content-Type: text/plain; charset="UTF-8"
On Tue, May 29, 2018 at 11:33 AM Nicol Bolas <jmckesson@gmail.com> wrote:
> But I don't like the idea of allowing the user to use `identifier` as if
> it were a function or functor.
>
Or even as if it were an *object*. It should be a completely different
> order of things, fundamentally
>
distinct from anything else in C++. Much like braced-init-lists aren't
> expressions, captured
>
expressions identifiers should not be objects or functions.
>
"Thing that can be invoked to execute a block of code and get back a value"
is not a completely different order of things. It's a function. Using
function-call
syntax therefore makes sense.
--
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/CAHSYqdb4vb9%3Db7%3Dpmf4HOGPU4VMt-1zmRTz626-jVF8pqB9Grw%40mail.gmail.com.
--00000000000090b142056d5a1b8d
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_quote"><div dir=3D"ltr">On Tue, May 29=
, 2018 at 11:33 AM Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.com">j=
mckesson@gmail.com</a>> wrote:</div><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div =
dir=3D"ltr"><div>But I don't like the idea of allowing the user to use =
`identifier` as if it were a function or functor.</div></div></blockquote><=
blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px=
#ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Or even as if it were a=
n <i>object</i>. It should be a completely different order of things, funda=
mentally</div></div></blockquote><blockquote class=3D"gmail_quote" style=3D=
"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D=
"ltr"><div>distinct from anything else in C++. Much like braced-init-lists =
aren't expressions, captured</div></div></blockquote><blockquote class=
=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div dir=3D"ltr"><div>expressions identifiers should not be o=
bjects or functions.</div></div></blockquote><div><br>=C2=A0"Thing tha=
t can be invoked to execute a block of code and get back a value"<br>i=
s not a completely different order of things.=C2=A0 It's a function.=C2=
=A0 Using function-call<br>syntax therefore makes sense.</div></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/CAHSYqdb4vb9%3Db7%3Dpmf4HOGPU4VMt-1zm=
RTz626-jVF8pqB9Grw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAHSYqdb4vb9%=
3Db7%3Dpmf4HOGPU4VMt-1zmRTz626-jVF8pqB9Grw%40mail.gmail.com</a>.<br />
--00000000000090b142056d5a1b8d--
.
Author: mihailnajdenov@gmail.com
Date: Tue, 29 May 2018 09:12:12 -0700 (PDT)
Raw View
------=_Part_39014_1399193513.1527610332850
Content-Type: multipart/alternative;
boundary="----=_Part_39015_519021685.1527610332851"
------=_Part_39015_519021685.1527610332851
Content-Type: text/plain; charset="UTF-8"
On Tuesday, May 29, 2018 at 6:03:29 PM UTC+3, Nicol Bolas wrote:
>
>
>
> On Tuesday, May 29, 2018 at 10:53:45 AM UTC-4, mihailn...@gmail.com wrote:
>>
>>
>>
>> On Tuesday, May 29, 2018 at 5:44:34 PM UTC+3, Edward Catmur wrote:
>>>
>>>
>>>
>>> On Tue, May 29, 2018 at 3:36 PM, <mihailn...@gmail.com> wrote:
>>>
>>>>
>>>>
>>>> On Tuesday, May 29, 2018 at 5:09:43 PM UTC+3, Edward Catmur wrote:
>>>>>
>>>>> ...
>>>>>
>>>>
>>>> Question: Why would you ever want to use [] -> int instead of std::function_ref<int()>
>>>> as a parameter?
>>>>
>>>
>>> [] -> int is transparent at the call site; std::function_ref<int()>
>>> requires the calling code to write a lambda. It is also lighter weight.
>>>
>>
>> What if the user decides to upgrade the call and write a lambda? What if
>> the user wants to pass a callable instance variable? Overloads?
>>
>
> What happens when a user decides to stop using `std::string` and start
> trying to pass a `std::vector<char>`? They get a compile error for not
> providing the thing they were told by the API to provide.
>
And that is exactly why we are moving away from std::string as a param to
string_view!
You want a good, general interface. Accepting a lazy arg *alone* is not
one.
>
> How is that any different? You said "give me an expression that results in
> an integer". You instead tries to give a lambda. That's not "an expression
> that results in an integer", so you get a compile error.
>
> You can turn any function-that-results-in-an-integer into an
> expresion-that-results-in-an-integer simply by calling it in-situ:
>
And both bind to function_ref hence function_ref is the better interface.
The problem is, the user knows the code is late evaluated - he has seen the
declaration.
Second, for the user there is no *practical* difference b/w
"function-that-results-in-an-integer" and
"expresion-that-results-in-an-integer"
Because of this the user *will want* to pass callables as well.
With lazy arg interface *alone* this will be both clumsy and awkward (to
say the least).
>
> func([]() -> int{...}());
>
> That makes it clear to everyone that the function *call* is the
> expression being captured, not the function itself.
>
--
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/4a0155aa-490d-4948-8ade-732c339e1e8d%40isocpp.org.
------=_Part_39015_519021685.1527610332851
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, May 29, 2018 at 6:03:29 PM UTC+3, Nico=
l Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><br><br>On Tuesday, May 29, 2018 at 10:53:45 AM UTC-4, <a>mihailn...@gmail=
..com</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-l=
eft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br=
><br>On Tuesday, May 29, 2018 at 5:44:34 PM UTC+3, Edward Catmur wrote:<blo=
ckquote 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"><br><div><br><div clas=
s=3D"gmail_quote">On Tue, May 29, 2018 at 3:36 PM, <span dir=3D"ltr"><<=
a rel=3D"nofollow">mihailn...@gmail.com</a>></span> wrote:<br><blockquot=
e class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc sol=
id;padding-left:1ex"><div dir=3D"ltr"><br><br>On Tuesday, May 29, 2018 at 5=
:09:43 PM UTC+3, Edward Catmur wrote:<blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr">...</div></blockquote><div><br></div><div>Question: Why =
would you ever want to use=C2=A0<font face=3D"courier new,monospace">[] -&g=
t; int</font><span> instead of=C2=A0<span></span><font face=3D"courier new,=
monospace">std::function_ref<int()> </font><font face=3D"arial,sans-s=
erif">as a parameter?=C2=A0</font></span></div></div></blockquote><div><br>=
</div><div>[] -> int is transparent at the call site; std::function_ref&=
lt;int()> requires the calling code to write a lambda. It is also lighte=
r weight.</div></div></div></div></blockquote><div><br></div><div>What if t=
he user decides to upgrade the call and write a lambda? What if the user wa=
nts to pass a callable instance variable? Overloads?=C2=A0</div></div></blo=
ckquote><div><br></div><div>What happens when a user decides to stop using =
`std::string` and start trying to pass a `std::vector<char>`? They ge=
t a compile error for not providing the thing they were told by the API to =
provide.</div></div></blockquote><div><br></div><div>And that is exactly wh=
y we are moving away from std::string as a param to string_view!=C2=A0</div=
><div>You want a good, general interface. Accepting a lazy arg <i>alone</i>=
is not one. </div><div>=C2=A0</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><br></div><div>How is that any different? You s=
aid "give me an expression that results in an integer". You inste=
ad tries to give a lambda. That's not "an expression that results =
in an integer", so you get a compile error.</div><div><br></div><div>Y=
ou can turn any function-that-results-in-an-<wbr>integer into an expresion-=
that-results-in-an-<wbr>integer simply by calling it in-situ:</div></div></=
blockquote><div>=C2=A0</div><div><br></div><div>And both bind to function_r=
ef hence function_ref is the better interface.</div><div><br></div><div>The=
problem is, the user knows the code is late evaluated - he has seen the de=
claration.=C2=A0</div><div>Second, for the user there is no <i>practical</i=
> difference b/w "function-that-results-in-an-integer" and "=
expresion-that-results-in-an-integer"</div><div><br></div><div>Because=
of this the user <i>will want</i> to pass callables as well.=C2=A0</div><d=
iv><br></div><div>With lazy arg interface <i>alone</i> this will be both cl=
umsy and awkward (to say the least).</div><div>=C2=A0</div><blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #c=
cc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><div><div styl=
e=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border=
-style:solid;border-width:1px"><code><div><span style=3D"color:#000">func</=
span><span style=3D"color:#660">([]()</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">-></span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#008">int</span><span style=3D"color:#660">{...}())=
;</span></div></code></div><br></div><div>That makes it clear to everyone t=
hat the function <i>call</i> is the expression being captured, not the func=
tion itself.<br></div></div></blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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/4a0155aa-490d-4948-8ade-732c339e1e8d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4a0155aa-490d-4948-8ade-732c339e1e8d=
%40isocpp.org</a>.<br />
------=_Part_39015_519021685.1527610332851--
------=_Part_39014_1399193513.1527610332850--
.
Author: florian.csdt@gmail.com
Date: Tue, 29 May 2018 09:41:28 -0700 (PDT)
Raw View
------=_Part_39240_336671412.1527612088665
Content-Type: multipart/alternative;
boundary="----=_Part_39241_194391813.1527612088665"
------=_Part_39241_194391813.1527612088665
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le mardi 29 mai 2018 18:12:12 UTC+2, mihailn...@gmail.com a =C3=A9crit :
>
>
>
> On Tuesday, May 29, 2018 at 6:03:29 PM UTC+3, Nicol Bolas wrote:
>>
>>
>>
>> On Tuesday, May 29, 2018 at 10:53:45 AM UTC-4, mihailn...@gmail.com=20
>> wrote:
>>>
>>>
>>>
>>> On Tuesday, May 29, 2018 at 5:44:34 PM UTC+3, Edward Catmur wrote:
>>>>
>>>>
>>>>
>>>> On Tue, May 29, 2018 at 3:36 PM, <mihailn...@gmail.com> wrote:
>>>>
>>>>>
>>>>>
>>>>> On Tuesday, May 29, 2018 at 5:09:43 PM UTC+3, Edward Catmur wrote:
>>>>>>
>>>>>> ...
>>>>>>
>>>>>
>>>>> Question: Why would you ever want to use [] -> int instead of std::fu=
nction_ref<int()>=20
>>>>> as a parameter?=20
>>>>>
>>>>
>>>> [] -> int is transparent at the call site; std::function_ref<int()>=20
>>>> requires the calling code to write a lambda. It is also lighter weight=
..
>>>>
>>>
>>> What if the user decides to upgrade the call and write a lambda? What i=
f=20
>>> the user wants to pass a callable instance variable? Overloads?=20
>>>
>>
>> What happens when a user decides to stop using `std::string` and start=
=20
>> trying to pass a `std::vector<char>`? They get a compile error for not=
=20
>> providing the thing they were told by the API to provide.
>>
>
> And that is exactly why we are moving away from std::string as a param to=
=20
> string_view!=20
> You want a good, general interface. Accepting a lazy arg *alone* is not=
=20
> one.=20
> =20
>
>>
>> How is that any different? You said "give me an expression that results=
=20
>> in an integer". You instead tries to give a lambda. That's not "an=20
>> expression that results in an integer", so you get a compile error.
>>
>> You can turn any function-that-results-in-an-integer into an=20
>> expresion-that-results-in-an-integer simply by calling it in-situ:
>>
> =20
>
> And both bind to function_ref hence function_ref is the better interface.
>
> The problem is, the user knows the code is late evaluated - he has seen=
=20
> the declaration.=20
> Second, for the user there is no *practical* difference b/w=20
> "function-that-results-in-an-integer" and=20
> "expresion-that-results-in-an-integer"
>
> Because of this the user *will want* to pass callables as well.=20
>
> With lazy arg interface *alone* this will be both clumsy and awkward (to=
=20
> say the least).
> =20
>
>>
>> func([]() -> int{...}());
>>
>> That makes it clear to everyone that the function *call* is the=20
>> expression being captured, not the function itself.
>>
>
You are missing the point: lazy parameters is not about passing callables=
=20
to a function, it is about delaying the construction of the parameters in=
=20
order to skip the construction of not needed ones, or allow some Return=20
Value Optimizations by knowing the final destination of the object.
If the call site is not transparent to this, then you cannot overload=20
properly operator|| for instance (or operator?: if this gets accepted), and=
=20
makes most use cases harder to write for the user for no good reason.
An "expression-that-results-in-an-integer" has no syntax overhead.
You could argue that an expression is implicitly convertible (without=20
executing it) into a std::function_ref, for instance. This would allow you=
=20
to have a real object to play with while allowing transparent call site.
But this would make the type system clumsy.
Consider trying to pass a std::function_ref<T()> as a lazy parameter to a=
=20
function that takes any kind of input:
template <class T>
T foo(std::function_ref<T()> f) { return f(); }
foo(1) // ok automatic conversion from 1 to std::function<int()>: lazy=20
evaluation
foo(std::function_ref<int()>([](){ return 1; })) //=20
std::function_ref<int()> is copied, not lazy evaluated
So expressions implicitly convertible to std::function_ref: bad idea!
--=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/92a83f13-3f06-43b5-9340-7942c13e0b33%40isocpp.or=
g.
------=_Part_39241_194391813.1527612088665
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le mardi 29 mai 2018 18:12:12 UTC+2, mihailn...@gm=
ail.com a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v dir=3D"ltr"><br><br>On Tuesday, May 29, 2018 at 6:03:29 PM UTC+3, Nicol B=
olas 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"><br><br=
>On Tuesday, May 29, 2018 at 10:53:45 AM UTC-4, <a>mihailn...@gmail.com</a>=
wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><br>On =
Tuesday, May 29, 2018 at 5:44:34 PM UTC+3, Edward Catmur 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"><br><div><br><div class=3D"gma=
il_quote">On Tue, May 29, 2018 at 3:36 PM, <span dir=3D"ltr"><<a rel=3D=
"nofollow">mihailn...@gmail.com</a>></span> wrote:<br><blockquote class=
=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div dir=3D"ltr"><br><br>On Tuesday, May 29, 2018 at 5:09:43 =
PM UTC+3, Edward Catmur wrote:<blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div =
dir=3D"ltr">...</div></blockquote><div><br></div><div>Question: Why would y=
ou ever want to use=C2=A0<font face=3D"courier new,monospace">[] -> int<=
/font><span> instead of=C2=A0<span></span><font face=3D"courier new,monospa=
ce">std::function_ref<int()> </font><font face=3D"arial,sans-serif">a=
s a parameter?=C2=A0</font></span></div></div></blockquote><div><br></div><=
div>[] -> int is transparent at the call site; std::function_ref<int(=
)> requires the calling code to write a lambda. It is also lighter weigh=
t.</div></div></div></div></blockquote><div><br></div><div>What if the user=
decides to upgrade the call and write a lambda? What if the user wants to =
pass a callable instance variable? Overloads?=C2=A0</div></div></blockquote=
><div><br></div><div>What happens when a user decides to stop using `std::s=
tring` and start trying to pass a `std::vector<char>`? They get a com=
pile error for not providing the thing they were told by the API to provide=
..</div></div></blockquote><div><br></div><div>And that is exactly why we ar=
e moving away from std::string as a param to string_view!=C2=A0</div><div>Y=
ou want a good, general interface. Accepting a lazy arg <i>alone</i> is not=
one. </div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div d=
ir=3D"ltr"><div><br></div><div>How is that any different? You said "gi=
ve me an expression that results in an integer". You instead tries to =
give a lambda. That's not "an expression that results in an intege=
r", so you get a compile error.</div><div><br></div><div>You can turn =
any function-that-results-in-an-<wbr>integer into an expresion-that-results=
-in-an-<wbr>integer simply by calling it in-situ:</div></div></blockquote><=
div>=C2=A0</div><div><br></div><div>And both bind to function_ref hence fun=
ction_ref is the better interface.</div><div><br></div><div>The problem is,=
the user knows the code is late evaluated - he has seen the declaration.=
=C2=A0</div><div>Second, for the user there is no <i>practical</i> differen=
ce b/w "function-that-results-in-an-<wbr>integer" and "expre=
sion-that-results-in-an-<wbr>integer"</div><div><br></div><div>Because=
of this the user <i>will want</i> to pass callables as well.=C2=A0</div><d=
iv><br></div><div>With lazy arg interface <i>alone</i> this will be both cl=
umsy and awkward (to say the least).</div><div>=C2=A0</div><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr"><div><br></div><div><div style=3D"=
background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-styl=
e:solid;border-width:1px"><code><div><span style=3D"color:#000">func</span>=
<span style=3D"color:#660">([]()</span><span style=3D"color:#000"> </span><=
span style=3D"color:#660">-></span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#008">int</span><span style=3D"color:#660">{...}());</sp=
an></div></code></div><br></div><div>That makes it clear to everyone that t=
he function <i>call</i> is the expression being captured, not the function =
itself.<br></div></div></blockquote></div></blockquote><div><br></div><div>=
You are missing the point: lazy parameters is not about=C2=A0 passing calla=
bles to a function, it is about delaying the construction of the parameters=
in order to skip the construction of not needed ones, or allow some Return=
Value Optimizations by knowing the final destination of the object.</div><=
div>If the call site is not transparent to this, then you cannot overload p=
roperly <span style=3D"font-family: courier new, monospace;">operator||</sp=
an> for instance (or <span style=3D"font-family: courier new, monospace;">o=
perator?:</span> if this gets accepted), and makes most use cases harder to=
write for the user for no good reason.</div><div>An "expression-that-=
results-in-an-integer" has no syntax overhead.</div><div><br></div><di=
v>You could argue that an expression is implicitly convertible (without exe=
cuting it) into a std::function_ref, for instance. This would allow you to =
have a real object to play with while allowing transparent call site.</div>=
<div>But this would make the type system clumsy.</div>Consider trying to pa=
ss a <span style=3D"font-family: courier new, monospace;">std::function_ref=
<T()></span> as a lazy parameter to a function that takes any kind of=
input:<br><div style=3D"background-color: rgb(250, 250, 250); border-color=
: rgb(187, 187, 187); border-style: solid; border-width: 1px; overflow-wrap=
: break-word;" class=3D"prettyprint"><code class=3D"prettyprint"><div class=
=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">template</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">class</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">></span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br>T foo</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">std</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">function_ref</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify"><</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify">T</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">()></span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
f</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"> </span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">return</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> f</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">();</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><b=
r>foo</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span style=3D"color: #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: #8=
00;" class=3D"styled-by-prettify">// ok automatic conversion from 1 to std:=
:function<int()>: lazy evaluation</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br><br>foo</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">std</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">function_ref</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify"><</span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">int</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: #008;" class=3D"styled-by-prettify">return</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #066;" class=3D"styled-by-prettify">1</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: #660;" class=
=3D"styled-by-prettify">}))</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-pr=
ettify">// std::function_ref<int()> is copied, not lazy evaluated</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></d=
iv></code></div><br>So expressions implicitly convertible to <span style=3D=
"font-family: courier new, monospace;">std::function_ref</span>: bad idea!<=
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/92a83f13-3f06-43b5-9340-7942c13e0b33%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/92a83f13-3f06-43b5-9340-7942c13e0b33=
%40isocpp.org</a>.<br />
------=_Part_39241_194391813.1527612088665--
------=_Part_39240_336671412.1527612088665--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Tue, 29 May 2018 18:04:59 +0100
Raw View
--0000000000000a1f2e056d5b3cf7
Content-Type: text/plain; charset="UTF-8"
On Tue, May 29, 2018 at 5:12 PM, <mihailnajdenov@gmail.com> wrote:
> On Tuesday, May 29, 2018 at 6:03:29 PM UTC+3, Nicol Bolas wrote:
>>
>> What happens when a user decides to stop using `std::string` and start
>> trying to pass a `std::vector<char>`? They get a compile error for not
>> providing the thing they were told by the API to provide.
>>
>
> And that is exactly why we are moving away from std::string as a param to
> string_view!
> You want a good, general interface. Accepting a lazy arg *alone* is not
> one.
>
std::string_view is strictly better than std::string as a parameter; it has
a smaller footprint than a std::string passed by value, and it requires
less indirection than a std::string passed by reference. In addition, the
relevant template is instantiated a limited number of times: at most once
for basic_string_view<char> per translation unit.
Contra this, std::function_ref must be instantiated once per function type
and its constructor must be instantiated once per callable type - once per
call, if the callables are closures. Its footprint (two pointers) is at
least as large as either a closure type (0-1 pointers, for a
capture-by-reference default) or a lazy parameter (1-2 pointers, depending
on implementation) and requires a closure to be reified which might
otherwise not occur. Its call pointer may result in double-indirection if
not inlined, and bloats the symbol table, particularly if debug symbols are
enabled. Again, if debugging is enabled or if inlining fails, its call
operator pollutes the call stack with irrelevant frames.
>> How is that any different? You said "give me an expression that results
>> in an integer". You instead tries to give a lambda. That's not "an
>> expression that results in an integer", so you get a compile error.
>>
>> You can turn any function-that-results-in-an-integer into an
>> expresion-that-results-in-an-integer simply by calling it in-situ:
>>
>
>
> And both bind to function_ref hence function_ref is the better interface.
>
Using function_ref requires wrapping an expression in a closure - `expr`
becomes at minimum `[&] { return expr; }` or quite possibly `[&]() ->
decltype(auto) { return expr; }` - a large amount of unnecessary
boilerplate. Passing a callable as a lazy parameter requires appending a
pair of parentheses.
> The problem is, the user knows the code is late evaluated - he has seen
> the declaration.
> Second, for the user there is no *practical* difference b/w
> "function-that-results-in-an-integer" and "expresion-that-results-in-an-
> integer"
>
> Because of this the user *will want* to pass callables as well.
>
Why? How likely are they have callables lying around with precisely the
semantics that are required?
> With lazy arg interface *alone* this will be both clumsy and awkward (to
> say the least).
>
Two characters `()` is clumsy and awkward?
>> func([]() -> int{...}());
>>
>> That makes it clear to everyone that the function *call* is the
>> expression being captured, not the function itself.
>>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit https://groups.google.com/a/is
> ocpp.org/d/topic/std-proposals/5oUZysJB4HE/unsubscribe.
> To unsubscribe from this group and all its topics, 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/is
> ocpp.org/d/msgid/std-proposals/4a0155aa-490d-4948-8ade-
> 732c339e1e8d%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/4a0155aa-490d-4948-8ade-732c339e1e8d%40isocpp.org?utm_medium=email&utm_source=footer>
> .
>
--
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/CAJnLdOYTyaMz7LvfMiYod9B%3DKVAWxxy%3DH8uo4reeJee%3DQ4NepA%40mail.gmail.com.
--0000000000000a1f2e056d5b3cf7
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
ue, May 29, 2018 at 5:12 PM, <span dir=3D"ltr"><<a href=3D"mailto:mihai=
lnajdenov@gmail.com" target=3D"_blank">mihailnajdenov@gmail.com</a>></sp=
an> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;=
border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Tuesday, M=
ay 29, 2018 at 6:03:29 PM UTC+3, Nicol Bolas wrote:<blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr"><div>What happens when a user decides to s=
top using `std::string` and start trying to pass a `std::vector<char>=
`? They get a compile error for not providing the thing they were told by t=
he API to provide.</div></div></blockquote><div><br></div><div>And that is =
exactly why we are moving away from std::string as a param to string_view!=
=C2=A0</div><div>You want a good, general interface. Accepting a lazy arg <=
i>alone</i> is not one.</div></div></blockquote><div><br></div><div>std::st=
ring_view is strictly better than std::string as a parameter; it has a smal=
ler footprint than a std::string passed by value, and it requires less indi=
rection than a std::string passed by reference. In addition, the relevant t=
emplate is instantiated a limited number of times: at most once for basic_s=
tring_view<char> per translation unit.</div><div><br></div><div>Contr=
a this, std::function_ref must be instantiated once per function type and i=
ts constructor must be instantiated once per callable type - once per call,=
if the callables are closures. Its footprint (two pointers) is at least as=
large as either a closure type (0-1 pointers, for a capture-by-reference d=
efault) or a lazy parameter (1-2 pointers, depending on implementation) and=
requires a closure to be reified which might otherwise not occur. Its call=
pointer may result in double-indirection if not inlined, and bloats the sy=
mbol table, particularly if debug symbols are enabled. Again, if debugging =
is enabled or if inlining fails, its call operator pollutes the call stack =
with irrelevant frames.</div><div><br></div><blockquote class=3D"gmail_quot=
e" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">=
<div dir=3D"ltr"><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><br></div><div>How is that any different? You said "give me an exp=
ression that results in an integer". You instead tries to give a lambd=
a. That's not "an expression that results in an integer", so =
you get a compile error.</div><div><br></div><div>You can turn any function=
-that-results-in-an-in<wbr>teger into an expresion-that-results-in-an-i<wbr=
>nteger simply by calling it in-situ:</div></div></blockquote><div>=C2=A0</=
div><div><br></div><div>And both bind to function_ref hence function_ref is=
the better interface.</div></div></blockquote><div><br></div><div>Using fu=
nction_ref requires wrapping an expression in a closure - `expr` becomes at=
minimum `[&] { return expr; }` or quite possibly `[&]() -> decl=
type(auto) { return expr; }` - a large amount of unnecessary boilerplate. P=
assing a callable as a lazy parameter requires appending a pair of parenthe=
ses.</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
<div>The problem is, the user knows the code is late evaluated - he has see=
n the declaration.=C2=A0</div><div>Second, for the user there is no <i>prac=
tical</i> difference b/w "function-that-results-in-an-i<wbr>nteger&quo=
t; and "expresion-that-results-in-an-<wbr>integer"</div><div><br>=
</div><div>Because of this the user <i>will want</i> to pass callables as w=
ell.=C2=A0</div></div></blockquote><div><br></div><div>Why? How likely are =
they have callables lying around with precisely the semantics that are requ=
ired?</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"marg=
in:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"=
><div>With lazy arg interface <i>alone</i> this will be both clumsy and awk=
ward (to say the least).</div></div></blockquote><div><br></div><div>Two ch=
aracters `()` is clumsy and awkward?</div><div><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"m=
argin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div=
dir=3D"ltr"><div><br></div><div><div style=3D"background-color:rgb(250,250=
,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px"><c=
ode><div><span style=3D"color:#000">func</span><span style=3D"color:#660">(=
[]()</span><span style=3D"color:#000"> </span><span style=3D"color:#660">-&=
gt;</span><span style=3D"color:#000"> </span><span style=3D"color:#008">int=
</span><span style=3D"color:#660">{...}());</span></div></code></div><br></=
div><div>That makes it clear to everyone that the function <i>call</i> is t=
he expression being captured, not the function itself.<span class=3D"m_6584=
694945396075630HOEnZb"><font color=3D"#888888"><br></font></span></div></di=
v></blockquote></div><span class=3D"m_6584694945396075630HOEnZb"><font colo=
r=3D"#888888">
<p></p>
-- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/unsubscribe" target=3D"_blan=
k">https://groups.google.com/a/is<wbr>ocpp.org/d/topic/std-proposals<wbr>/5=
oUZysJB4HE/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_blank">std-prop=
osals+unsubscribe@isoc<wbr>pp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">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/4a0155aa-490d-4948-8ade-732c339e1e8d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank">=
https://groups.google.com/a/is<wbr>ocpp.org/d/msgid/std-proposals<wbr>/4a01=
55aa-490d-4948-8ade-<wbr>732c339e1e8d%40isocpp.org</a>.<br>
</font></span></blockquote></div><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/CAJnLdOYTyaMz7LvfMiYod9B%3DKVAWxxy%3D=
H8uo4reeJee%3DQ4NepA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdOYTya=
Mz7LvfMiYod9B%3DKVAWxxy%3DH8uo4reeJee%3DQ4NepA%40mail.gmail.com</a>.<br />
--0000000000000a1f2e056d5b3cf7--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 29 May 2018 10:08:46 -0700 (PDT)
Raw View
------=_Part_38932_1344209782.1527613726726
Content-Type: multipart/alternative;
boundary="----=_Part_38933_2007487055.1527613726726"
------=_Part_38933_2007487055.1527613726726
Content-Type: text/plain; charset="UTF-8"
On Tuesday, May 29, 2018 at 12:12:12 PM UTC-4, mihailn...@gmail.com wrote:
>
>
>
> On Tuesday, May 29, 2018 at 6:03:29 PM UTC+3, Nicol Bolas wrote:
>>
>>
>>
>> On Tuesday, May 29, 2018 at 10:53:45 AM UTC-4, mihailn...@gmail.com
>> wrote:
>>>
>>>
>>>
>>> On Tuesday, May 29, 2018 at 5:44:34 PM UTC+3, Edward Catmur wrote:
>>>>
>>>>
>>>>
>>>> On Tue, May 29, 2018 at 3:36 PM, <mihailn...@gmail.com> wrote:
>>>>
>>>>>
>>>>>
>>>>> On Tuesday, May 29, 2018 at 5:09:43 PM UTC+3, Edward Catmur wrote:
>>>>>>
>>>>>> ...
>>>>>>
>>>>>
>>>>> Question: Why would you ever want to use [] -> int instead of std::function_ref<int()>
>>>>> as a parameter?
>>>>>
>>>>
>>>> [] -> int is transparent at the call site; std::function_ref<int()>
>>>> requires the calling code to write a lambda. It is also lighter weight.
>>>>
>>>
>>> What if the user decides to upgrade the call and write a lambda? What if
>>> the user wants to pass a callable instance variable? Overloads?
>>>
>>
>> What happens when a user decides to stop using `std::string` and start
>> trying to pass a `std::vector<char>`? They get a compile error for not
>> providing the thing they were told by the API to provide.
>>
>
> And that is exactly why we are moving away from std::string as a param to
> string_view!
>
`vector<char>` is not convertible to `string_view`, nor *should it be*. If
you want to convert them, then you should do it yourself.
Same goes for functions vs. captured expressions. After all, what happens
if you want to capture an expression that *evaluates to a function*? How do
you tell the difference if a function is automatically turned into a
captured expression?
--
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/39d30b78-f556-40b3-9d11-386b571e2440%40isocpp.org.
------=_Part_38933_2007487055.1527613726726
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, May 29, 2018 at 12:12:12 PM UTC-4, mih=
ailn...@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div d=
ir=3D"ltr"><br><br>On Tuesday, May 29, 2018 at 6:03:29 PM UTC+3, Nicol Bola=
s wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><br>On=
Tuesday, May 29, 2018 at 10:53:45 AM UTC-4, <a>mihailn...@gmail.com</a> wr=
ote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><br>On Tue=
sday, May 29, 2018 at 5:44:34 PM UTC+3, Edward Catmur wrote:<blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc=
solid;padding-left:1ex"><div dir=3D"ltr"><br><div><br><div class=3D"gmail_=
quote">On Tue, May 29, 2018 at 3:36 PM, <span dir=3D"ltr"><<a rel=3D"no=
follow">mihailn...@gmail.com</a>></span> wrote:<br><blockquote class=3D"=
gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-=
left:1ex"><div dir=3D"ltr"><br><br>On Tuesday, May 29, 2018 at 5:09:43 PM U=
TC+3, Edward Catmur 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">...</div></blockquote><div><br></div><div>Question: Why would you =
ever want to use=C2=A0<font face=3D"courier new,monospace">[] -> int</fo=
nt><span> instead of=C2=A0<span></span><font face=3D"courier new,monospace"=
>std::function_ref<int()> </font><font face=3D"arial,sans-serif">as a=
parameter?=C2=A0</font></span></div></div></blockquote><div><br></div><div=
>[] -> int is transparent at the call site; std::function_ref<int()&g=
t; requires the calling code to write a lambda. It is also lighter weight.<=
/div></div></div></div></blockquote><div><br></div><div>What if the user de=
cides to upgrade the call and write a lambda? What if the user wants to pas=
s a callable instance variable? Overloads?=C2=A0</div></div></blockquote><d=
iv><br></div><div>What happens when a user decides to stop using `std::stri=
ng` and start trying to pass a `std::vector<char>`? They get a compil=
e error for not providing the thing they were told by the API to provide.</=
div></div></blockquote><div><br></div><div>And that is exactly why we are m=
oving away from std::string as a param to string_view!=C2=A0</div></div></b=
lockquote><div><br></div><div>`vector<char>` is not convertible to `s=
tring_view`, nor <i>should it be</i>. If you want to convert them, then you=
should do it yourself.</div><div><br></div><div>Same goes for functions vs=
.. captured expressions. After all, what happens if you want to capture an e=
xpression that <i>evaluates to a function</i>? How do you tell the differen=
ce if a function is automatically turned into a captured expression?</div><=
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/39d30b78-f556-40b3-9d11-386b571e2440%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/39d30b78-f556-40b3-9d11-386b571e2440=
%40isocpp.org</a>.<br />
------=_Part_38933_2007487055.1527613726726--
------=_Part_38932_1344209782.1527613726726--
.
Author: mihailnajdenov@gmail.com
Date: Tue, 29 May 2018 10:47:45 -0700 (PDT)
Raw View
------=_Part_39636_777425568.1527616065679
Content-Type: multipart/alternative;
boundary="----=_Part_39637_931066610.1527616065679"
------=_Part_39637_931066610.1527616065679
Content-Type: text/plain; charset="UTF-8"
On Tuesday, May 29, 2018 at 8:05:02 PM UTC+3, Edward Catmur wrote:
>
> On Tue, May 29, 2018 at 5:12 PM, <mihailn...@gmail.com <javascript:>>
> wrote:
>
>> On Tuesday, May 29, 2018 at 6:03:29 PM UTC+3, Nicol Bolas wrote:
>>>
>>> What happens when a user decides to stop using `std::string` and start
>>> trying to pass a `std::vector<char>`? They get a compile error for not
>>> providing the thing they were told by the API to provide.
>>>
>>
>> And that is exactly why we are moving away from std::string as a param to
>> string_view!
>> You want a good, general interface. Accepting a lazy arg *alone* is not
>> one.
>>
>
> std::string_view is strictly better than std::string as a parameter; it
> has a smaller footprint than a std::string passed by value, and it requires
> less indirection than a std::string passed by reference. In addition, the
> relevant template is instantiated a limited number of times: at most once
> for basic_string_view<char> per translation unit.
>
> Contra this, std::function_ref must be instantiated once per function type
> and its constructor must be instantiated once per callable type - once per
> call, if the callables are closures. Its footprint (two pointers) is at
> least as large as either a closure type (0-1 pointers, for a
> capture-by-reference default) or a lazy parameter (1-2 pointers, depending
> on implementation) and requires a closure to be reified which might
> otherwise not occur. Its call pointer may result in double-indirection if
> not inlined, and bloats the symbol table, particularly if debug symbols are
> enabled. Again, if debugging is enabled or if inlining fails, its call
> operator pollutes the call stack with irrelevant frames.
>
>
>>> How is that any different? You said "give me an expression that results
>>> in an integer". You instead tries to give a lambda. That's not "an
>>> expression that results in an integer", so you get a compile error.
>>>
>>> You can turn any function-that-results-in-an-integer into an
>>> expresion-that-results-in-an-integer simply by calling it in-situ:
>>>
>>
>>
>> And both bind to function_ref hence function_ref is the better interface.
>>
>
> Using function_ref requires wrapping an expression in a closure - `expr`
> becomes at minimum `[&] { return expr; }` or quite possibly `[&]() ->
> decltype(auto) { return expr; }` - a large amount of unnecessary
> boilerplate. Passing a callable as a lazy parameter requires appending a
> pair of parentheses.
>
>
>> The problem is, the user knows the code is late evaluated - he has seen
>> the declaration.
>> Second, for the user there is no *practical* difference b/w
>> "function-that-results-in-an-integer" and
>> "expresion-that-results-in-an-integer"
>>
>> Because of this the user *will want* to pass callables as well.
>>
>
> Why? How likely are they have callables lying around with precisely the
> semantics that are required?
>
>
>> With lazy arg interface *alone* this will be both clumsy and awkward (to
>> say the least).
>>
>
> Two characters `()` is clumsy and awkward?
>
Ok, give me a sales pitch. When to choose func_ref and when lazy if I what
to present my class to the world.
On one hand is func_ref which binds to everything but must introduce an
explicit lambda to write code inline
, on the other is lazy, in which inline code is the default, but is single
single expression only and does not bind to anything (inline only).
For me, personally func_ref is the better interface as it is the most
general, but I am obviously missing something (performance aside) as you
all are so exited.
When I will want to use lazy? What are the rules of thumb? What is "the
killer app"?
This is an honest question as I use callables *a lot*, and will gladly find
its place if I can.
>
>
>>> func([]() -> int{...}());
>>>
>>> That makes it clear to everyone that the function *call* is the
>>> expression being captured, not the function itself.
>>>
>> --
>> You received this message because you are subscribed to a topic in the
>> Google Groups "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this topic, visit
>> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/unsubscribe
>> .
>> To unsubscribe from this group and all its topics, send an email to
>> std-proposal...@isocpp.org <javascript:>.
>> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
>> To view this discussion on the web visit
>> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/4a0155aa-490d-4948-8ade-732c339e1e8d%40isocpp.org
>> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/4a0155aa-490d-4948-8ade-732c339e1e8d%40isocpp.org?utm_medium=email&utm_source=footer>
>> .
>>
>
>
--
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/09a17e7a-765a-423f-b17d-f86832914328%40isocpp.org.
------=_Part_39637_931066610.1527616065679
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, May 29, 2018 at 8:05:02 PM UTC+3, Edwa=
rd Catmur wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt=
r"><div><div class=3D"gmail_quote">On Tue, May 29, 2018 at 5:12 PM, <span =
dir=3D"ltr"><<a onmousedown=3D"this.href=3D'javascript:';return =
true;" onclick=3D"this.href=3D'javascript:';return true;" href=3D"j=
avascript:" target=3D"_blank" rel=3D"nofollow" gdf-obfuscated-mailto=3D"3Qz=
Cx5LlBgAJ">mihailn...@gmail.com</a>></span> wrote:<br><blockquote class=
=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div dir=3D"ltr">On Tuesday, May 29, 2018 at 6:03:29 PM UTC+3=
, Nicol Bolas wrote:<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=
"><div>What happens when a user decides to stop using `std::string` and sta=
rt trying to pass a `std::vector<char>`? They get a compile error for=
not providing the thing they were told by the API to provide.</div></div><=
/blockquote><div><br></div><div>And that is exactly why we are moving away =
from std::string as a param to string_view!=C2=A0</div><div>You want a good=
, general interface. Accepting a lazy arg <i>alone</i> is not one.</div></d=
iv></blockquote><div><br></div><div>std::string_view is strictly better tha=
n std::string as a parameter; it has a smaller footprint than a std::string=
passed by value, and it requires less indirection than a std::string passe=
d by reference. In addition, the relevant template is instantiated a limite=
d number of times: at most once for basic_string_view<char> per trans=
lation unit.</div><div><br></div><div>Contra this, std::function_ref must b=
e instantiated once per function type and its constructor must be instantia=
ted once per callable type - once per call, if the callables are closures. =
Its footprint (two pointers) is at least as large as either a closure type =
(0-1 pointers, for a capture-by-reference default) or a lazy parameter (1-2=
pointers, depending on implementation) and requires a closure to be reifie=
d which might otherwise not occur. Its call pointer may result in double-in=
direction if not inlined, and bloats the symbol table, particularly if debu=
g symbols are enabled. Again, if debugging is enabled or if inlining fails,=
its call operator pollutes the call stack with irrelevant frames.</div><di=
v><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc=
solid;padding-left:1ex"><div dir=3D"ltr"><div><br></div><div>How is that a=
ny different? You said "give me an expression that results in an integ=
er". You instead tries to give a lambda. That's not "an expre=
ssion that results in an integer", so you get a compile error.</div><d=
iv><br></div><div>You can turn any function-that-results-in-an-<wbr>integer=
into an expresion-that-results-in-an-<wbr>integer simply by calling it in-=
situ:</div></div></blockquote><div>=C2=A0</div><div><br></div><div>And both=
bind to function_ref hence function_ref is the better interface.</div></di=
v></blockquote><div><br></div><div>Using function_ref requires wrapping an =
expression in a closure - `expr` becomes at minimum `[&] { return expr;=
}` or quite possibly `[&]() -> decltype(auto) { return expr; }` - a=
large amount of unnecessary boilerplate. Passing a callable as a lazy para=
meter requires appending a pair of parentheses.</div><div>=C2=A0</div><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #cc=
c solid;padding-left:1ex"><div dir=3D"ltr"><div>The problem is, the user kn=
ows the code is late evaluated - he has seen the declaration.=C2=A0</div><d=
iv>Second, for the user there is no <i>practical</i> difference b/w "f=
unction-that-results-in-an-<wbr>integer" and "expresion-that-resu=
lts-in-an-<wbr>integer"</div><div><br></div><div>Because of this the u=
ser <i>will want</i> to pass callables as well.=C2=A0</div></div></blockquo=
te><div><br></div><div>Why? How likely are they have callables lying around=
with precisely the semantics that are required?</div><div>=C2=A0</div><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><div>With lazy arg interface <i=
>alone</i> this will be both clumsy and awkward (to say the least).</div></=
div></blockquote><div><br></div><div>Two characters `()` is clumsy and awkw=
ard?</div></div></div></div></blockquote><div><br></div><div><br></div><div=
>Ok, give me a sales pitch. When to choose func_ref and when lazy if I what=
to present my class to the world.=C2=A0</div><div><br></div><div>On one ha=
nd is func_ref which binds to everything but must introduce an explicit lam=
bda to write code inline</div><div>, on the other is lazy, in which inline =
code is the default, but is single single expression only and does not bind=
to anything (inline only).=C2=A0</div><div><br></div><div>For me, personal=
ly func_ref is the better interface as it is the most general, but I am obv=
iously missing something (<span style=3D"display: inline !important; float:=
none; background-color: transparent; color: rgb(34, 34, 34); font-family: =
"Arial","Helvetica",sans-serif; font-size: 13px; font-s=
tyle: normal; font-variant: normal; font-weight: 400; letter-spacing: norma=
l; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; t=
ext-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; w=
ord-spacing: 0px;">performance aside</span>) as you all are so exited.</div=
><div><br></div><div>When I will want to use lazy?=C2=A0<span style=3D"disp=
lay: inline !important; float: none; background-color: transparent; color: =
rgb(34, 34, 34); font-family: "Arial","Helvetica",sans-=
serif; font-size: 13px; font-style: normal; font-variant: normal; font-weig=
ht: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decorat=
ion: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-widt=
h: 0px; white-space: normal; word-spacing: 0px;">What are the rules of thum=
b? What is "the killer app"?=C2=A0</span></div><div><span style=
=3D"display: inline !important; float: none; background-color: transparent;=
color: rgb(34, 34, 34); font-family: "Arial","Helvetica&quo=
t;,sans-serif; font-size: 13px; font-style: normal; font-variant: normal; f=
ont-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text=
-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-str=
oke-width: 0px; white-space: normal; word-spacing: 0px;"><br></span></div><=
div><span style=3D"display: inline !important; float: none; background-colo=
r: transparent; color: rgb(34, 34, 34); font-family: "Arial",&quo=
t;Helvetica",sans-serif; font-size: 13px; font-style: normal; font-var=
iant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-al=
ign: left; text-decoration: none; text-indent: 0px; text-transform: none; -=
webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px;">Thi=
s is an honest question as I use callables <i>a lot</i>, and will gladly fi=
nd its place if I can.=C2=A0</span></div><div><i></i>=C2=A0</div><blockquot=
e 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><div class=3D"gmai=
l_quote"><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0=
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><br></div><div><=
div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187=
);border-style:solid;border-width:1px"><code><div><span style=3D"color:#000=
">func</span><span style=3D"color:#660">([]()</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#660">-></span><span style=3D"color:#00=
0"> </span><span style=3D"color:#008">int</span><span style=3D"color:#660">=
{...}());</span></div></code></div><br></div><div>That makes it clear to ev=
eryone that the function <i>call</i> is the expression being captured, not =
the function itself.<span><font color=3D"#888888"><br></font></span></div><=
/div></blockquote></div><span><font color=3D"#888888">
<p></p>
-- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a onmousedown=3D"this.href=3D'ht=
tps://groups.google.com/a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/unsu=
bscribe';return true;" onclick=3D"this.href=3D'https://groups.googl=
e.com/a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/unsubscribe';retur=
n true;" href=3D"https://groups.google.com/a/isocpp.org/d/topic/std-proposa=
ls/5oUZysJB4HE/unsubscribe" target=3D"_blank" rel=3D"nofollow">https://grou=
ps.google.com/a/<wbr>isocpp.org/d/topic/std-<wbr>proposals/5oUZysJB4HE/<wbr=
>unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a onmo=
usedown=3D"this.href=3D'javascript:';return true;" onclick=3D"this.=
href=3D'javascript:';return true;" href=3D"javascript:" target=3D"_=
blank" rel=3D"nofollow" gdf-obfuscated-mailto=3D"3QzCx5LlBgAJ">std-proposal=
....@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a onmousedown=3D"this.href=3D'jav=
ascript:';return true;" onclick=3D"this.href=3D'javascript:';re=
turn true;" href=3D"javascript:" target=3D"_blank" rel=3D"nofollow" gdf-obf=
uscated-mailto=3D"3QzCx5LlBgAJ">std-pr...@isocpp.org</a>.<br>
To view this discussion on the web visit <a onmousedown=3D"this.href=3D'=
;https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/4a0155aa-490d=
-4948-8ade-732c339e1e8d%40isocpp.org?utm_medium\x3demail\x26utm_source\x3df=
ooter';return true;" onclick=3D"this.href=3D'https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4a0155aa-490d-4948-8ade-732c339e1e8d=
%40isocpp.org?utm_medium\x3demail\x26utm_source\x3dfooter';return true;=
" href=3D"https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/4a01=
55aa-490d-4948-8ade-732c339e1e8d%40isocpp.org?utm_medium=3Demail&utm_so=
urce=3Dfooter" target=3D"_blank" rel=3D"nofollow">https://groups.google.com=
/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/4a0155aa-490d-4948-<wbr>8ade-=
732c339e1e8d%40isocpp.org</a><wbr>.<br>
</font></span></blockquote></div><br></div></div>
</blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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/09a17e7a-765a-423f-b17d-f86832914328%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/09a17e7a-765a-423f-b17d-f86832914328=
%40isocpp.org</a>.<br />
------=_Part_39637_931066610.1527616065679--
------=_Part_39636_777425568.1527616065679--
.
Author: inkwizytoryankes@gmail.com
Date: Tue, 29 May 2018 11:23:21 -0700 (PDT)
Raw View
------=_Part_20904_172680567.1527618201543
Content-Type: multipart/alternative;
boundary="----=_Part_20905_1254740852.1527618201543"
------=_Part_20905_1254740852.1527618201543
Content-Type: text/plain; charset="UTF-8"
On Tuesday, May 29, 2018 at 5:44:22 PM UTC+2, Hyman Rosen wrote:
>
> On Tue, May 29, 2018 at 11:33 AM Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> But I don't like the idea of allowing the user to use `identifier` as if
>> it were a function or functor.
>>
> Or even as if it were an *object*. It should be a completely different
>> order of things, fundamentally
>>
> distinct from anything else in C++. Much like braced-init-lists aren't
>> expressions, captured
>>
> expressions identifiers should not be objects or functions.
>>
>
> "Thing that can be invoked to execute a block of code and get back a
> value"
> is not a completely different order of things. It's a function. Using
> function-call
> syntax therefore makes sense.
>
I agree that it could look as function but I think it should not be
function, it could have even different ABI than normal function.
Another thing is how many times you can call it, image simple case:
foo(bar(baz()));
`foo` have this lazy parameter, then where should be temporary crated by
`baz` stored? and what will happens when you call lazy parameter again?
You already use storage for it. Or lifetime of temporaries in lazy
parameters will be different than normal parameters?
--
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/593791b6-6f47-484e-b3b2-34efb4cf4e41%40isocpp.org.
------=_Part_20905_1254740852.1527618201543
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, May 29, 2018 at 5:44:22 PM UTC+2, Hyma=
n Rosen wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><div class=3D"gmail_quote"><div dir=3D"ltr">On Tue, May 29, 2018 at 11:33 =
AM Nicol Bolas <<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated=
-mailto=3D"l8Ch_SvhBgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'j=
avascript:';return true;" onclick=3D"this.href=3D'javascript:';=
return true;">jmck...@gmail.com</a>> wrote:</div><blockquote class=3D"gm=
ail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr"><div>But I don't like the idea of allowing the=
user to use `identifier` as if it were a function or functor.</div></div><=
/blockquote><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Or even as=
if it were an <i>object</i>. It should be a completely different order of =
things, fundamentally</div></div></blockquote><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr"><div>distinct from anything else in C++. Much like brace=
d-init-lists aren't expressions, captured</div></div></blockquote><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #cc=
c solid;padding-left:1ex"><div dir=3D"ltr"><div>expressions identifiers sho=
uld not be objects or functions.</div></div></blockquote><div><br>=C2=A0&qu=
ot;Thing that can be invoked to execute a block of code and get back a valu=
e"<br>is not a completely different order of things.=C2=A0 It's a =
function.=C2=A0 Using function-call<br>syntax therefore makes sense.</div><=
/div></div></blockquote><div><br></div><div>I agree that it could look as f=
unction but I think it should not be function, it could have even different=
ABI than normal function.</div><div>Another thing is how many times you ca=
n call it, image simple case:</div><div><div style=3D"background-color: rgb=
(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bor=
der-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><code cla=
ss=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #000=
;" class=3D"styled-by-prettify">foo</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">bar</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
baz</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()));</=
span></div></code></div>`foo` have this lazy parameter, then where should b=
e temporary crated by `baz` stored? and what will happens when you call laz=
y parameter again?</div><div>You already use storage for it. Or lifetime of=
temporaries in lazy parameters will be different than normal parameters?<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" 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/593791b6-6f47-484e-b3b2-34efb4cf4e41%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/593791b6-6f47-484e-b3b2-34efb4cf4e41=
%40isocpp.org</a>.<br />
------=_Part_20905_1254740852.1527618201543--
------=_Part_20904_172680567.1527618201543--
.
Author: mihailnajdenov@gmail.com
Date: Tue, 29 May 2018 11:40:33 -0700 (PDT)
Raw View
------=_Part_39632_1266123761.1527619233432
Content-Type: multipart/alternative;
boundary="----=_Part_39633_1620547650.1527619233432"
------=_Part_39633_1620547650.1527619233432
Content-Type: text/plain; charset="UTF-8"
On Tuesday, May 29, 2018 at 9:23:21 PM UTC+3, Marcin Jaczewski wrote:
>
>
>
> On Tuesday, May 29, 2018 at 5:44:22 PM UTC+2, Hyman Rosen wrote:
>>
>> On Tue, May 29, 2018 at 11:33 AM Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>> But I don't like the idea of allowing the user to use `identifier` as if
>>> it were a function or functor.
>>>
>> Or even as if it were an *object*. It should be a completely different
>>> order of things, fundamentally
>>>
>> distinct from anything else in C++. Much like braced-init-lists aren't
>>> expressions, captured
>>>
>> expressions identifiers should not be objects or functions.
>>>
>>
>> "Thing that can be invoked to execute a block of code and get back a
>> value"
>> is not a completely different order of things. It's a function. Using
>> function-call
>> syntax therefore makes sense.
>>
>
> I agree that it could look as function but I think it should not be
> function, it could have even different ABI than normal function.
> Another thing is how many times you can call it, image simple case:
> foo(bar(baz()));
> `foo` have this lazy parameter, then where should be temporary crated by
> `baz` stored? and what will happens when you call lazy parameter again?
> You already use storage for it. Or lifetime of temporaries in lazy
> parameters will be different than normal parameters?
>
everything b/w foo brackets is a single expression. baz is in the same
scope as bar an the call to bar is normal as in []{ bar(baz()); } normal
See one of the post of Florian Lemaitre above for tear down of the process.
--
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/43f466e4-a5ac-4359-b61b-c9c45780941a%40isocpp.org.
------=_Part_39633_1620547650.1527619233432
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, May 29, 2018 at 9:23:21 PM UTC+3, Marc=
in Jaczewski wrote:<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"><br><br>On Tuesday, May 29, 2018 at 5:44:22 PM UTC+2, Hyman Rosen wro=
te:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"g=
mail_quote"><div dir=3D"ltr">On Tue, May 29, 2018 at 11:33 AM Nicol Bolas &=
lt;<a rel=3D"nofollow">jmck...@gmail.com</a>> wrote:</div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;p=
adding-left:1ex"><div dir=3D"ltr"><div>But I don't like the idea of all=
owing the user to use `identifier` as if it were a function or functor.</di=
v></div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin:0 0 =
0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>O=
r even as if it were an <i>object</i>. It should be a completely different =
order of things, fundamentally</div></div></blockquote><blockquote class=3D=
"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding=
-left:1ex"><div dir=3D"ltr"><div>distinct from anything else in C++. Much l=
ike braced-init-lists aren't expressions, captured</div></div></blockqu=
ote><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>expressions identi=
fiers should not be objects or functions.</div></div></blockquote><div><br>=
=C2=A0"Thing that can be invoked to execute a block of code and get ba=
ck a value"<br>is not a completely different order of things.=C2=A0 It=
's a function.=C2=A0 Using function-call<br>syntax therefore makes sens=
e.</div></div></div></blockquote><div><br></div><div>I agree that it could =
look as function but I think it should not be function, it could have even =
different ABI than normal function.</div><div>Another thing is how many tim=
es you can call it, image simple case:</div><div><div style=3D"background-c=
olor:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;bord=
er-width:1px"><code><div><span style=3D"color:#000">foo</span><span style=
=3D"color:#660">(</span><span style=3D"color:#000">bar</span><span style=3D=
"color:#660">(</span><span style=3D"color:#000">baz</span><span style=3D"co=
lor:#660">()));</span></div></code></div>`foo` have this lazy parameter, th=
en where should be temporary crated by `baz` stored? and what will happens =
when you call lazy parameter again?</div><div>You already use storage for i=
t. Or lifetime of temporaries in lazy parameters will be different than nor=
mal parameters?<br></div></div></blockquote><div><br></div><div>=C2=A0every=
thing b/w foo brackets is a single expression. baz is in the same scope as =
bar an the call to bar is normal as in []{ bar(baz()); } normal</div><div>S=
ee one of the post of Florian Lemaitre above for tear down of the process.=
=C2=A0</div><div></div><div><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/43f466e4-a5ac-4359-b61b-c9c45780941a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/43f466e4-a5ac-4359-b61b-c9c45780941a=
%40isocpp.org</a>.<br />
------=_Part_39633_1620547650.1527619233432--
------=_Part_39632_1266123761.1527619233432--
.
Author: inkwizytoryankes@gmail.com
Date: Tue, 29 May 2018 12:14:23 -0700 (PDT)
Raw View
------=_Part_40048_1181789612.1527621263346
Content-Type: multipart/alternative;
boundary="----=_Part_40049_1228749120.1527621263347"
------=_Part_40049_1228749120.1527621263347
Content-Type: text/plain; charset="UTF-8"
On Tuesday, May 29, 2018 at 8:40:33 PM UTC+2, mihailn...@gmail.com wrote:
>
>
>
> On Tuesday, May 29, 2018 at 9:23:21 PM UTC+3, Marcin Jaczewski wrote:
>>
>>
>>
>> On Tuesday, May 29, 2018 at 5:44:22 PM UTC+2, Hyman Rosen wrote:
>>>
>>> On Tue, May 29, 2018 at 11:33 AM Nicol Bolas <jmck...@gmail.com> wrote:
>>>
>>>> But I don't like the idea of allowing the user to use `identifier` as
>>>> if it were a function or functor.
>>>>
>>> Or even as if it were an *object*. It should be a completely different
>>>> order of things, fundamentally
>>>>
>>> distinct from anything else in C++. Much like braced-init-lists aren't
>>>> expressions, captured
>>>>
>>> expressions identifiers should not be objects or functions.
>>>>
>>>
>>> "Thing that can be invoked to execute a block of code and get back a
>>> value"
>>> is not a completely different order of things. It's a function. Using
>>> function-call
>>> syntax therefore makes sense.
>>>
>>
>> I agree that it could look as function but I think it should not be
>> function, it could have even different ABI than normal function.
>> Another thing is how many times you can call it, image simple case:
>> foo(bar(baz()));
>> `foo` have this lazy parameter, then where should be temporary crated by
>> `baz` stored? and what will happens when you call lazy parameter again?
>> You already use storage for it. Or lifetime of temporaries in lazy
>> parameters will be different than normal parameters?
>>
>
> everything b/w foo brackets is a single expression. baz is in the same
> scope as bar an the call to bar is normal as in []{ bar(baz()); } normal
> See one of the post of Florian Lemaitre above for tear down of the
> process.
>
> Ok, but then behavior of `5 && foo(bar())` and `myType{} && foo(bar())`
is different because value returned by `bar` in second case will be
destroyed before whole expression will end.
--
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/ffe29619-a735-4e65-86d5-45ef2ca6d352%40isocpp.org.
------=_Part_40049_1228749120.1527621263347
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, May 29, 2018 at 8:40:33 PM UTC+2, miha=
iln...@gmail.com 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"><br><br>On Tuesday, May 29, 2018 at 9:23:21 PM UTC+3, Marcin Jacz=
ewski 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"><br><b=
r>On Tuesday, May 29, 2018 at 5:44:22 PM UTC+2, Hyman Rosen wrote:<blockquo=
te 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"><div class=3D"gmail_quote">=
<div dir=3D"ltr">On Tue, May 29, 2018 at 11:33 AM Nicol Bolas <<a rel=3D=
"nofollow">jmck...@gmail.com</a>> wrote:</div><blockquote class=3D"gmail=
_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:=
1ex"><div dir=3D"ltr"><div>But I don't like the idea of allowing the us=
er to use `identifier` as if it were a function or functor.</div></div></bl=
ockquote><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Or even as if=
it were an <i>object</i>. It should be a completely different order of thi=
ngs, fundamentally</div></div></blockquote><blockquote class=3D"gmail_quote=
" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><=
div dir=3D"ltr"><div>distinct from anything else in C++. Much like braced-i=
nit-lists aren't expressions, captured</div></div></blockquote><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div>expressions identifiers should=
not be objects or functions.</div></div></blockquote><div><br>=C2=A0"=
Thing that can be invoked to execute a block of code and get back a value&q=
uot;<br>is not a completely different order of things.=C2=A0 It's a fun=
ction.=C2=A0 Using function-call<br>syntax therefore makes sense.</div></di=
v></div></blockquote><div><br></div><div>I agree that it could look as func=
tion but I think it should not be function, it could have even different AB=
I than normal function.</div><div>Another thing is how many times you can c=
all it, image simple case:</div><div><div style=3D"background-color:rgb(250=
,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px=
"><code><div><span style=3D"color:#000">foo</span><span style=3D"color:#660=
">(</span><span style=3D"color:#000">bar</span><span style=3D"color:#660">(=
</span><span style=3D"color:#000">baz</span><span style=3D"color:#660">()))=
;</span></div></code></div>`foo` have this lazy parameter, then where shoul=
d be temporary crated by `baz` stored? and what will happens when you call =
lazy parameter again?</div><div>You already use storage for it. Or lifetime=
of temporaries in lazy parameters will be different than normal parameters=
?<br></div></div></blockquote><div><br></div><div>=C2=A0everything b/w foo =
brackets is a single expression. baz is in the same scope as bar an the cal=
l to bar is normal as in []{ bar(baz()); } normal</div><div>See one of the =
post of Florian Lemaitre above for tear down of the process.=C2=A0</div><di=
v></div><div><br></div></div></blockquote><div>=C2=A0Ok, but then behavior =
of `5 && foo(bar())` and `myType{} && foo(bar())` is differ=
ent because value returned by `bar` in second case will be destroyed before=
whole expression will end.<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/ffe29619-a735-4e65-86d5-45ef2ca6d352%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/ffe29619-a735-4e65-86d5-45ef2ca6d352=
%40isocpp.org</a>.<br />
------=_Part_40049_1228749120.1527621263347--
------=_Part_40048_1181789612.1527621263346--
.
Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Tue, 29 May 2018 12:20:46 -0700 (PDT)
Raw View
------=_Part_21687_2126163098.1527621647008
Content-Type: multipart/alternative;
boundary="----=_Part_21688_1712582746.1527621647008"
------=_Part_21688_1712582746.1527621647008
Content-Type: text/plain; charset="UTF-8"
There is a huge difference between passing a callable as parameter (for
instance as a std::function) and calling by lazy: A functor will be called
each time, producing its value, while the lazy is evaluated at most once,
but maybe never. This means that there has to be a flag indicating whether
the evaluation of the parameter was done. This flag must be created and
pre-cleared by the caller to allow for lazy forwarding. I don't see how the
called function could handle this as it doesn't know if the caller created
the flag or just passed forwarded by lazy from its caller.
Note that even for types without constructor there must be a flag as the
function to be called to evaluate the lazy parameter may be arbitrarily
complex, including having side effects and requiring construction of
temporaries. These temporareis, at least in the case of a by reference
parameter type, will have to live until the outermost function getting the
lazy parameter returns. Obviously only the caller knows the nature of the
expression so only it can destroy the temporaries (and the returned value)
in case the callee actually evaluated it.
Thus it seems that for each lazy parameter the caller must push a pointer
to a "lazy block" containing the flag, the function pointer and the
resulting data. This lazy block is created on the stack before calling the
function. In case the function forwards the lazy parameter lazily it just
passes the pointer it was given. When all of this returns the ultimate
caller checks the flag to see if it needs to destroy the value and any
temporaries.
Exception handling could be interesting to implement, but should not be
intractable as we have the flag to check. If there is an exception in the
expression itself it unwinds what it did so far and does not set the flag.
The caller responsible for destruction must of course check the flag also
in an unwinding situation and that seems to be just about it.
Given the fact that evaluation occurs just once I am suspicious whether the
operator() is really appropriate, it does indicate that evaluation occurs
each time. I would argue that just like for by reference vs. by value
parameters we will get used to not having to annotate the parameter usages.
It would be reasonable to let the "evaluation function" be responsible for
the flag checking but it is not possible to just pass the function pointer
as has been indicated in this thread as the lazy forwarding prevents the
stack offset from being knowable when the function gets called. Well maybe
some kind of thunk could be introduced to add an offset to the stack
pointer for each forwarding level but that would be an ABI definition
issue, not a language issue.
--
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/b8b98c77-237c-4fb3-9ccb-030d8d0b7755%40isocpp.org.
------=_Part_21688_1712582746.1527621647008
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">There is a huge difference between passing a callable as p=
arameter (for instance as a std::function) and calling by lazy: A functor w=
ill be called each time, producing its value, while the lazy is evaluated a=
t most once, but maybe never. This means that there has to be a flag indica=
ting whether the evaluation of the parameter was done. This flag must be cr=
eated and pre-cleared by the caller to allow for lazy forwarding. I don'=
;t see how the called function could handle this as it doesn't know if =
the caller created the flag or just passed forwarded by lazy from its calle=
r.<div><br></div><div>Note that even for types without constructor there mu=
st be a flag as the function to be called to evaluate the lazy parameter ma=
y be arbitrarily complex, including having side effects and requiring const=
ruction of temporaries. These temporareis, at least in the case of a by ref=
erence parameter type, will have to live until the outermost function getti=
ng the lazy parameter returns. Obviously only the caller knows the nature o=
f the expression so only it can destroy the temporaries (and the returned v=
alue) in case the callee actually evaluated it.</div><div><br></div><div>Th=
us it seems that for each lazy parameter the caller must push a pointer to =
a "lazy block" containing the flag, the function pointer and the =
resulting data. This lazy block is created on the stack before calling the =
function. In case the function forwards the lazy parameter lazily it just p=
asses the pointer it was given. When all of this returns the ultimate calle=
r checks the flag to see if it needs to destroy the value and any temporari=
es.</div><div><br></div><div>Exception handling could be interesting to imp=
lement, but should not be intractable as we have the flag to check. If ther=
e is an exception in the expression itself it unwinds what it did so far an=
d does not set the flag. The caller responsible for destruction must of cou=
rse check the flag also in an unwinding situation and that seems to be just=
about it.</div><div><br></div><div>Given the fact that evaluation occurs j=
ust once I am suspicious whether the operator() is really appropriate, it d=
oes indicate that evaluation occurs each time. I would argue that just like=
for by reference vs. by value parameters we will get used to not having to=
annotate the parameter usages.</div><div><br></div><div>It would be reason=
able to let the "evaluation function" be responsible for the flag=
checking but it is not possible to just pass the function pointer as has b=
een indicated in this thread as the lazy forwarding prevents the stack offs=
et from being knowable when the function gets called. Well maybe some kind =
of thunk could be introduced to add an offset to the stack pointer for each=
forwarding level but that would be an ABI definition issue, not a language=
issue.</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/b8b98c77-237c-4fb3-9ccb-030d8d0b7755%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b8b98c77-237c-4fb3-9ccb-030d8d0b7755=
%40isocpp.org</a>.<br />
------=_Part_21688_1712582746.1527621647008--
------=_Part_21687_2126163098.1527621647008--
.
Author: florian.csdt@gmail.com
Date: Tue, 29 May 2018 13:20:14 -0700 (PDT)
Raw View
------=_Part_40607_911054084.1527625214764
Content-Type: multipart/alternative;
boundary="----=_Part_40608_1803220413.1527625214765"
------=_Part_40608_1803220413.1527625214765
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le mardi 29 mai 2018 21:20:47 UTC+2, Bengt Gustafsson a =C3=A9crit :
>
> There is a huge difference between passing a callable as parameter (for=
=20
> instance as a std::function) and calling by lazy: A functor will be calle=
d=20
> each time, producing its value, while the lazy is evaluated at most once,=
=20
> but maybe never. This means that there has to be a flag indicating whethe=
r=20
> the evaluation of the parameter was done. This flag must be created and=
=20
> pre-cleared by the caller to allow for lazy forwarding. I don't see how t=
he=20
> called function could handle this as it doesn't know if the caller create=
d=20
> the flag or just passed forwarded by lazy from its caller.
>
> Note that even for types without constructor there must be a flag as the=
=20
> function to be called to evaluate the lazy parameter may be arbitrarily=
=20
> complex, including having side effects and requiring construction of=20
> temporaries. These temporareis, at least in the case of a by reference=20
> parameter type, will have to live until the outermost function getting th=
e=20
> lazy parameter returns. Obviously only the caller knows the nature of the=
=20
> expression so only it can destroy the temporaries (and the returned value=
)=20
> in case the callee actually evaluated it.
>
> Thus it seems that for each lazy parameter the caller must push a pointer=
=20
> to a "lazy block" containing the flag, the function pointer and the=20
> resulting data. This lazy block is created on the stack before calling th=
e=20
> function. In case the function forwards the lazy parameter lazily it just=
=20
> passes the pointer it was given. When all of this returns the ultimate=20
> caller checks the flag to see if it needs to destroy the value and any=20
> temporaries.
>
> Exception handling could be interesting to implement, but should not be=
=20
> intractable as we have the flag to check. If there is an exception in the=
=20
> expression itself it unwinds what it did so far and does not set the flag=
..=20
> The caller responsible for destruction must of course check the flag also=
=20
> in an unwinding situation and that seems to be just about it.
>
> Given the fact that evaluation occurs just once I am suspicious whether=
=20
> the operator() is really appropriate, it does indicate that evaluation=20
> occurs each time. I would argue that just like for by reference vs. by=20
> value parameters we will get used to not having to annotate the parameter=
=20
> usages.
>
> It would be reasonable to let the "evaluation function" be responsible fo=
r=20
> the flag checking but it is not possible to just pass the function pointe=
r=20
> as has been indicated in this thread as the lazy forwarding prevents the=
=20
> stack offset from being knowable when the function gets called. Well mayb=
e=20
> some kind of thunk could be introduced to add an offset to the stack=20
> pointer for each forwarding level but that would be an ABI definition=20
> issue, not a language issue.
>
The "evaluation function" needs to access the stack frame (or related) of=
=20
the caller anyway, so adding the flag here and let the "evaluation=20
function" set it seems reasonable.
I like the idea to put temporaries into the caller stack frame instead of=
=20
the "evaluation function" stack frame. If all temporaries have a trivial=20
destructor, you could even say that there is no flag for its destruction.
If we want to optimize lazy parameter forwarding, we need to pass the stack=
=20
frame (or related) from the caller for each lazy parameter.
Otherwise, we could pass the stack frame pointer once to the callee, and=20
recreate a new "evaluation function" to forward a lazy parameter that could=
=20
just tail call the previous one.
You could even say that you don't need to pass the stack frame explicitly,=
=20
and let the callee retrieve it with the equivalent to=20
__builtin_frame_address(1).
Of course, this is an ABI and an optimization problem, not a language one=
=20
as Bengt said.
--=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/cf5d0a50-08a9-46a2-bad6-4afa76965306%40isocpp.or=
g.
------=_Part_40608_1803220413.1527625214765
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le mardi 29 mai 2018 21:20:47 UTC+2, Bengt Gustafs=
son a =C3=A9crit=C2=A0:<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">There is a huge difference between passing a callable as paramete=
r (for instance as a std::function) and calling by lazy: A functor will be =
called each time, producing its value, while the lazy is evaluated at most =
once, but maybe never. This means that there has to be a flag indicating wh=
ether the evaluation of the parameter was done. This flag must be created a=
nd pre-cleared by the caller to allow for lazy forwarding. I don't see =
how the called function could handle this as it doesn't know if the cal=
ler created the flag or just passed forwarded by lazy from its caller.<div>=
<br></div><div>Note that even for types without constructor there must be a=
flag as the function to be called to evaluate the lazy parameter may be ar=
bitrarily complex, including having side effects and requiring construction=
of temporaries. These temporareis, at least in the case of a by reference =
parameter type, will have to live until the outermost function getting the =
lazy parameter returns. Obviously only the caller knows the nature of the e=
xpression so only it can destroy the temporaries (and the returned value) i=
n case the callee actually evaluated it.</div><div><br></div><div>Thus it s=
eems that for each lazy parameter the caller must push a pointer to a "=
;lazy block" containing the flag, the function pointer and the resulti=
ng data. This lazy block is created on the stack before calling the functio=
n. In case the function forwards the lazy parameter lazily it just passes t=
he pointer it was given. When all of this returns the ultimate caller check=
s the flag to see if it needs to destroy the value and any temporaries.</di=
v><div><br></div><div>Exception handling could be interesting to implement,=
but should not be intractable as we have the flag to check. If there is an=
exception in the expression itself it unwinds what it did so far and does =
not set the flag. The caller responsible for destruction must of course che=
ck the flag also in an unwinding situation and that seems to be just about =
it.</div><div><br></div><div>Given the fact that evaluation occurs just onc=
e I am suspicious whether the operator() is really appropriate, it does ind=
icate that evaluation occurs each time. I would argue that just like for by=
reference vs. by value parameters we will get used to not having to annota=
te the parameter usages.</div><div><br></div><div>It would be reasonable to=
let the "evaluation function" be responsible for the flag checki=
ng but it is not possible to just pass the function pointer as has been ind=
icated in this thread as the lazy forwarding prevents the stack offset from=
being knowable when the function gets called. Well maybe some kind of thun=
k could be introduced to add an offset to the stack pointer for each forwar=
ding level but that would be an ABI definition issue, not a language issue.=
</div></div></blockquote><div><br></div><div>=C2=A0The "evaluation fun=
ction" needs to access the stack frame (or related) of the caller anyw=
ay, so adding the flag here and let the "evaluation function" set=
it seems reasonable.</div><div><br></div><div>I like the idea to put tempo=
raries into the caller stack frame instead of the "evaluation function=
" stack frame. If all temporaries have a trivial destructor, you could=
even say that there is no flag for its destruction.</div><div><br></div><d=
iv>If we want to optimize lazy parameter forwarding, we need to pass the st=
ack frame (or related) from the caller for each lazy parameter.</div><div>O=
therwise, we could pass the stack frame pointer once to the callee, and rec=
reate a new "evaluation function" to forward a lazy parameter tha=
t could just tail call the previous one.</div><div>You could even say that =
you don't need to pass the stack frame explicitly, and let the callee r=
etrieve it with the equivalent to <span style=3D"font-family: courier new, =
monospace;">__builtin_frame_address(1)</span>.</div><div>Of course, this is=
an ABI and an optimization problem, not a language one as Bengt said.<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/cf5d0a50-08a9-46a2-bad6-4afa76965306%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/cf5d0a50-08a9-46a2-bad6-4afa76965306=
%40isocpp.org</a>.<br />
------=_Part_40608_1803220413.1527625214765--
------=_Part_40607_911054084.1527625214764--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 29 May 2018 13:21:21 -0700 (PDT)
Raw View
------=_Part_34603_303903083.1527625281234
Content-Type: multipart/alternative;
boundary="----=_Part_34604_1439211335.1527625281235"
------=_Part_34604_1439211335.1527625281235
Content-Type: text/plain; charset="UTF-8"
On Tuesday, May 29, 2018 at 1:47:45 PM UTC-4, mihailn...@gmail.com wrote:
>
> Ok, give me a sales pitch. When to choose func_ref and when lazy if I what
> to present my class to the world.
>
Stop thinking about what is going on literally between the caller and
callee, and focus on the meaning of the API. You use lazy evaluation if you
want a function to capture an expression. You use function_ref if you want
a function to call a given function.
It's *that simple*.
`std::sort` does not take an expression to be evaluated; it takes a
function to be called. A callback system does not take an expression to be
evaluated; it takes a function to be called at the designated time. And so
forth.
By contrast, a lazy `operator&&` does not take a function to be called; it
takes an expression to be conditionally evaluated. That's what `&&` does;
it acts on two expressions. The person who gives you those expressions
thinks of them as *expressions*, not functions that evaluate to a value.
`lazy_emplace` does not take a function which returns `T`; it takes an
expression whose evaluation ultimately generates a prvalue of type `T`,
which can be shoved into the container. Indeed, in the latter case, we
could declare that a braced-init-list can be used in such an expression
capture (as long as the expression capture's type is explicitly stated),
thus allowing you to do `vector::lazy_emplace({value1, value2})`. Or even
with designated initializers for aggregates: `lazy_emplace({.x = value1, .y
= value2})`. The compiler has enough information to know what's going on,
all without having to mention the type redundantly at the cite of the call.
I cannot conceive of an interface where you would confuse one with the
other. Where you want to take something that is either a function to be
called or an expression to be evaluated. In the mind of the person writing
the API, there is a clear idea of how the function will be used, and to me,
it's always one or the other.
On one hand is func_ref which binds to everything but must introduce an
> explicit lambda to write code inline
> , on the other is lazy, in which inline code is the default, but is single
> single expression only and does not bind to anything (inline only).
>
> For me, personally func_ref is the better interface as it is the most
> general, but I am obviously missing something (performance aside) as you
> all are so exited.
>
> When I will want to use lazy? What are the rules of thumb? What is "the
> killer app"?
>
The two examples I gave above are the "killer app". Transparent lazy
evaluation equivalent to C++'s `&&` and `||` behavior, and the ability to
have `lazy_emplace` work. Neither of these cases are things for which
passing a function is the natural interface.
The rule of thumb is that you use a lazy expression when it makes sense
based on what you're doing. `lazy_emplace` does it because it is the most
natural way to make it work. The natural low-level user code is:
new(container.get_mem_for_new_item()) auto(expr);
So we invert that by having `container.lazy_emplace` apply `expr`
internally. Same thing, just done without having to expose the user to the
low-level guts. And since `expr` could throw exceptions, those now happen
within the purview of `container`'s member functions, which can abort the
object creation properly.
This is an honest question as I use callables *a lot*, and will gladly find
> its place if I can.
>
>
--
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/fece72a0-4000-4672-a659-cfdb079f0f9e%40isocpp.org.
------=_Part_34604_1439211335.1527625281235
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, May 29, 2018 at 1:47:45 PM UTC-4, mihailn...@g=
mail.com 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=
"><div></div><div>Ok, give me a sales pitch. When to choose func_ref and wh=
en lazy if I what to present my class to the world.=C2=A0</div></div></bloc=
kquote><div><br></div><div>Stop thinking about what is going on literally b=
etween the caller and callee, and focus on the meaning of the API. You use =
lazy evaluation if you want a function to capture an expression. You use fu=
nction_ref if you want a function to call a given function.</div><div><br><=
/div><div>It's <i>that simple</i>.<br></div><div><br></div><div></div><=
div>`std::sort` does not take an expression to be evaluated; it takes a fun=
ction to be called. A callback system does not take an expression to be eva=
luated; it takes a function to be called at the designated time. And so for=
th.</div><div><br></div><div>By contrast, a lazy `operator&&` does =
not take a function to be called; it takes an expression to be conditionall=
y evaluated. That's what `&&` does; it acts on two expressions.=
The person who gives you those expressions thinks of them as <i>expression=
s</i>, not functions that evaluate to a value.<br></div><div><br></div><div=
>`lazy_emplace` does not take a function which returns `T`; it takes an exp=
ression whose evaluation ultimately generates a prvalue of type `T`, which =
can be shoved into the container. Indeed, in the latter case, we could decl=
are that a braced-init-list can be used in such an expression capture (as l=
ong as the expression capture's type is explicitly stated), thus allowi=
ng you to do `vector::lazy_emplace({value1, value2})`. Or even with designa=
ted initializers for aggregates: `lazy_emplace({.x =3D value1, .y =3D value=
2})`. The compiler has enough information to know what's going on, all =
without having to mention the type redundantly at the cite of the call.</di=
v><div><br></div><div>I cannot conceive of an interface where you would con=
fuse one with the other. Where you want to take something that is either a =
function to be called or an expression to be evaluated. In the mind of the =
person writing the API, there is a clear idea of how the function will be u=
sed, and to me, it's always one or the other.<br></div><div><br></div><=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><di=
v>On one hand is func_ref which binds to everything but must introduce an e=
xplicit lambda to write code inline</div><div>, on the other is lazy, in wh=
ich inline code is the default, but is single single expression only and do=
es not bind to anything (inline only).=C2=A0</div><div><br></div><div>For m=
e, personally func_ref is the better interface as it is the most general, b=
ut I am obviously missing something (<span style=3D"display:inline!importan=
t;float:none;background-color:transparent;color:rgb(34,34,34);font-family:&=
quot;Arial","Helvetica",sans-serif;font-size:13px;font-style=
:normal;font-variant:normal;font-weight:400;letter-spacing:normal;text-alig=
n:left;text-decoration:none;text-indent:0px;text-transform:none;white-space=
:normal;word-spacing:0px">performance aside</span>) as you all are so exite=
d.</div><div><br></div><div>When I will want to use lazy?=C2=A0<span style=
=3D"display:inline!important;float:none;background-color:transparent;color:=
rgb(34,34,34);font-family:"Arial","Helvetica",sans-seri=
f;font-size:13px;font-style:normal;font-variant:normal;font-weight:400;lett=
er-spacing:normal;text-align:left;text-decoration:none;text-indent:0px;text=
-transform:none;white-space:normal;word-spacing:0px">What are the rules of =
thumb? What is "the killer app"?</span></div></div></blockquote><=
div><br></div><div>The two examples I gave above are the "killer app&q=
uot;. Transparent lazy evaluation equivalent to C++'s `&&` and =
`||` behavior, and the ability to have `lazy_emplace` work. Neither of thes=
e cases are things for which passing a function is the natural interface.</=
div><div><br></div><div>The rule of thumb is that you use a lazy expression=
when it makes sense based on what you're doing. `lazy_emplace` does it=
because it is the most natural way to make it work. The natural low-level =
user code is:</div><div><br></div><div><div style=3D"background-color: rgb(=
250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bord=
er-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><code clas=
s=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;=
" class=3D"styled-by-prettify">new</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">container</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">get_mem_for_new_item</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">())</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">a=
uto</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">expr</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">);</span></div></code>=
</div><br></div><div></div><div>So we invert that by having `container.lazy=
_emplace` apply `expr` internally. Same thing, just done without having to =
expose the user to the low-level guts. And since `expr` could throw excepti=
ons, those now happen within the purview of `container`'s member functi=
ons, which can abort the object creation properly.<br></div><div><br></div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><span st=
yle=3D"display:inline!important;float:none;background-color:transparent;col=
or:rgb(34,34,34);font-family:"Arial","Helvetica",sans-s=
erif;font-size:13px;font-style:normal;font-variant:normal;font-weight:400;l=
etter-spacing:normal;text-align:left;text-decoration:none;text-indent:0px;t=
ext-transform:none;white-space:normal;word-spacing:0px"></span></div><div><=
span style=3D"display:inline!important;float:none;background-color:transpar=
ent;color:rgb(34,34,34);font-family:"Arial","Helvetica"=
,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weigh=
t:400;letter-spacing:normal;text-align:left;text-decoration:none;text-inden=
t:0px;text-transform:none;white-space:normal;word-spacing:0px">This is an h=
onest question as I use callables <i>a lot</i>, and will gladly find its pl=
ace if I can.=C2=A0</span></div><div><br></div></div></blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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/fece72a0-4000-4672-a659-cfdb079f0f9e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/fece72a0-4000-4672-a659-cfdb079f0f9e=
%40isocpp.org</a>.<br />
------=_Part_34604_1439211335.1527625281235--
------=_Part_34603_303903083.1527625281234--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 29 May 2018 13:25:16 -0700 (PDT)
Raw View
------=_Part_17312_748233345.1527625516557
Content-Type: multipart/alternative;
boundary="----=_Part_17313_1663059352.1527625516557"
------=_Part_17313_1663059352.1527625516557
Content-Type: text/plain; charset="UTF-8"
On Tuesday, May 29, 2018 at 4:21:21 PM UTC-4, Nicol Bolas wrote:
>
> On Tuesday, May 29, 2018 at 1:47:45 PM UTC-4, mihailn...@gmail.com wrote:
>>
>> On one hand is func_ref which binds to everything but must introduce an
>> explicit lambda to write code inline
>> , on the other is lazy, in which inline code is the default, but is
>> single single expression only and does not bind to anything (inline only).
>>
>> For me, personally func_ref is the better interface as it is the most
>> general, but I am obviously missing something (performance aside) as you
>> all are so exited.
>>
>> When I will want to use lazy? What are the rules of thumb? What is "the
>> killer app"?
>>
>
> The two examples I gave above are the "killer app". Transparent lazy
> evaluation equivalent to C++'s `&&` and `||` behavior, and the ability to
> have `lazy_emplace` work. Neither of these cases are things for which
> passing a function is the natural interface.
>
> The rule of thumb is that you use a lazy expression when it makes sense
> based on what you're doing. `lazy_emplace` does it because it is the most
> natural way to make it work. The natural low-level user code is:
>
> new(container.get_mem_for_new_item()) auto(expr);
>
> So we invert that by having `container.lazy_emplace` apply `expr`
> internally. Same thing, just done without having to expose the user to the
> low-level guts. And since `expr` could throw exceptions, those now happen
> within the purview of `container`'s member functions, which can abort the
> object creation properly.
>
Some other rules of thumb:
1. You can't affect how lazy expressions evaluate. That is, you can't give
them values; they are simply a thing that generates a value. That's another
reason `std::sort` and most algorithms wouldn't use them.
2. You can't evaluate them more than once. UB ought to result if you try.
3. You can't pass a lazy expression outside of your call stack. Nor can you
return one.
So if you ever need to do any of these things, you are clearly using the
wrong tool.
--
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/3eae7705-ff85-4282-821f-4850c0b1e377%40isocpp.org.
------=_Part_17313_1663059352.1527625516557
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, May 29, 2018 at 4:21:21 PM UTC-4, Nicol Bolas =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On Tues=
day, May 29, 2018 at 1:47:45 PM UTC-4, <a>mihailn...@gmail.com</a> wrote:<b=
lockquote 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></div><div>On o=
ne hand is func_ref which binds to everything but must introduce an explici=
t lambda to write code inline</div><div>, on the other is lazy, in which in=
line code is the default, but is single single expression only and does not=
bind to anything (inline only).=C2=A0</div><div><br></div><div>For me, per=
sonally func_ref is the better interface as it is the most general, but I a=
m obviously missing something (<span style=3D"display:inline!important;floa=
t:none;background-color:transparent;color:rgb(34,34,34);font-family:"A=
rial","Helvetica",sans-serif;font-size:13px;font-style:norma=
l;font-variant:normal;font-weight:400;letter-spacing:normal;text-align:left=
;text-decoration:none;text-indent:0px;text-transform:none;white-space:norma=
l;word-spacing:0px">performance aside</span>) as you all are so exited.</di=
v><div><br></div><div>When I will want to use lazy?=C2=A0<span style=3D"dis=
play:inline!important;float:none;background-color:transparent;color:rgb(34,=
34,34);font-family:"Arial","Helvetica",sans-serif;font-=
size:13px;font-style:normal;font-variant:normal;font-weight:400;letter-spac=
ing:normal;text-align:left;text-decoration:none;text-indent:0px;text-transf=
orm:none;white-space:normal;word-spacing:0px">What are the rules of thumb? =
What is "the killer app"?</span></div></div></blockquote><div><br=
></div><div>The two examples I gave above are the "killer app". T=
ransparent lazy evaluation equivalent to C++'s `&&` and `||` be=
havior, and the ability to have `lazy_emplace` work. Neither of these cases=
are things for which passing a function is the natural interface.</div><di=
v><br></div><div>The rule of thumb is that you use a lazy expression when i=
t makes sense based on what you're doing. `lazy_emplace` does it becaus=
e it is the most natural way to make it work. The natural low-level user co=
de is:</div><div><br></div><div><div style=3D"background-color:rgb(250,250,=
250);border-color:rgb(187,187,187);border-style:solid;border-width:1px"><co=
de><div><span style=3D"color:#008">new</span><span style=3D"color:#660">(</=
span><span style=3D"color:#000">container</span><span style=3D"color:#660">=
..</span><span style=3D"color:#000">get_mem_for_new_<wbr>item</span><span st=
yle=3D"color:#660">())</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">auto</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">expr</span><span style=3D"color:#660">);</span></div></code=
></div><br></div><div></div><div>So we invert that by having `container.laz=
y_emplace` apply `expr` internally. Same thing, just done without having to=
expose the user to the low-level guts. And since `expr` could throw except=
ions, those now happen within the purview of `container`'s member funct=
ions, which can abort the object creation properly.<br></div></div></blockq=
uote><div><br></div><div>Some other rules of thumb:</div><div><br></div><di=
v>1. You can't affect how lazy expressions evaluate. That is, you can&#=
39;t give them values; they are simply a thing that generates a value. That=
's another reason `std::sort` and most algorithms wouldn't use them=
..<br></div><div><br></div><div>2. You can't evaluate them more than onc=
e. UB ought to result if you try.</div><div><br></div><div>3. You can't=
pass a lazy expression outside of your call stack. Nor can you return one.=
<br></div><div><br></div><div>So if you ever need to do any of these things=
, you are clearly using the wrong tool.</div><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/3eae7705-ff85-4282-821f-4850c0b1e377%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/3eae7705-ff85-4282-821f-4850c0b1e377=
%40isocpp.org</a>.<br />
------=_Part_17313_1663059352.1527625516557--
------=_Part_17312_748233345.1527625516557--
.
Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Tue, 29 May 2018 15:03:11 -0700 (PDT)
Raw View
------=_Part_41376_1927949359.1527631392055
Content-Type: multipart/alternative;
boundary="----=_Part_41377_1163352758.1527631392055"
------=_Part_41377_1163352758.1527631392055
Content-Type: text/plain; charset="UTF-8"
@florian: Yes, good point: The fact that you don't need a "already
evaluated" flag for simple expressions clearly points to the fact that the
caller side should handle the flag, i.e. the callee should just call the
function in case it needs the value. The function can elect to use a flag
or re-evalutate if it can figure out that runtime cost is low, no side
effects occur and no temporary destructors to call. Using thunks to adjust
stack frame offsets is probably wise as it is going to be fairly rare that
forwarding occurs (especially in multiple levels).
@Nicol: Prohibiting using a lazy parameter more than once seems overly
restrictive and very error prone, especially if no diagnostic is required.
Furthermore the caller must keep track of whether the function was called
anyway to handle temporary destruction properly.
Den tisdag 29 maj 2018 kl. 22:25:16 UTC+2 skrev Nicol Bolas:
>
> On Tuesday, May 29, 2018 at 4:21:21 PM UTC-4, Nicol Bolas wrote:
>>
>> On Tuesday, May 29, 2018 at 1:47:45 PM UTC-4, mihailn...@gmail.com wrote:
>>>
>>> On one hand is func_ref which binds to everything but must introduce an
>>> explicit lambda to write code inline
>>> , on the other is lazy, in which inline code is the default, but is
>>> single single expression only and does not bind to anything (inline only).
>>>
>>> For me, personally func_ref is the better interface as it is the most
>>> general, but I am obviously missing something (performance aside) as
>>> you all are so exited.
>>>
>>> When I will want to use lazy? What are the rules of thumb? What is "the
>>> killer app"?
>>>
>>
>> The two examples I gave above are the "killer app". Transparent lazy
>> evaluation equivalent to C++'s `&&` and `||` behavior, and the ability to
>> have `lazy_emplace` work. Neither of these cases are things for which
>> passing a function is the natural interface.
>>
>> The rule of thumb is that you use a lazy expression when it makes sense
>> based on what you're doing. `lazy_emplace` does it because it is the most
>> natural way to make it work. The natural low-level user code is:
>>
>> new(container.get_mem_for_new_item()) auto(expr);
>>
>> So we invert that by having `container.lazy_emplace` apply `expr`
>> internally. Same thing, just done without having to expose the user to the
>> low-level guts. And since `expr` could throw exceptions, those now happen
>> within the purview of `container`'s member functions, which can abort the
>> object creation properly.
>>
>
> Some other rules of thumb:
>
> 1. You can't affect how lazy expressions evaluate. That is, you can't give
> them values; they are simply a thing that generates a value. That's another
> reason `std::sort` and most algorithms wouldn't use them.
>
> 2. You can't evaluate them more than once. UB ought to result if you try.
>
> 3. You can't pass a lazy expression outside of your call stack. Nor can
> you return one.
>
> So if you ever need to do any of these things, you are clearly using the
> wrong tool.
>
>
--
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/b5a52d3d-3255-41b8-8649-ce4703f1ac2e%40isocpp.org.
------=_Part_41377_1163352758.1527631392055
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">@florian: Yes, good point: The fact that you don't nee=
d a "already evaluated" flag for simple expressions clearly point=
s to the fact that the caller side should handle the flag, i.e. the callee =
should just call the function in case it needs the value. The function can =
elect to use a flag or re-evalutate if it can figure out that runtime cost =
is low, no side effects occur and no temporary destructors to call. Using t=
hunks to adjust stack frame offsets is probably wise as it is going to be f=
airly rare that forwarding occurs (especially in multiple levels).<div><div=
><br></div><div>@Nicol: Prohibiting using a lazy parameter more than once s=
eems overly restrictive and very error prone, especially if no diagnostic i=
s required. Furthermore the caller must keep track of whether the function =
was called anyway to handle temporary destruction properly.<br><br>Den tisd=
ag 29 maj 2018 kl. 22:25:16 UTC+2 skrev Nicol Bolas:<blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div dir=3D"ltr">On Tuesday, May 29, 2018 at 4:21:21 =
PM UTC-4, Nicol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"marg=
in:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div di=
r=3D"ltr">On Tuesday, May 29, 2018 at 1:47:45 PM UTC-4, <a>mihailn...@gmail=
..com</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-l=
eft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><di=
v></div><div>On one hand is func_ref which binds to everything but must int=
roduce an explicit lambda to write code inline</div><div>, on the other is =
lazy, in which inline code is the default, but is single single expression =
only and does not bind to anything (inline only).=C2=A0</div><div><br></div=
><div>For me, personally func_ref is the better interface as it is the most=
general, but I am obviously missing something (<span style=3D"display:inli=
ne!important;float:none;background-color:transparent;color:rgb(34,34,34);fo=
nt-family:"Arial","Helvetica",sans-serif;font-size:13px=
;font-style:normal;font-variant:normal;font-weight:400;letter-spacing:norma=
l;text-align:left;text-decoration:none;text-indent:0px;text-transform:none;=
white-space:normal;word-spacing:0px">performance aside</span>) as you all a=
re so exited.</div><div><br></div><div>When I will want to use lazy?=C2=A0<=
span style=3D"display:inline!important;float:none;background-color:transpar=
ent;color:rgb(34,34,34);font-family:"Arial","Helvetica"=
,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weigh=
t:400;letter-spacing:normal;text-align:left;text-decoration:none;text-inden=
t:0px;text-transform:none;white-space:normal;word-spacing:0px">What are the=
rules of thumb? What is "the killer app"?</span></div></div></bl=
ockquote><div><br></div><div>The two examples I gave above are the "ki=
ller app". Transparent lazy evaluation equivalent to C++'s `&&=
amp;` and `||` behavior, and the ability to have `lazy_emplace` work. Neith=
er of these cases are things for which passing a function is the natural in=
terface.</div><div><br></div><div>The rule of thumb is that you use a lazy =
expression when it makes sense based on what you're doing. `lazy_emplac=
e` does it because it is the most natural way to make it work. The natural =
low-level user code is:</div><div><br></div><div><div style=3D"background-c=
olor:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;bord=
er-width:1px"><code><div><span style=3D"color:#008">new</span><span style=
=3D"color:#660">(</span><span style=3D"color:#000">container</span><span st=
yle=3D"color:#660">.</span><span style=3D"color:#000">get_mem_for_new_<wbr>=
item</span><span style=3D"color:#660">())</span><span style=3D"color:#000">=
</span><span style=3D"color:#008">auto</span><span style=3D"color:#660">(<=
/span><span style=3D"color:#000">expr</span><span style=3D"color:#660">);</=
span></div></code></div><br></div><div></div><div>So we invert that by havi=
ng `container.lazy_emplace` apply `expr` internally. Same thing, just done =
without having to expose the user to the low-level guts. And since `expr` c=
ould throw exceptions, those now happen within the purview of `container`&#=
39;s member functions, which can abort the object creation properly.<br></d=
iv></div></blockquote><div><br></div><div>Some other rules of thumb:</div><=
div><br></div><div>1. You can't affect how lazy expressions evaluate. T=
hat is, you can't give them values; they are simply a thing that genera=
tes a value. That's another reason `std::sort` and most algorithms woul=
dn't use them.<br></div><div><br></div><div>2. You can't evaluate t=
hem more than once. UB ought to result if you try.</div><div><br></div><div=
>3. You can't pass a lazy expression outside of your call stack. Nor ca=
n you return one.<br></div><div><br></div><div>So if you ever need to do an=
y of these things, you are clearly using the wrong tool.</div><br></div></b=
lockquote></div></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/b5a52d3d-3255-41b8-8649-ce4703f1ac2e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b5a52d3d-3255-41b8-8649-ce4703f1ac2e=
%40isocpp.org</a>.<br />
------=_Part_41377_1163352758.1527631392055--
------=_Part_41376_1927949359.1527631392055--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 30 May 2018 00:12:27 +0100
Raw View
--000000000000d993e1056d6080b4
Content-Type: text/plain; charset="UTF-8"
On Tue, 29 May 2018, 23:03 Bengt Gustafsson, <bengt.gustafsson@beamways.com>
wrote:
> @florian: Yes, good point: The fact that you don't need a "already
> evaluated" flag for simple expressions clearly points to the fact that the
> caller side should handle the flag, i.e. the callee should just call the
> function in case it needs the value. The function can elect to use a flag
> or re-evalutate if it can figure out that runtime cost is low, no side
> effects occur and no temporary destructors to call. Using thunks to adjust
> stack frame offsets is probably wise as it is going to be fairly rare that
> forwarding occurs (especially in multiple levels).
>
> @Nicol: Prohibiting using a lazy parameter more than once seems overly
> restrictive and very error prone, especially if no diagnostic is required.
> Furthermore the caller must keep track of whether the function was called
> anyway to handle temporary destruction properly.
>
In the proposal under discussion, there is no caching of the result of the
evaluation of the passed in expression and so no flag required and no
destructor call. Multiple use results in multiple evaluation of the
initializer expression, which may result in UB if the evaluation of the
expression falsifies its own preconditions (e.g. moving out a container or
smart pointer that is required to be non empty).
> Den tisdag 29 maj 2018 kl. 22:25:16 UTC+2 skrev Nicol Bolas:
>>
>> On Tuesday, May 29, 2018 at 4:21:21 PM UTC-4, Nicol Bolas wrote:
>>>
>>> On Tuesday, May 29, 2018 at 1:47:45 PM UTC-4, mihailn...@gmail.com
>>> wrote:
>>>>
>>>> On one hand is func_ref which binds to everything but must introduce an
>>>> explicit lambda to write code inline
>>>> , on the other is lazy, in which inline code is the default, but is
>>>> single single expression only and does not bind to anything (inline only).
>>>>
>>>> For me, personally func_ref is the better interface as it is the most
>>>> general, but I am obviously missing something (performance aside) as
>>>> you all are so exited.
>>>>
>>>> When I will want to use lazy? What are the rules of thumb? What is
>>>> "the killer app"?
>>>>
>>>
>>> The two examples I gave above are the "killer app". Transparent lazy
>>> evaluation equivalent to C++'s `&&` and `||` behavior, and the ability to
>>> have `lazy_emplace` work. Neither of these cases are things for which
>>> passing a function is the natural interface.
>>>
>>> The rule of thumb is that you use a lazy expression when it makes sense
>>> based on what you're doing. `lazy_emplace` does it because it is the most
>>> natural way to make it work. The natural low-level user code is:
>>>
>>> new(container.get_mem_for_new_item()) auto(expr);
>>>
>>> So we invert that by having `container.lazy_emplace` apply `expr`
>>> internally. Same thing, just done without having to expose the user to the
>>> low-level guts. And since `expr` could throw exceptions, those now happen
>>> within the purview of `container`'s member functions, which can abort the
>>> object creation properly.
>>>
>>
>> Some other rules of thumb:
>>
>> 1. You can't affect how lazy expressions evaluate. That is, you can't
>> give them values; they are simply a thing that generates a value. That's
>> another reason `std::sort` and most algorithms wouldn't use them.
>>
>> 2. You can't evaluate them more than once. UB ought to result if you try.
>>
>> 3. You can't pass a lazy expression outside of your call stack. Nor can
>> you return one.
>>
>> So if you ever need to do any of these things, you are clearly using the
>> wrong tool.
>>
>> --
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/unsubscribe
> .
> To unsubscribe from this group and all its topics, 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/b5a52d3d-3255-41b8-8649-ce4703f1ac2e%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/b5a52d3d-3255-41b8-8649-ce4703f1ac2e%40isocpp.org?utm_medium=email&utm_source=footer>
> .
>
--
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/CAJnLdObYQtzFfdbxh0Wb4rU_vYiqZHhscofF%2BJXVdgTy3uU45Q%40mail.gmail.com.
--000000000000d993e1056d6080b4
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"auto"><div><br><br><div class=3D"gmail_quote"><div dir=3D"ltr">=
On Tue, 29 May 2018, 23:03 Bengt Gustafsson, <<a href=3D"mailto:bengt.gu=
stafsson@beamways.com">bengt.gustafsson@beamways.com</a>> wrote:<br></di=
v><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:=
1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">@florian: Yes, good point=
: The fact that you don't need a "already evaluated" flag for=
simple expressions clearly points to the fact that the caller side should =
handle the flag, i.e. the callee should just call the function in case it n=
eeds the value. The function can elect to use a flag or re-evalutate if it =
can figure out that runtime cost is low, no side effects occur and no tempo=
rary destructors to call. Using thunks to adjust stack frame offsets is pro=
bably wise as it is going to be fairly rare that forwarding occurs (especia=
lly in multiple levels).<div><div><br></div><div>@Nicol: Prohibiting using =
a lazy parameter more than once seems overly restrictive and very error pro=
ne, especially if no diagnostic is required. Furthermore the caller must ke=
ep track of whether the function was called anyway to handle temporary dest=
ruction properly.<br></div></div></div></blockquote></div></div><div dir=3D=
"auto"><br></div><div dir=3D"auto">In the proposal under discussion, there =
is no caching of the result of the evaluation of the passed in expression a=
nd so no flag required and no destructor call. Multiple use results in mult=
iple evaluation of the initializer expression, which may result in UB if th=
e evaluation of the expression falsifies its own preconditions (e.g. moving=
out a container or smart pointer that is required to be non empty).=C2=A0<=
/div><div dir=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gmail_quot=
e"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left=
:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div><br>Den tisdag=
29 maj 2018 kl. 22:25:16 UTC+2 skrev Nicol Bolas:<blockquote class=3D"gmai=
l_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr">On Tuesday, May 29, 2018 at 4:21:21 PM UTC-=
4, Nicol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;ma=
rgin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"lt=
r">On Tuesday, May 29, 2018 at 1:47:45 PM UTC-4, <a rel=3D"noreferrer">miha=
iln...@gmail.com</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margi=
n:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div></div><div>On one hand is func_ref which binds to everything =
but must introduce an explicit lambda to write code inline</div><div>, on t=
he other is lazy, in which inline code is the default, but is single single=
expression only and does not bind to anything (inline only).=C2=A0</div><d=
iv><br></div><div>For me, personally func_ref is the better interface as it=
is the most general, but I am obviously missing something (<span style=3D"=
display:inline!important;float:none;background-color:transparent;color:rgb(=
34,34,34);font-family:"Arial","Helvetica",sans-serif;fo=
nt-size:13px;font-style:normal;font-variant:normal;font-weight:400;letter-s=
pacing:normal;text-align:left;text-decoration:none;text-indent:0px;text-tra=
nsform:none;white-space:normal;word-spacing:0px">performance aside</span>) =
as you all are so exited.</div><div><br></div><div>When I will want to use =
lazy?=C2=A0<span style=3D"display:inline!important;float:none;background-co=
lor:transparent;color:rgb(34,34,34);font-family:"Arial","Hel=
vetica",sans-serif;font-size:13px;font-style:normal;font-variant:norma=
l;font-weight:400;letter-spacing:normal;text-align:left;text-decoration:non=
e;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">=
What are the rules of thumb? What is "the killer app"?</span></di=
v></div></blockquote><div><br></div><div>The two examples I gave above are =
the "killer app". Transparent lazy evaluation equivalent to C++&#=
39;s `&&` and `||` behavior, and the ability to have `lazy_emplace`=
work. Neither of these cases are things for which passing a function is th=
e natural interface.</div><div><br></div><div>The rule of thumb is that you=
use a lazy expression when it makes sense based on what you're doing. =
`lazy_emplace` does it because it is the most natural way to make it work. =
The natural low-level user code is:</div><div><br></div><div><div style=3D"=
background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-styl=
e:solid;border-width:1px"><code><div><span style=3D"color:#008">new</span><=
span style=3D"color:#660">(</span><span style=3D"color:#000">container</spa=
n><span style=3D"color:#660">.</span><span style=3D"color:#000">get_mem_for=
_new_item</span><span style=3D"color:#660">())</span><span style=3D"color:#=
000"> </span><span style=3D"color:#008">auto</span><span style=3D"color:#66=
0">(</span><span style=3D"color:#000">expr</span><span style=3D"color:#660"=
>);</span></div></code></div><br></div><div></div><div>So we invert that by=
having `container.lazy_emplace` apply `expr` internally. Same thing, just =
done without having to expose the user to the low-level guts. And since `ex=
pr` could throw exceptions, those now happen within the purview of `contain=
er`'s member functions, which can abort the object creation properly.<b=
r></div></div></blockquote><div><br></div><div>Some other rules of thumb:</=
div><div><br></div><div>1. You can't affect how lazy expressions evalua=
te. That is, you can't give them values; they are simply a thing that g=
enerates a value. That's another reason `std::sort` and most algorithms=
wouldn't use them.<br></div><div><br></div><div>2. You can't evalu=
ate them more than once. UB ought to result if you try.</div><div><br></div=
><div>3. You can't pass a lazy expression outside of your call stack. N=
or can you return one.<br></div><div><br></div><div>So if you ever need to =
do any of these things, you are clearly using the wrong tool.</div><br></di=
v></blockquote></div></div></div>
<p></p>
-- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/unsubscribe" target=3D"_blan=
k" rel=3D"noreferrer">https://groups.google.com/a/isocpp.org/d/topic/std-pr=
oposals/5oUZysJB4HE/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_blank" rel=3D"n=
oreferrer">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank" rel=3D"noreferrer">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/b5a52d3d-3255-41b8-8649-ce4703f1ac2e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank" =
rel=3D"noreferrer">https://groups.google.com/a/isocpp.org/d/msgid/std-propo=
sals/b5a52d3d-3255-41b8-8649-ce4703f1ac2e%40isocpp.org</a>.<br>
</blockquote></div></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/CAJnLdObYQtzFfdbxh0Wb4rU_vYiqZHhscofF=
%2BJXVdgTy3uU45Q%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdObYQtzFfd=
bxh0Wb4rU_vYiqZHhscofF%2BJXVdgTy3uU45Q%40mail.gmail.com</a>.<br />
--000000000000d993e1056d6080b4--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 29 May 2018 17:00:44 -0700 (PDT)
Raw View
------=_Part_41839_1471988806.1527638444124
Content-Type: multipart/alternative;
boundary="----=_Part_41840_416910329.1527638444124"
------=_Part_41840_416910329.1527638444124
Content-Type: text/plain; charset="UTF-8"
On Tuesday, May 29, 2018 at 7:22:11 PM UTC-4, Edward Catmur wrote:
>
> On Tue, 29 May 2018, 23:03 Bengt Gustafsson, <bengt.gu...@beamways.com
> <javascript:>> wrote:
>
>> @florian: Yes, good point: The fact that you don't need a "already
>> evaluated" flag for simple expressions clearly points to the fact that the
>> caller side should handle the flag, i.e. the callee should just call the
>> function in case it needs the value. The function can elect to use a flag
>> or re-evalutate if it can figure out that runtime cost is low, no side
>> effects occur and no temporary destructors to call. Using thunks to adjust
>> stack frame offsets is probably wise as it is going to be fairly rare that
>> forwarding occurs (especially in multiple levels).
>>
>> @Nicol: Prohibiting using a lazy parameter more than once seems overly
>> restrictive and very error prone, especially if no diagnostic is required.
>> Furthermore the caller must keep track of whether the function was called
>> anyway to handle temporary destruction properly.
>>
>
> In the proposal under discussion, there is no caching of the result of the
> evaluation of the passed in expression and so no flag required and no
> destructor call. Multiple use results in multiple evaluation of the
> initializer expression, which may result in UB if the evaluation of the
> expression falsifies its own preconditions (e.g. moving out a container or
> smart pointer that is required to be non empty).
>
My issue with allowing multiple evaluation to be well-defined in some cases
is that there's no way to *ensure* that at the compiler level. There's no
way to write a concept or a `static_assert` or something that would cause
compilation failure if the user does the wrong thing.
It would be safer to just declare it UB period.
--
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/46f2c4fb-e5d3-4043-af3d-c2c14963b8e3%40isocpp.org.
------=_Part_41840_416910329.1527638444124
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, May 29, 2018 at 7:22:11 PM UTC-4, Edward Catmu=
r 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"auto"><div=
><div class=3D"gmail_quote"><div dir=3D"ltr">On Tue, 29 May 2018, 23:03 Ben=
gt Gustafsson, <<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated=
-mailto=3D"B5YQN-4UAAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'j=
avascript:';return true;" onclick=3D"this.href=3D'javascript:';=
return true;">bengt.gu...@beamways.com</a><wbr>> wrote:<br></div><blockq=
uote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr">@florian: Yes, good point: The fac=
t that you don't need a "already evaluated" flag for simple e=
xpressions clearly points to the fact that the caller side should handle th=
e flag, i.e. the callee should just call the function in case it needs the =
value. The function can elect to use a flag or re-evalutate if it can figur=
e out that runtime cost is low, no side effects occur and no temporary dest=
ructors to call. Using thunks to adjust stack frame offsets is probably wis=
e as it is going to be fairly rare that forwarding occurs (especially in mu=
ltiple levels).<div><div><br></div><div>@Nicol: Prohibiting using a lazy pa=
rameter more than once seems overly restrictive and very error prone, espec=
ially if no diagnostic is required. Furthermore the caller must keep track =
of whether the function was called anyway to handle temporary destruction p=
roperly.<br></div></div></div></blockquote></div></div><div dir=3D"auto"><b=
r></div><div dir=3D"auto">In the proposal under discussion, there is no cac=
hing of the result of the evaluation of the passed in expression and so no =
flag required and no destructor call. Multiple use results in multiple eval=
uation of the initializer expression, which may result in UB if the evaluat=
ion of the expression falsifies its own preconditions (e.g. moving out a co=
ntainer or smart pointer that is required to be non empty).=C2=A0</div></di=
v></blockquote><div><br></div><div>My issue with allowing multiple evaluati=
on to be well-defined in some cases is that there's no way to <i>ensure=
</i> that at the compiler level. There's no way to write a concept or a=
`static_assert` or something that would cause compilation failure if the u=
ser does the wrong thing.</div><div><br></div><div>It would be safer to jus=
t declare it UB period.<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/46f2c4fb-e5d3-4043-af3d-c2c14963b8e3%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/46f2c4fb-e5d3-4043-af3d-c2c14963b8e3=
%40isocpp.org</a>.<br />
------=_Part_41840_416910329.1527638444124--
------=_Part_41839_1471988806.1527638444124--
.
Author: florian.csdt@gmail.com
Date: Wed, 30 May 2018 01:40:44 -0700 (PDT)
Raw View
------=_Part_43115_2045102069.1527669644956
Content-Type: multipart/alternative;
boundary="----=_Part_43116_1146810625.1527669644957"
------=_Part_43116_1146810625.1527669644957
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le mercredi 30 mai 2018 01:22:11 UTC+2, Edward Catmur a =C3=A9crit :
>
>
>
> On Tue, 29 May 2018, 23:03 Bengt Gustafsson, <bengt.gu...@beamways.com=20
> <javascript:>> wrote:
>
>> @florian: Yes, good point: The fact that you don't need a "already=20
>> evaluated" flag for simple expressions clearly points to the fact that t=
he=20
>> caller side should handle the flag, i.e. the callee should just call the=
=20
>> function in case it needs the value. The function can elect to use a fla=
g=20
>> or re-evalutate if it can figure out that runtime cost is low, no side=
=20
>> effects occur and no temporary destructors to call. Using thunks to adju=
st=20
>> stack frame offsets is probably wise as it is going to be fairly rare th=
at=20
>> forwarding occurs (especially in multiple levels).
>>
>> @Nicol: Prohibiting using a lazy parameter more than once seems overly=
=20
>> restrictive and very error prone, especially if no diagnostic is require=
d.=20
>> Furthermore the caller must keep track of whether the function was calle=
d=20
>> anyway to handle temporary destruction properly.
>>
>
> In the proposal under discussion, there is no caching of the result of th=
e=20
> evaluation of the passed in expression and so no flag required and no=20
> destructor call. Multiple use results in multiple evaluation of the=20
> initializer expression, which may result in UB if the evaluation of the=
=20
> expression falsifies its own preconditions (e.g. moving out a container o=
r=20
> smart pointer that is required to be non empty).=20
>
=20
The problem here is not caching the result. If you want to evaluate the=20
expression multiple times, then passing an actual callable object would be=
=20
preferable. So caching is not needed.
The real problem is temporaries lifetime. Let me give you an example:
void print(std::string_view sv) { std::cout << sv << std::endl; }
void print_lazy([] -> std::string_view sv) { std::cout << sv() << std::endl=
;=20
}
void foo0() {
print(std::string("foo")); // ok: temporary string is kept alive until=20
after the execution of print
}
void foo1() {
print_lazy(std::string("foo")); // std::string is generated within=20
"evaluation function" and cannot be kept alive until after the execution of=
=20
print_lazy
}
void foo2() {
print([]() -> std::string_view { return std::string("foo"); }) // same=20
issue as above, but made explicit for better understanding
}
If temporaries are destroyed by the "evaluation function", print and=20
print_lazy cannot be semantically equivalent, and lazy parameters would=20
bring many lifetime issues that are not desirable.
If foo0 is correct (and it is), then foo1 should also be correct, but this=
=20
cannot be if temporary lifetime is bound to the "evaluation function"
The idea was the temporaries use the caller storage (in the caller stack=20
frame), and are destroyed by the caller after the callee execution.
Here we would need to store a flag for the caller to know if the=20
temporaries need to be destroyed or not.
Here could be how the compiler generates print_lazy and foo1:
void print_lazy(std::string_view (*sv_expr)(void*), void* stack_p) {
std::cout << sv_expr(stack_p) << std::endl; // no lifetime management her=
e
}
void foo1() {
// lazy parameter storage
bool __lazy_executed =3D false;
alignas(alignof(std::string)) std::byte __lazy_str_storage[sizeof(std::
string)];
// lazy parameter executor
std::string_view __lazy(void* stack_p) {
std::string* p =3D new(stack_p + /* __lazy_str_storage offset */) std::
string("foo");
// ensure the string is deleted if std::string_view construction throws=
=20
=20
auto str_deleter =3D std::make_scope_exit([p]{ p->~std::string(); })
std::string_view sv =3D std::string_view(*p); // no exception guarantee=
=20
for this constructor
// if creation of the string throws, the object is not created and=20
don't need to be destroyed
// The flag will not be set in that case as the exception is not caught
*static_cast<bool*>(stack_p + /* __lazy_executed offset */) =3D true;
=20
return sv; // "NRVO" is mandatory here
}
// call to print_lazy
print_lazy(&__lazy, __builtin_stack_address(0));
// destroy the temporary string:
if (__lazy_executed) {
static_cast<std::string*>(__lazy_str_storage)->~std::string();
}
}
Of course, this would be generated by the compiler and it would not need to=
=20
be achievable with the same efficiency if written by hand (the NRVO here is=
=20
trivial to do for the compiler in this case).
Also, this is an implementation example to show it is possible, but other=
=20
implementations with the same guarantees would also be possible.
I hope this little explanation will make things clearer...
--=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/e79281d1-55a4-41f0-8f42-95050c8ec679%40isocpp.or=
g.
------=_Part_43116_1146810625.1527669644957
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le mercredi 30 mai 2018 01:22:11 UTC+2, Edward Cat=
mur a =C3=A9crit=C2=A0:<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"auto"><div><br><br><div class=3D"gmail_quote"><div dir=3D"ltr">On Tue,=
29 May 2018, 23:03 Bengt Gustafsson, <<a href=3D"javascript:" target=3D=
"_blank" gdf-obfuscated-mailto=3D"B5YQN-4UAAAJ" rel=3D"nofollow" onmousedow=
n=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=
=3D'javascript:';return true;">bengt.gu...@beamways.com</a><wbr>>=
; wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .=
8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">@florian:=
Yes, good point: The fact that you don't need a "already evaluate=
d" flag for simple expressions clearly points to the fact that the cal=
ler side should handle the flag, i.e. the callee should just call the funct=
ion in case it needs the value. The function can elect to use a flag or re-=
evalutate if it can figure out that runtime cost is low, no side effects oc=
cur and no temporary destructors to call. Using thunks to adjust stack fram=
e offsets is probably wise as it is going to be fairly rare that forwarding=
occurs (especially in multiple levels).<div><div><br></div><div>@Nicol: Pr=
ohibiting using a lazy parameter more than once seems overly restrictive an=
d very error prone, especially if no diagnostic is required. Furthermore th=
e caller must keep track of whether the function was called anyway to handl=
e temporary destruction properly.<br></div></div></div></blockquote></div><=
/div><div dir=3D"auto"><br></div><div dir=3D"auto">In the proposal under di=
scussion, there is no caching of the result of the evaluation of the passed=
in expression and so no flag required and no destructor call. Multiple use=
results in multiple evaluation of the initializer expression, which may re=
sult in UB if the evaluation of the expression falsifies its own preconditi=
ons (e.g. moving out a container or smart pointer that is required to be no=
n empty). <br></div></div></blockquote><div>=C2=A0</div><div>The problem he=
re is not caching the result. If you want to evaluate the expression multip=
le times, then passing an actual callable object would be preferable. So ca=
ching is not needed.<br></div><div>The real problem is temporaries lifetime=
.. Let me give you an example:</div><div><div style=3D"background-color: rgb=
(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bor=
der-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><code cla=
ss=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008=
;" class=3D"styled-by-prettify">void</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">print</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">string_view =
sv</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"> std</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">cout </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify"><<</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> sv </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify"><<</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> std</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">end=
l</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </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: #00=
8;" class=3D"styled-by-prettify">void</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> print_lazy</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">([]</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">-></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: #000;" class=3D"styled-by-prettify">string_=
view sv</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</=
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"> std</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">cout </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify"><<</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> sv</span><span style=3D"color: #660;" class=3D"s=
tyled-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">=
std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">endl</span><sp=
an 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><br></span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">void</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> foo0</span><span style=3D"color: #660;" class=3D"styl=
ed-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=
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">print</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">std</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">string</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #080;" cla=
ss=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: #800;" class=3D"style=
d-by-prettify">// ok: temporary string is kept alive until after the execut=
ion of print</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"><br></span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">void</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> foo1</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=3D"colo=
r: #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 print_lazy</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">std</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">::</span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">string</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">(</span><span style=3D"color: #080;" class=3D"styled-by-prettify">&quo=
t;foo"</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>));</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #800;" class=3D"styled-by-prettify">// std::string =
is generated within "evaluation function" and cannot be kept aliv=
e until after the execution of print_lazy</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">void</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> foo2</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 styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">print</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">([]()</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">-></span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify">string_view </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">retur=
n</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">string</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"colo=
r: #080;" 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;" cl=
ass=3D"styled-by-prettify">})</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-=
prettify">// same issue as above, but made explicit for better understandin=
g</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></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></span></div></code>=
</div><br>If temporaries are destroyed by the "evaluation function&quo=
t;, print and print_lazy cannot be semantically equivalent, and lazy parame=
ters would bring many lifetime issues that are not desirable.</div><div>If =
foo0 is correct (and it is), then foo1 should also be correct, but this can=
not be if temporary lifetime is bound to the "evaluation function"=
;<br></div><div><br></div><div>The idea was the temporaries use the caller =
storage (in the caller stack frame), and are destroyed by the caller after =
the callee execution.</div><div>Here we would need to store a flag for the =
caller to know if the temporaries need to be destroyed or not.</div><div>He=
re could be how the compiler generates print_lazy and foo1:</div><div><div =
style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, =
187); border-style: solid; border-width: 1px; overflow-wrap: break-word;" c=
lass=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subprettypri=
nt"><span style=3D"color: #008;" class=3D"styled-by-prettify">void</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> print_lazy</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">std</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">string_view </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(*</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">sv_expr</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)(</span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">void</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">*),</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">void</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">*</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> stack_p</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: #6=
60;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br>=C2=A0 std</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">cout </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify"><<</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> sv_expr</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">stack_p</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><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">endl</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"sty=
led-by-prettify">// no lifetime management here</span><span style=3D"color:=
#000;" class=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><br></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">void</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> foo1</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">()</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </=
span><span style=3D"color: #800;" class=3D"styled-by-prettify">// lazy para=
meter storage</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">bool</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> _=
_lazy_executed </span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">false</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 alignas</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">alignof</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">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><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> std</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">::</span><span style=3D"color: #008;" class=3D"styled-by-prettify">by=
te</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> __lazy_=
str_storage</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>[</span><span style=3D"color: #008;" class=3D"styled-by-prettify">sizeof</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">std</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">string</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">)];</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br><br>=C2=A0 </span><span style=3D"color: #80=
0;" class=3D"styled-by-prettify">// lazy parameter executor</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 std</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">string_view __lazy</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">void</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> stack_p</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-b=
y-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br>=C2=A0 =C2=A0 std</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">::</span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">string</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">*</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> p </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">new</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify">stack_p </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">/* __lazy_str_storage offset */</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">::</span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">string</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">(</span><span style=3D"color: #080;" class=3D"styled-by-prettify">&qu=
ot;foo"</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><b=
r>=C2=A0 =C2=A0 </span><span style=3D"color: #800;" class=3D"styled-by-pret=
tify">// ensure the string is deleted if std::string_view construction thro=
ws =C2=A0 =C2=A0</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled=
-by-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> str_deleter </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">make_scope=
_exit</span><span style=3D"color: #660;" class=3D"styled-by-prettify">([</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">p</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">]{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> p</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">->~</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">std</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">::</span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">string</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">();</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
})</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=
=C2=A0 =C2=A0 std</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">s=
tring_view sv </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> st=
d</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">string_view</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">(*</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">p</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" clas=
s=3D"styled-by-prettify">// no exception guarantee for this constructor</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0=
=C2=A0 </span><span style=3D"color: #800;" class=3D"styled-by-prettify">//=
if creation of the string throws, the object is not created and don't =
need to be destroyed</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #800;" class=3D"st=
yled-by-prettify">// The flag will not be set in that case as the exception=
is not caught</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">*</span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">static_cast</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy"><</span><span style=3D"color: #008;" class=3D"styled-by-prettify">bo=
ol</span><span style=3D"color: #660;" class=3D"styled-by-prettify">*>(</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">stack_p </sp=
an><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">/* __lazy_executed offset */</sp=
an><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">=3D</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">true</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> sv</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-p=
rettify">// "NRVO" is mandatory here</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br><br>=C2=A0 </span><span style=3D"color: #80=
0;" class=3D"styled-by-prettify">// call to print_lazy</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 print_lazy</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">(&</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">__lazy</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> __builtin_stack_address</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"=
color: #066;" class=3D"styled-by-prettify">0</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">));</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br><br>=C2=A0 </span><span style=3D"color: #800=
;" class=3D"styled-by-prettify">// destroy the temporary string:</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">if</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">__lazy_executed</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">static_cast</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify"><</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">std</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">::</span><span style=3D"color: #008;" class=3D"styled-by-prettify">strin=
g</span><span style=3D"color: #660;" class=3D"styled-by-prettify">*>(</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">__lazy_str_st=
orage</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)->=
;~</span><span style=3D"color: #000;" class=3D"styled-by-prettify">std</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">string</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">();</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br></span></div></code></div></div><div>Of course, this =
would be generated by the compiler and it would not need to be achievable w=
ith the same efficiency if written by hand (the NRVO here is trivial to do =
for the compiler in this case).</div><div>Also, this is an implementation e=
xample to show it is possible, but other implementations with the same guar=
antees would also be possible.</div><div><br></div><div>I hope this little =
explanation will make things clearer...<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/e79281d1-55a4-41f0-8f42-95050c8ec679%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/e79281d1-55a4-41f0-8f42-95050c8ec679=
%40isocpp.org</a>.<br />
------=_Part_43116_1146810625.1527669644957--
------=_Part_43115_2045102069.1527669644956--
.
Author: florian.csdt@gmail.com
Date: Wed, 30 May 2018 01:50:53 -0700 (PDT)
Raw View
------=_Part_43476_1960782291.1527670253868
Content-Type: multipart/alternative;
boundary="----=_Part_43477_1435354691.1527670253870"
------=_Part_43477_1435354691.1527670253870
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le mercredi 30 mai 2018 10:40:45 UTC+2, floria...@gmail.com a =C3=A9crit :
>
>
>
> Le mercredi 30 mai 2018 01:22:11 UTC+2, Edward Catmur a =C3=A9crit :
>>
>>
>>
>> On Tue, 29 May 2018, 23:03 Bengt Gustafsson, <bengt.gu...@beamways.com>=
=20
>> wrote:
>>
>>> @florian: Yes, good point: The fact that you don't need a "already=20
>>> evaluated" flag for simple expressions clearly points to the fact that =
the=20
>>> caller side should handle the flag, i.e. the callee should just call th=
e=20
>>> function in case it needs the value. The function can elect to use a fl=
ag=20
>>> or re-evalutate if it can figure out that runtime cost is low, no side=
=20
>>> effects occur and no temporary destructors to call. Using thunks to adj=
ust=20
>>> stack frame offsets is probably wise as it is going to be fairly rare t=
hat=20
>>> forwarding occurs (especially in multiple levels).
>>>
>>> @Nicol: Prohibiting using a lazy parameter more than once seems overly=
=20
>>> restrictive and very error prone, especially if no diagnostic is requir=
ed.=20
>>> Furthermore the caller must keep track of whether the function was call=
ed=20
>>> anyway to handle temporary destruction properly.
>>>
>>
>> In the proposal under discussion, there is no caching of the result of=
=20
>> the evaluation of the passed in expression and so no flag required and n=
o=20
>> destructor call. Multiple use results in multiple evaluation of the=20
>> initializer expression, which may result in UB if the evaluation of the=
=20
>> expression falsifies its own preconditions (e.g. moving out a container =
or=20
>> smart pointer that is required to be non empty).=20
>>
> =20
> The problem here is not caching the result. If you want to evaluate the=
=20
> expression multiple times, then passing an actual callable object would b=
e=20
> preferable. So caching is not needed.
> The real problem is temporaries lifetime. Let me give you an example:
> void print(std::string_view sv) { std::cout << sv << std::endl; }
> void print_lazy([] -> std::string_view sv) { std::cout << sv() << std::
> endl; }
>
> void foo0() {
> print(std::string("foo")); // ok: temporary string is kept alive until=
=20
> after the execution of print
> }
> void foo1() {
> print_lazy(std::string("foo")); // std::string is generated within=20
> "evaluation function" and cannot be kept alive until after the execution =
of=20
> print_lazy
> }
> void foo2() {
> print([]() -> std::string_view { return std::string("foo"); }) // same=
=20
> issue as above, but made explicit for better understanding
> }
>
> If temporaries are destroyed by the "evaluation function", print and=20
> print_lazy cannot be semantically equivalent, and lazy parameters would=
=20
> bring many lifetime issues that are not desirable.
> If foo0 is correct (and it is), then foo1 should also be correct, but thi=
s=20
> cannot be if temporary lifetime is bound to the "evaluation function"
>
> The idea was the temporaries use the caller storage (in the caller stack=
=20
> frame), and are destroyed by the caller after the callee execution.
> Here we would need to store a flag for the caller to know if the=20
> temporaries need to be destroyed or not.
> Here could be how the compiler generates print_lazy and foo1:
> void print_lazy(std::string_view (*sv_expr)(void*), void* stack_p) {
> std::cout << sv_expr(stack_p) << std::endl; // no lifetime management=
=20
> here
> }
>
> void foo1() {
> // lazy parameter storage
> bool __lazy_executed =3D false;
> alignas(alignof(std::string)) std::byte __lazy_str_storage[sizeof(std::
> string)];
>
> // lazy parameter executor
> std::string_view __lazy(void* stack_p) {
> std::string* p =3D new(stack_p + /* __lazy_str_storage offset */) std=
::
> string("foo");
>
> // ensure the string is deleted if std::string_view construction=20
> throws =20
> auto str_deleter =3D std::make_scope_exit([p]{ p->~std::string(); })
>
> std::string_view sv =3D std::string_view(*p); // no exception guarant=
ee=20
> for this constructor
>
> // if creation of the string throws, the object is not created and=20
> don't need to be destroyed
> // The flag will not be set in that case as the exception is not=20
> caught
> *static_cast<bool*>(stack_p + /* __lazy_executed offset */) =3D true;
> =20
> return sv; // "NRVO" is mandatory here
> }
>
> // call to print_lazy
> print_lazy(&__lazy, __builtin_stack_address(0));
>
> // destroy the temporary string:
> if (__lazy_executed) {
> static_cast<std::string*>(__lazy_str_storage)->~std::string();
> }
> }
> Of course, this would be generated by the compiler and it would not need=
=20
> to be achievable with the same efficiency if written by hand (the NRVO he=
re=20
> is trivial to do for the compiler in this case).
> Also, this is an implementation example to show it is possible, but other=
=20
> implementations with the same guarantees would also be possible.
>
> I hope this little explanation will make things clearer...
>
I screwed up the exception handling, scope_exit will destroy std::string=
=20
even if it doesn't throw, which is not what we want.
Here is the example fixed:
void print_lazy(std::string_view (*sv_expr)(void*), void* stack_p) {
std::cout << sv_expr(stack_p) << std::endl; // no lifetime management her=
e
}
void foo1() {
// lazy parameter storage
bool __lazy_executed =3D false;
alignas(alignof(std::string)) std::byte __lazy_str_storage[sizeof(std::
string)];
// lazy parameter executor
std::string_view __lazy(void* stack_p) {
std::string* p =3D new(stack_p + /* __lazy_str_storage offset */) std::
string("foo");
// ensure the string is deleted if std::string_view construction throws
try {
std::string_view sv =3D std::string_view(*p); // no exception guarant=
ee=20
for this constructor
} catch (...) {
p->~std::string();
throw;
}
// if creation of the string throws, the object is not created and=20
don't need to be destroyed
// The flag will not be set in that case as the exception is not caught
*static_cast<bool*>(stack_p + /* __lazy_executed offset */) =3D true;
=20
return sv; // "NRVO" is mandatory here
}
// call to print_lazy
print_lazy(&__lazy, __builtin_stack_address(0));
// destroy the temporary string:
if (__lazy_executed) {
static_cast<std::string*>(__lazy_str_storage)->~std::string();
}
}
--=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/b12791de-64ad-4641-b0c0-341f5997cb6d%40isocpp.or=
g.
------=_Part_43477_1435354691.1527670253870
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le mercredi 30 mai 2018 10:40:45 UTC+2, floria...@=
gmail.com a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><=
div dir=3D"ltr"><br><br>Le mercredi 30 mai 2018 01:22:11 UTC+2, Edward Catm=
ur a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin:0;m=
argin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"a=
uto"><div><br><br><div class=3D"gmail_quote"><div dir=3D"ltr">On Tue, 29 Ma=
y 2018, 23:03 Bengt Gustafsson, <<a rel=3D"nofollow">bengt.gu...@beamway=
s.com</a>> wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"lt=
r">@florian: Yes, good point: The fact that you don't need a "alre=
ady evaluated" flag for simple expressions clearly points to the fact =
that the caller side should handle the flag, i.e. the callee should just ca=
ll the function in case it needs the value. The function can elect to use a=
flag or re-evalutate if it can figure out that runtime cost is low, no sid=
e effects occur and no temporary destructors to call. Using thunks to adjus=
t stack frame offsets is probably wise as it is going to be fairly rare tha=
t forwarding occurs (especially in multiple levels).<div><div><br></div><di=
v>@Nicol: Prohibiting using a lazy parameter more than once seems overly re=
strictive and very error prone, especially if no diagnostic is required. Fu=
rthermore the caller must keep track of whether the function was called any=
way to handle temporary destruction properly.<br></div></div></div></blockq=
uote></div></div><div dir=3D"auto"><br></div><div dir=3D"auto">In the propo=
sal under discussion, there is no caching of the result of the evaluation o=
f the passed in expression and so no flag required and no destructor call. =
Multiple use results in multiple evaluation of the initializer expression, =
which may result in UB if the evaluation of the expression falsifies its ow=
n preconditions (e.g. moving out a container or smart pointer that is requi=
red to be non empty). <br></div></div></blockquote><div>=C2=A0</div><div>Th=
e problem here is not caching the result. If you want to evaluate the expre=
ssion multiple times, then passing an actual callable object would be prefe=
rable. So caching is not needed.<br></div><div>The real problem is temporar=
ies lifetime. Let me give you an example:</div><div><div style=3D"backgroun=
d-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;b=
order-width:1px"><code><div><span style=3D"color:#008">void</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#008">print</span><span styl=
e=3D"color:#660">(</span><span style=3D"color:#000">std</span><span style=
=3D"color:#660">::</span><span style=3D"color:#000">string_view sv</span><s=
pan style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#660">{</span><span style=3D"color:#000"> std</span><span sty=
le=3D"color:#660">::</span><span style=3D"color:#000">cout </span><span sty=
le=3D"color:#660"><<</span><span style=3D"color:#000"> sv </span><spa=
n style=3D"color:#660"><<</span><span style=3D"color:#000"> std</span=
><span style=3D"color:#660">::</span><span style=3D"color:#000">endl</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></span><span s=
tyle=3D"color:#008">void</span><span style=3D"color:#000"> print_lazy</span=
><span style=3D"color:#660">([]</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#660">-></span><span style=3D"color:#000"> std</span>=
<span style=3D"color:#660">::</span><span style=3D"color:#000">string_view =
sv</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">{</span><span style=3D"color:#000"> std</spa=
n><span style=3D"color:#660">::</span><span style=3D"color:#000">cout </spa=
n><span style=3D"color:#660"><<</span><span style=3D"color:#000"> sv<=
/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"> std=
</span><span style=3D"color:#660">::</span><span style=3D"color:#000">endl<=
/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><br></sp=
an><span style=3D"color:#008">void</span><span style=3D"color:#000"> foo0</=
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 <=
/span><span style=3D"color:#008">print</span><span style=3D"color:#660">(</=
span><span style=3D"color:#000">std</span><span style=3D"color:#660">::</sp=
an><span style=3D"color:#008">string</span><span style=3D"color:#660">(</sp=
an><span style=3D"color:#080">"foo"</span><span style=3D"color:#6=
60">));</span><span style=3D"color:#000"> </span><span style=3D"color:#800"=
>// ok: temporary string is kept alive until after the execution of print</=
span><span style=3D"color:#000"><br></span><span style=3D"color:#660">}</sp=
an><span style=3D"color:#000"><br></span><span style=3D"color:#008">void</s=
pan><span style=3D"color:#000"> foo1</span><span style=3D"color:#660">()</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#660">{</span><=
span style=3D"color:#000"><br>=C2=A0 print_lazy</span><span style=3D"color:=
#660">(</span><span style=3D"color:#000">std</span><span style=3D"color:#66=
0">::</span><span style=3D"color:#008">string</span><span style=3D"color:#6=
60">(</span><span style=3D"color:#080">"foo"</span><span style=3D=
"color:#660">))<wbr>;</span><span style=3D"color:#000"> </span><span style=
=3D"color:#800">// std::string is generated within "evaluation functio=
n" and cannot be kept alive until after the execution of print_lazy</s=
pan><span style=3D"color:#000"><br></span><span style=3D"color:#660">}</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#008">void</sp=
an><span style=3D"color:#000"> foo2</span><span style=3D"color:#660">()</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#660">{</span><s=
pan style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">print=
</span><span style=3D"color:#660">([]()</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#660">-></span><span style=3D"color:#000"> st=
d</span><span style=3D"color:#660">::</span><span style=3D"color:#000">stri=
ng_view </span><span style=3D"color:#660">{</span><span style=3D"color:#000=
"> </span><span style=3D"color:#008">return</span><span style=3D"color:#000=
"> std</span><span style=3D"color:#660">::</span><span style=3D"color:#008"=
>string</span><span style=3D"color:#660">(</span><span style=3D"color:#080"=
>"foo"</span><span style=3D"color:#660">);</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660">})</span><span style=3D"color=
:#000"> </span><span style=3D"color:#800">// same issue as above, but made =
explicit for better understanding</span><span style=3D"color:#000"><br></sp=
an><span style=3D"color:#660">}</span><span style=3D"color:#000"><br></span=
></div></code></div><br>If temporaries are destroyed by the "evaluatio=
n function", print and print_lazy cannot be semantically equivalent, a=
nd lazy parameters would bring many lifetime issues that are not desirable.=
</div><div>If foo0 is correct (and it is), then foo1 should also be correct=
, but this cannot be if temporary lifetime is bound to the "evaluation=
function"<br></div><div><br></div><div>The idea was the temporaries u=
se the caller storage (in the caller stack frame), and are destroyed by the=
caller after the callee execution.</div><div>Here we would need to store a=
flag for the caller to know if the temporaries need to be destroyed or not=
..</div><div>Here could be how the compiler generates print_lazy and foo1:</=
div><div><div style=3D"background-color:rgb(250,250,250);border-color:rgb(1=
87,187,187);border-style:solid;border-width:1px"><code><div><span style=3D"=
color:#008">void</span><span style=3D"color:#000"> print_lazy</span><span s=
tyle=3D"color:#660">(</span><span style=3D"color:#000">std</span><span styl=
e=3D"color:#660">::</span><span style=3D"color:#000">string_view </span><sp=
an style=3D"color:#660">(*</span><span style=3D"color:#000">sv_expr</span><=
span style=3D"color:#660">)(</span><span style=3D"color:#008">void</span><s=
pan style=3D"color:#660">*),</span><span style=3D"color:#000"> </span><span=
style=3D"color:#008">void</span><span style=3D"color:#660">*</span><span s=
tyle=3D"color:#000"> stack_p</span><span style=3D"color:#660">)</span><span=
style=3D"color:#000"> </span><span style=3D"color:#660">{</span><span styl=
e=3D"color:#000"><br>=C2=A0 std</span><span style=3D"color:#660">::</span><=
span style=3D"color:#000">cout </span><span style=3D"color:#660"><<</=
span><span style=3D"color:#000"> sv_expr</span><span style=3D"color:#660">(=
</span><span style=3D"color:#000">stack_p</span><span style=3D"color:#660">=
)</span><span style=3D"color:#000"> </span><span style=3D"color:#660"><&=
lt;</span><span style=3D"color:#000"> std</span><span style=3D"color:#660">=
::</span><span style=3D"color:#000">endl</span><span style=3D"color:#660">;=
</span><span style=3D"color:#000"> </span><span style=3D"color:#800">// no =
lifetime management here</span><span style=3D"color:#000"><br></span><span =
style=3D"color:#660">}</span><span style=3D"color:#000"><br><br></span><spa=
n style=3D"color:#008">void</span><span style=3D"color:#000"> foo1</span><s=
pan 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 </span><=
span style=3D"color:#800">// lazy parameter storage</span><span style=3D"co=
lor:#000"><br>=C2=A0 </span><span style=3D"color:#008">bool</span><span sty=
le=3D"color:#000"> __lazy_executed </span><span style=3D"color:#660">=3D</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#008">false</sp=
an><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0=
alignas</span><span style=3D"color:#660">(</span><span style=3D"color:#008=
">alignof</span><span style=3D"color:#660">(</span><span style=3D"color:#00=
0">std</span><span style=3D"color:#660">::</span><span style=3D"color:#008"=
>string</span><span style=3D"color:#660">))</span><span style=3D"color:#000=
"> std</span><span style=3D"color:#660">::</span><span style=3D"color:#008"=
>byte</span><span style=3D"color:#000"> __lazy_str_storage</span><span styl=
e=3D"color:#660">[</span><span style=3D"color:#008">sizeof</span><span styl=
e=3D"color:#660">(</span><span style=3D"color:#000">std</span><span style=
=3D"color:#660">:<wbr>:</span><span style=3D"color:#008">string</span><span=
style=3D"color:#660">)];</span><span style=3D"color:#000"><br><br>=C2=A0 <=
/span><span style=3D"color:#800">// lazy parameter executor</span><span sty=
le=3D"color:#000"><br>=C2=A0 std</span><span style=3D"color:#660">::</span>=
<span style=3D"color:#000">string_view __lazy</span><span style=3D"color:#6=
60">(</span><span style=3D"color:#008">void</span><span style=3D"color:#660=
">*</span><span style=3D"color:#000"> stack_p</span><span style=3D"color:#6=
60">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 std</span><span style=
=3D"color:#660">::</span><span style=3D"color:#008">string</span><span styl=
e=3D"color:#660">*</span><span style=3D"color:#000"> p </span><span style=
=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D=
"color:#008">new</span><span style=3D"color:#660">(</span><span style=3D"co=
lor:#000">stack_p </span><span style=3D"color:#660">+</span><span style=3D"=
color:#000"> </span><span style=3D"color:#800">/* __lazy_str_storage offset=
*/</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> st=
d</span><span style=3D"color:#660">::</span><span style=3D"color:#008">stri=
ng</span><span style=3D"color:#660">(</span><span style=3D"color:#080">&quo=
t;foo"</span><span style=3D"color:#660">);</span><span style=3D"color:=
#000"><br><br>=C2=A0 =C2=A0 </span><span style=3D"color:#800">// ensure the=
string is deleted if std::string_view construction throws =C2=A0 =C2=A0</s=
pan><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"colo=
r:#008">auto</span><span style=3D"color:#000"> str_deleter </span><span sty=
le=3D"color:#660">=3D</span><span style=3D"color:#000"> std</span><span sty=
le=3D"color:#660">::</span><span style=3D"color:#000">make_scope_exit</span=
><span style=3D"color:#660">([</span><span style=3D"color:#000">p</span><sp=
an style=3D"color:#660">]{</span><span style=3D"color:#000"> p</span><span =
style=3D"color:#660">->~</span><span style=3D"color:#000">std</span><spa=
n style=3D"color:#660">::</span><span style=3D"color:#008">string</span><sp=
an style=3D"color:#660">();</span><span style=3D"color:#000"> </span><span =
style=3D"color:#660">})</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=
=A0 std</span><span style=3D"color:#660">::</span><span style=3D"color:#000=
">string_view sv </span><span style=3D"color:#660">=3D</span><span style=3D=
"color:#000"> std</span><span style=3D"color:#660">::</span><span style=3D"=
color:#000">string_view</span><span style=3D"color:#660">(*</span><span sty=
le=3D"color:#000">p</span><span style=3D"color:#660">);</span><span style=
=3D"color:#000"> </span><span style=3D"color:#800">// no exception guarante=
e for this constructor</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=
=A0 </span><span style=3D"color:#800">// if creation of the string throws, =
the object is not created and don't need to be destroyed</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#800">// T=
he flag will not be set in that case as the exception is not caught</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#66=
0">*</span><span style=3D"color:#008">static_cast</span><span style=3D"colo=
r:#660"><</span><span style=3D"color:#008">bool</span><span style=3D"col=
or:#660">*>(</span><span style=3D"color:#000">stack_p </span><span style=
=3D"color:#660">+</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#800">/* __lazy_executed offset */</span><span style=3D"color:#660">)<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#660">=3D</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#008">true</span=
><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 <br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><sp=
an style=3D"color:#000"> sv</span><span style=3D"color:#660">;</span><span =
style=3D"color:#000"> </span><span style=3D"color:#800">// "NRVO"=
is mandatory here</span><span style=3D"color:#000"><br>=C2=A0 </span><span=
style=3D"color:#660">}</span><span style=3D"color:#000"><br><br>=C2=A0 </s=
pan><span style=3D"color:#800">// call to print_lazy</span><span style=3D"c=
olor:#000"><br>=C2=A0 print_lazy</span><span style=3D"color:#660">(&</s=
pan><span style=3D"color:#000">__lazy</span><span style=3D"color:#660">,</s=
pan><span style=3D"color:#000"> __builtin_stack_address</span><span style=
=3D"color:#660">(</span><span style=3D"color:#066">0</span><span style=3D"c=
olor:#660">));</span><span style=3D"color:#000"><br><br>=C2=A0 </span><span=
style=3D"color:#800">// destroy the temporary string:</span><span style=3D=
"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">if</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">__lazy_executed</span><span style=3D"color:#660">)</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">{</span><span s=
tyle=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">sta=
tic_cast</span><span style=3D"color:#660"><</span><span style=3D"color:#=
000">std</span><span style=3D"color:#660">::</span><span style=3D"color:#00=
8">string</span><span style=3D"color:#660">*>(</span><span style=3D"colo=
r:#000">__<wbr>lazy_str_storage</span><span style=3D"color:#660">)->~</s=
pan><span style=3D"color:#000">std</span><span style=3D"color:#660">::</spa=
n><span style=3D"color:#008">strin<wbr>g</span><span style=3D"color:#660">(=
);</span><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:=
#660">}</span><span style=3D"color:#000"><br></span><span style=3D"color:#6=
60">}</span><span style=3D"color:#000"><br></span></div></code></div></div>=
<div>Of course, this would be generated by the compiler and it would not ne=
ed to be achievable with the same efficiency if written by hand (the NRVO h=
ere is trivial to do for the compiler in this case).</div><div>Also, this i=
s an implementation example to show it is possible, but other implementatio=
ns with the same guarantees would also be possible.</div><div><br></div><di=
v>I hope this little explanation will make things clearer...<br></div></div=
></blockquote><div><br></div><div>I screwed up the exception handling, scop=
e_exit will destroy=C2=A0 std::string even if it doesn't throw, which i=
s not what we want.</div><div>Here is the example fixed:<br></div><div><div=
style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187,=
187); border-style: solid; border-width: 1px; overflow-wrap: break-word;" =
class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subprettypr=
int"><div><div style=3D"background-color:rgb(250,250,250);border-color:rgb(=
187,187,187);border-style:solid;border-width:1px"><code><div><span style=3D=
"color:#008"><span style=3D"color: #008;" class=3D"styled-by-prettify">void=
</span></span><span style=3D"color:#000"><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> print_lazy</span></span><span style=3D"color:#660"=
><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span></span><=
span style=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">std</span></span><span style=3D"color:#660"><span style=3D"color: =
#660;" class=3D"styled-by-prettify">::</span></span><span style=3D"color:#0=
00"><span style=3D"color: #000;" class=3D"styled-by-prettify">string_view <=
/span></span><span style=3D"color:#660"><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(*</span></span><span style=3D"color:#000"><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">sv_expr</span></span><spa=
n style=3D"color:#660"><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">)(</span></span><span style=3D"color:#008"><span style=3D"color: #008=
;" class=3D"styled-by-prettify">void</span></span><span style=3D"color:#660=
"><span style=3D"color: #660;" class=3D"styled-by-prettify">*),</span></spa=
n><span style=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span></span><span style=3D"color:#008"><span style=3D"color:=
#008;" class=3D"styled-by-prettify">void</span></span><span style=3D"color=
:#660"><span style=3D"color: #660;" class=3D"styled-by-prettify">*</span></=
span><span style=3D"color:#000"><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> stack_p</span></span><span style=3D"color:#660"><span style=
=3D"color: #660;" class=3D"styled-by-prettify">)</span></span><span style=
=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span></span><span style=3D"color:#660"><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span></span><span style=3D"color:#000"><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 std</span></spa=
n><span style=3D"color:#660"><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">::</span></span><span style=3D"color:#000"><span style=3D"color=
: #000;" class=3D"styled-by-prettify">cout </span></span><span style=3D"col=
or:#660"><span style=3D"color: #660;" class=3D"styled-by-prettify"><<=
</span></span><span style=3D"color:#000"><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> sv_expr</span></span><span style=3D"color:#660"><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">(</span></span><spa=
n style=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">stack_p</span></span><span style=3D"color:#660"><span style=3D"color:=
#660;" class=3D"styled-by-prettify">)</span></span><span style=3D"color:#0=
00"><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span></spa=
n><span style=3D"color:#660"><span style=3D"color: #660;" class=3D"styled-b=
y-prettify"><<</span></span><span style=3D"color:#000"><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> std</span></span><span style=
=3D"color:#660"><span style=3D"color: #660;" class=3D"styled-by-prettify">:=
:</span></span><span style=3D"color:#000"><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">endl</span></span><span style=3D"color:#660"><span=
style=3D"color: #660;" class=3D"styled-by-prettify">;</span></span><span s=
tyle=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span></span><span style=3D"color:#800"><span style=3D"color: #800;" c=
lass=3D"styled-by-prettify">// no lifetime management here</span></span><sp=
an style=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br></span></span><span style=3D"color:#660"><span style=3D"color: #=
660;" class=3D"styled-by-prettify">}</span></span><span style=3D"color:#000=
"><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span>=
</span><span style=3D"color:#008"><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">void</span></span><span style=3D"color:#000"><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> foo1</span></span><span sty=
le=3D"color:#660"><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>()</span></span><span style=3D"color:#000"><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span></span><span style=3D"color:#660"><span =
style=3D"color: #660;" class=3D"styled-by-prettify">{</span></span><span st=
yle=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br>=C2=A0 </span></span><span style=3D"color:#800"><span style=3D"color:=
#800;" class=3D"styled-by-prettify">// lazy parameter storage</span></span=
><span style=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br>=C2=A0 </span></span><span style=3D"color:#008"><span style=
=3D"color: #008;" class=3D"styled-by-prettify">bool</span></span><span styl=
e=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-prettify">=
__lazy_executed </span></span><span style=3D"color:#660"><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">=3D</span></span><span style=3D"co=
lor:#000"><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
></span><span style=3D"color:#008"><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">false</span></span><span style=3D"color:#660"><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span></span><span style=
=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br>=C2=A0 alignas</span></span><span style=3D"color:#660"><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">(</span></span><span style=3D"colo=
r:#008"><span style=3D"color: #008;" class=3D"styled-by-prettify">alignof</=
span></span><span style=3D"color:#660"><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span></span><span style=3D"color:#000"><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">std</span></span><span sty=
le=3D"color:#660"><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>::</span></span><span style=3D"color:#008"><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">string</span></span><span style=3D"color:#660"><=
span style=3D"color: #660;" class=3D"styled-by-prettify">))</span></span><s=
pan style=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> std</span></span><span style=3D"color:#660"><span style=3D"color: =
#660;" class=3D"styled-by-prettify">::</span></span><span style=3D"color:#0=
08"><span style=3D"color: #008;" class=3D"styled-by-prettify">byte</span></=
span><span style=3D"color:#000"><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> __lazy_str_storage</span></span><span style=3D"color:#660">=
<span style=3D"color: #660;" class=3D"styled-by-prettify">[</span></span><s=
pan style=3D"color:#008"><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">sizeof</span></span><span style=3D"color:#660"><span style=3D"color=
: #660;" class=3D"styled-by-prettify">(</span></span><span style=3D"color:#=
000"><span style=3D"color: #000;" class=3D"styled-by-prettify">std</span></=
span><span style=3D"color:#660"><span style=3D"color: #660;" class=3D"style=
d-by-prettify">:</span><wbr><span style=3D"color: #660;" class=3D"styled-by=
-prettify">:</span></span><span style=3D"color:#008"><span style=3D"color: =
#008;" class=3D"styled-by-prettify">string</span></span><span style=3D"colo=
r:#660"><span style=3D"color: #660;" class=3D"styled-by-prettify">)];</span=
></span><span style=3D"color:#000"><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br><br>=C2=A0 </span></span><span style=3D"color:#800"><=
span style=3D"color: #800;" class=3D"styled-by-prettify">// lazy parameter =
executor</span></span><span style=3D"color:#000"><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 std</span></span><span style=3D"=
color:#660"><span style=3D"color: #660;" class=3D"styled-by-prettify">::</s=
pan></span><span style=3D"color:#000"><span style=3D"color: #000;" class=3D=
"styled-by-prettify">string_view __lazy</span></span><span style=3D"color:#=
660"><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span></sp=
an><span style=3D"color:#008"><span style=3D"color: #008;" class=3D"styled-=
by-prettify">void</span></span><span style=3D"color:#660"><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">*</span></span><span style=3D"colo=
r:#000"><span style=3D"color: #000;" class=3D"styled-by-prettify"> stack_p<=
/span></span><span style=3D"color:#660"><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)</span></span><span style=3D"color:#000"><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span></span><span style=
=3D"color:#660"><span style=3D"color: #660;" class=3D"styled-by-prettify">{=
</span></span><span style=3D"color:#000"><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 std</span></span><span style=3D"c=
olor:#660"><span style=3D"color: #660;" class=3D"styled-by-prettify">::</sp=
an></span><span style=3D"color:#008"><span style=3D"color: #008;" class=3D"=
styled-by-prettify">string</span></span><span style=3D"color:#660"><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">*</span></span><span styl=
e=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-prettify">=
p </span></span><span style=3D"color:#660"><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">=3D</span></span><span style=3D"color:#000"><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span></span><span =
style=3D"color:#008"><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">new</span></span><span style=3D"color:#660"><span style=3D"color: #660;=
" class=3D"styled-by-prettify">(</span></span><span style=3D"color:#000"><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">stack_p </span></sp=
an><span style=3D"color:#660"><span style=3D"color: #660;" class=3D"styled-=
by-prettify">+</span></span><span style=3D"color:#000"><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span></span><span style=3D"color:#=
800"><span style=3D"color: #800;" class=3D"styled-by-prettify">/* __lazy_st=
r_storage offset */</span></span><span style=3D"color:#660"><span style=3D"=
color: #660;" class=3D"styled-by-prettify">)</span></span><span style=3D"co=
lor:#000"><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</s=
pan></span><span style=3D"color:#660"><span style=3D"color: #660;" class=3D=
"styled-by-prettify">::</span></span><span style=3D"color:#008"><span style=
=3D"color: #008;" class=3D"styled-by-prettify">string</span></span><span st=
yle=3D"color:#660"><span style=3D"color: #660;" class=3D"styled-by-prettify=
">(</span></span><span style=3D"color:#080"><span style=3D"color: #080;" cl=
ass=3D"styled-by-prettify">"foo"</span></span><span style=3D"colo=
r:#660"><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span>=
</span><span style=3D"color:#000"><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br><br>=C2=A0 =C2=A0 </span></span><span style=3D"color:#=
800"><span style=3D"color: #800;" class=3D"styled-by-prettify">// ensure th=
e string is deleted if std::string_view construction throws</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">try</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: #000;" class=3D"styled-by-prettify"></span></span><span style=3D=
"color:#800"><span style=3D"color: #000;" class=3D"styled-by-prettify"><cod=
e class=3D"prettyprint"><code><span style=3D"color:#000"><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">std</span></span><span style=3D"col=
or:#660"><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span=
></span><span style=3D"color:#000"><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">string_view sv </span></span><span style=3D"color:#660"><=
span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span></span><=
span style=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> std</span></span><span style=3D"color:#660"><span style=3D"color:=
#660;" class=3D"styled-by-prettify">::</span></span><span style=3D"color:#=
000"><span style=3D"color: #000;" class=3D"styled-by-prettify">string_view<=
/span></span><span style=3D"color:#660"><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(*</span></span><span style=3D"color:#000"><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">p</span></span><span styl=
e=3D"color:#660"><span style=3D"color: #660;" class=3D"styled-by-prettify">=
);</span></span><span style=3D"color:#000"><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span></span><span style=3D"color:#800"><span s=
tyle=3D"color: #800;" class=3D"styled-by-prettify">// no exception guarante=
e for this constructor</span></span><span style=3D"color:#000"><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span></span></code></c=
ode>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">catch</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=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 p</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">->~</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">std</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">string</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">();</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">throw</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">}</span></span><span style=3D"color:#000"><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0 </=
span></span><span style=3D"color:#800"><span style=3D"color: #800;" class=
=3D"styled-by-prettify">// if creation of the string throws, the object is =
not created and don't need to be destroyed</span></span><span style=3D"=
color:#000"><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 </span></span><span style=3D"color:#800"><span style=3D"color=
: #800;" class=3D"styled-by-prettify">// The flag will not be set in that c=
ase as the exception is not caught</span></span><span style=3D"color:#000">=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0=
</span></span><span style=3D"color:#660"><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">*</span></span><span style=3D"color:#008"><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">static_cast</span></span>=
<span style=3D"color:#660"><span style=3D"color: #660;" class=3D"styled-by-=
prettify"><</span></span><span style=3D"color:#008"><span style=3D"color=
: #008;" class=3D"styled-by-prettify">bool</span></span><span style=3D"colo=
r:#660"><span style=3D"color: #660;" class=3D"styled-by-prettify">*>(</s=
pan></span><span style=3D"color:#000"><span style=3D"color: #000;" class=3D=
"styled-by-prettify">stack_p </span></span><span style=3D"color:#660"><span=
style=3D"color: #660;" class=3D"styled-by-prettify">+</span></span><span s=
tyle=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span></span><span style=3D"color:#800"><span style=3D"color: #800;" c=
lass=3D"styled-by-prettify">/* __lazy_executed offset */</span></span><span=
style=3D"color:#660"><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">)</span></span><span style=3D"color:#000"><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> </span></span><span style=3D"color:#660"><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span></span><sp=
an style=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span></span><span style=3D"color:#008"><span style=3D"color: #008=
;" class=3D"styled-by-prettify">true</span></span><span style=3D"color:#660=
"><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span></span>=
<span style=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 </span></span><span style=3D"=
color:#008"><span style=3D"color: #008;" class=3D"styled-by-prettify">retur=
n</span></span><span style=3D"color:#000"><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> sv</span></span><span style=3D"color:#660"><span =
style=3D"color: #660;" class=3D"styled-by-prettify">;</span></span><span st=
yle=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span></span><span style=3D"color:#800"><span style=3D"color: #800;" cl=
ass=3D"styled-by-prettify">// "NRVO" is mandatory here</span></sp=
an><span style=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br>=C2=A0 </span></span><span style=3D"color:#660"><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">}</span></span><span style=
=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br><br>=C2=A0 </span></span><span style=3D"color:#800"><span style=3D"color=
: #800;" class=3D"styled-by-prettify">// call to print_lazy</span></span><s=
pan style=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br>=C2=A0 print_lazy</span></span><span style=3D"color:#660"><span=
style=3D"color: #660;" class=3D"styled-by-prettify">(&</span></span><s=
pan style=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify">__lazy</span></span><span style=3D"color:#660"><span style=3D"color=
: #660;" class=3D"styled-by-prettify">,</span></span><span style=3D"color:#=
000"><span style=3D"color: #000;" class=3D"styled-by-prettify"> __builtin_s=
tack_address</span></span><span style=3D"color:#660"><span style=3D"color: =
#660;" class=3D"styled-by-prettify">(</span></span><span style=3D"color:#06=
6"><span style=3D"color: #066;" class=3D"styled-by-prettify">0</span></span=
><span style=3D"color:#660"><span style=3D"color: #660;" class=3D"styled-by=
-prettify">));</span></span><span style=3D"color:#000"><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 </span></span><span st=
yle=3D"color:#800"><span style=3D"color: #800;" class=3D"styled-by-prettify=
">// destroy the temporary string:</span></span><span style=3D"color:#000">=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span=
></span><span style=3D"color:#008"><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">if</span></span><span style=3D"color:#000"><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span></span><span style=3D"c=
olor:#660"><span style=3D"color: #660;" class=3D"styled-by-prettify">(</spa=
n></span><span style=3D"color:#000"><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">__lazy_executed</span></span><span style=3D"color:#660">=
<span style=3D"color: #660;" class=3D"styled-by-prettify">)</span></span><s=
pan style=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span></span><span style=3D"color:#660"><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">{</span></span><span style=3D"color:#000">=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0=
</span></span><span style=3D"color:#008"><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">static_cast</span></span><span style=3D"color:#660=
"><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span></sp=
an><span style=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-=
by-prettify">std</span></span><span style=3D"color:#660"><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">::</span></span><span style=3D"colo=
r:#008"><span style=3D"color: #008;" class=3D"styled-by-prettify">string</s=
pan></span><span style=3D"color:#660"><span style=3D"color: #660;" class=3D=
"styled-by-prettify">*>(</span></span><span style=3D"color:#000"><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">__</span><wbr><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">lazy_str_storage</span></sp=
an><span style=3D"color:#660"><span style=3D"color: #660;" class=3D"styled-=
by-prettify">)->~</span></span><span style=3D"color:#000"><span style=3D=
"color: #000;" class=3D"styled-by-prettify">std</span></span><span style=3D=
"color:#660"><span style=3D"color: #660;" class=3D"styled-by-prettify">::</=
span></span><span style=3D"color:#008"><span style=3D"color: #008;" class=
=3D"styled-by-prettify">strin</span><wbr><span style=3D"color: #008;" class=
=3D"styled-by-prettify">g</span></span><span style=3D"color:#660"><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">();</span></span><span sty=
le=3D"color:#000"><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br>=C2=A0 </span></span><span style=3D"color:#660"><span style=3D"color: =
#660;" class=3D"styled-by-prettify">}</span></span><span style=3D"color:#00=
0"><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></s=
pan><span style=3D"color:#660"><span style=3D"color: #660;" class=3D"styled=
-by-prettify">}</span></span><span style=3D"color:#000"><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br></span></span></div></code></div=
></div></div></code></div><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" 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/b12791de-64ad-4641-b0c0-341f5997cb6d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b12791de-64ad-4641-b0c0-341f5997cb6d=
%40isocpp.org</a>.<br />
------=_Part_43477_1435354691.1527670253870--
------=_Part_43476_1960782291.1527670253868--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 30 May 2018 10:44:52 +0100
Raw View
--000000000000563111056d6934ad
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Wed, 30 May 2018, 09:40 , <florian.csdt@gmail.com> wrote:
>
>
> Le mercredi 30 mai 2018 01:22:11 UTC+2, Edward Catmur a =C3=A9crit :
>>
>>
>>
>> On Tue, 29 May 2018, 23:03 Bengt Gustafsson, <bengt.gu...@beamways.com>
>> wrote:
>>
>>> @florian: Yes, good point: The fact that you don't need a "already
>>> evaluated" flag for simple expressions clearly points to the fact that =
the
>>> caller side should handle the flag, i.e. the callee should just call th=
e
>>> function in case it needs the value. The function can elect to use a fl=
ag
>>> or re-evalutate if it can figure out that runtime cost is low, no side
>>> effects occur and no temporary destructors to call. Using thunks to adj=
ust
>>> stack frame offsets is probably wise as it is going to be fairly rare t=
hat
>>> forwarding occurs (especially in multiple levels).
>>>
>>> @Nicol: Prohibiting using a lazy parameter more than once seems overly
>>> restrictive and very error prone, especially if no diagnostic is requir=
ed.
>>> Furthermore the caller must keep track of whether the function was call=
ed
>>> anyway to handle temporary destruction properly.
>>>
>>
>> In the proposal under discussion, there is no caching of the result of
>> the evaluation of the passed in expression and so no flag required and n=
o
>> destructor call. Multiple use results in multiple evaluation of the
>> initializer expression, which may result in UB if the evaluation of the
>> expression falsifies its own preconditions (e.g. moving out a container =
or
>> smart pointer that is required to be non empty).
>>
>
> The problem here is not caching the result. If you want to evaluate the
> expression multiple times, then passing an actual callable object would b=
e
> preferable. So caching is not needed.
> The real problem is temporaries lifetime. Let me give you an example:
> void print(std::string_view sv) { std::cout << sv << std::endl; }
> void print_lazy([] -> std::string_view sv) { std::cout << sv() << std::
> endl; }
>
> void foo0() {
> print(std::string("foo")); // ok: temporary string is kept alive until
> after the execution of print
> }
> void foo1() {
> print_lazy(std::string("foo")); // std::string is generated within
> "evaluation function" and cannot be kept alive until after the execution =
of
> print_lazy
> }
> void foo2() {
> print([]() -> std::string_view { return std::string("foo"); }) // same
> issue as above, but made explicit for better understanding
> }
>
> If temporaries are destroyed by the "evaluation function", print and
> print_lazy cannot be semantically equivalent, and lazy parameters would
> bring many lifetime issues that are not desirable.
> If foo0 is correct (and it is), then foo1 should also be correct, but thi=
s
> cannot be if temporary lifetime is bound to the "evaluation function"
>
> The idea was the temporaries use the caller storage (in the caller stack
> frame), and are destroyed by the caller after the callee execution.
> Here we would need to store a flag for the caller to know if the
> temporaries need to be destroyed or not.
>
Thanks, that's very clear. So the same ABI can still be used (the callee
does not need to know whether the expression involves temporaries), but
because an evaluation may use stack space in the caller, the callee is
strictly forbidden from evaluating the expression more than once. This
would be UB so a check would be emitted in debug builds and omitted in
optimized release builds.
If multiple evaluation were really desired, a different ABI would be
required such that the callee could supply scratch stack space to the
evaluation and invoke code to destroy temporaries. But I'm not aware of any
use cases for multiple evaluation.
Here could be how the compiler generates print_lazy and foo1:
> void print_lazy(std::string_view (*sv_expr)(void*), void* stack_p) {
> std::cout << sv_expr(stack_p) << std::endl; // no lifetime management
> here
> }
>
> void foo1() {
> // lazy parameter storage
> bool __lazy_executed =3D false;
> alignas(alignof(std::string)) std::byte __lazy_str_storage[sizeof(std::
> string)];
>
> // lazy parameter executor
> std::string_view __lazy(void* stack_p) {
> std::string* p =3D new(stack_p + /* __lazy_str_storage offset */) std=
::
> string("foo");
>
> // ensure the string is deleted if std::string_view construction
> throws
> auto str_deleter =3D std::make_scope_exit([p]{ p->~std::string(); })
>
> std::string_view sv =3D std::string_view(*p); // no exception guarant=
ee
> for this constructor
>
> // if creation of the string throws, the object is not created and
> don't need to be destroyed
> // The flag will not be set in that case as the exception is not
> caught
> *static_cast<bool*>(stack_p + /* __lazy_executed offset */) =3D true;
>
> return sv; // "NRVO" is mandatory here
> }
>
> // call to print_lazy
> print_lazy(&__lazy, __builtin_stack_address(0));
>
> // destroy the temporary string:
> if (__lazy_executed) {
> static_cast<std::string*>(__lazy_str_storage)->~std::string();
> }
> }
> Of course, this would be generated by the compiler and it would not need
> to be achievable with the same efficiency if written by hand (the NRVO he=
re
> is trivial to do for the compiler in this case).
> Also, this is an implementation example to show it is possible, but other
> implementations with the same guarantees would also be possible.
>
> I hope this little explanation will make things clearer...
>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/=
unsubscribe
> .
> To unsubscribe from this group and all its topics, 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/e79281d1-55a=
4-41f0-8f42-95050c8ec679%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e79281d1-55=
a4-41f0-8f42-95050c8ec679%40isocpp.org?utm_medium=3Demail&utm_source=3Dfoot=
er>
> .
>
--=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/CAJnLdOYy306AQcJg0btk48S1h6oFJQz27tk744KnCVEb%3D=
nnQ-g%40mail.gmail.com.
--000000000000563111056d6934ad
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"auto"><div><br><br><div class=3D"gmail_quote"><div dir=3D"ltr">=
On Wed, 30 May 2018, 09:40 , <<a href=3D"mailto:florian.csdt@gmail.com">=
florian.csdt@gmail.com</a>> wrote:<br></div><blockquote class=3D"gmail_q=
uote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1e=
x"><div dir=3D"ltr"><br><br>Le mercredi 30 mai 2018 01:22:11 UTC+2, Edward =
Catmur a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin=
:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"auto"><div><br><br><div class=3D"gmail_quote"><div dir=3D"ltr">On Tue, =
29 May 2018, 23:03 Bengt Gustafsson, <<a rel=3D"nofollow noreferrer">ben=
gt.gu...@beamways.com</a>> wrote:<br></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr">@florian: Yes, good point: The fact that you don't n=
eed a "already evaluated" flag for simple expressions clearly poi=
nts to the fact that the caller side should handle the flag, i.e. the calle=
e should just call the function in case it needs the value. The function ca=
n elect to use a flag or re-evalutate if it can figure out that runtime cos=
t is low, no side effects occur and no temporary destructors to call. Using=
thunks to adjust stack frame offsets is probably wise as it is going to be=
fairly rare that forwarding occurs (especially in multiple levels).<div><d=
iv><br></div><div>@Nicol: Prohibiting using a lazy parameter more than once=
seems overly restrictive and very error prone, especially if no diagnostic=
is required. Furthermore the caller must keep track of whether the functio=
n was called anyway to handle temporary destruction properly.<br></div></di=
v></div></blockquote></div></div><div dir=3D"auto"><br></div><div dir=3D"au=
to">In the proposal under discussion, there is no caching of the result of =
the evaluation of the passed in expression and so no flag required and no d=
estructor call. Multiple use results in multiple evaluation of the initiali=
zer expression, which may result in UB if the evaluation of the expression =
falsifies its own preconditions (e.g. moving out a container or smart point=
er that is required to be non empty). <br></div></div></blockquote><div>=C2=
=A0</div><div>The problem here is not caching the result. If you want to ev=
aluate the expression multiple times, then passing an actual callable objec=
t would be preferable. So caching is not needed.<br></div><div>The real pro=
blem is temporaries lifetime. Let me give you an example:</div><div><div st=
yle=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bord=
er-style:solid;border-width:1px" class=3D"m_6200674375113368750prettyprint"=
><code class=3D"m_6200674375113368750prettyprint"><div class=3D"m_620067437=
5113368750subprettyprint"><span style=3D"color:#008" class=3D"m_62006743751=
13368750styled-by-prettify">void</span><span style=3D"color:#000" class=3D"=
m_6200674375113368750styled-by-prettify"> </span><span style=3D"color:#008"=
class=3D"m_6200674375113368750styled-by-prettify">print</span><span style=
=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify">(</span><=
span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify"=
>std</span><span style=3D"color:#660" class=3D"m_6200674375113368750styled-=
by-prettify">::</span><span style=3D"color:#000" class=3D"m_620067437511336=
8750styled-by-prettify">string_view sv</span><span style=3D"color:#660" cla=
ss=3D"m_6200674375113368750styled-by-prettify">)</span><span style=3D"color=
:#000" class=3D"m_6200674375113368750styled-by-prettify"> </span><span styl=
e=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify">{</span>=
<span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify=
"> std</span><span style=3D"color:#660" class=3D"m_6200674375113368750style=
d-by-prettify">::</span><span style=3D"color:#000" class=3D"m_6200674375113=
368750styled-by-prettify">cout </span><span style=3D"color:#660" class=3D"m=
_6200674375113368750styled-by-prettify"><<</span><span style=3D"color=
:#000" class=3D"m_6200674375113368750styled-by-prettify"> sv </span><span s=
tyle=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify"><&=
lt;</span><span style=3D"color:#000" class=3D"m_6200674375113368750styled-b=
y-prettify"> std</span><span style=3D"color:#660" class=3D"m_62006743751133=
68750styled-by-prettify">::</span><span style=3D"color:#000" class=3D"m_620=
0674375113368750styled-by-prettify">endl</span><span style=3D"color:#660" c=
lass=3D"m_6200674375113368750styled-by-prettify">;</span><span style=3D"col=
or:#000" class=3D"m_6200674375113368750styled-by-prettify"> </span><span st=
yle=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify">}</spa=
n><span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-pretti=
fy"><br></span><span style=3D"color:#008" class=3D"m_6200674375113368750sty=
led-by-prettify">void</span><span style=3D"color:#000" class=3D"m_620067437=
5113368750styled-by-prettify"> print_lazy</span><span style=3D"color:#660" =
class=3D"m_6200674375113368750styled-by-prettify">([]</span><span style=3D"=
color:#000" class=3D"m_6200674375113368750styled-by-prettify"> </span><span=
style=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify">-&g=
t;</span><span style=3D"color:#000" class=3D"m_6200674375113368750styled-by=
-prettify"> std</span><span style=3D"color:#660" class=3D"m_620067437511336=
8750styled-by-prettify">::</span><span style=3D"color:#000" class=3D"m_6200=
674375113368750styled-by-prettify">string_view sv</span><span style=3D"colo=
r:#660" class=3D"m_6200674375113368750styled-by-prettify">)</span><span sty=
le=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify"> </span=
><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettif=
y">{</span><span style=3D"color:#000" class=3D"m_6200674375113368750styled-=
by-prettify"> std</span><span style=3D"color:#660" class=3D"m_6200674375113=
368750styled-by-prettify">::</span><span style=3D"color:#000" class=3D"m_62=
00674375113368750styled-by-prettify">cout </span><span style=3D"color:#660"=
class=3D"m_6200674375113368750styled-by-prettify"><<</span><span sty=
le=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify"> sv</sp=
an><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-prett=
ify">()</span><span style=3D"color:#000" class=3D"m_6200674375113368750styl=
ed-by-prettify"> </span><span style=3D"color:#660" class=3D"m_6200674375113=
368750styled-by-prettify"><<</span><span style=3D"color:#000" class=
=3D"m_6200674375113368750styled-by-prettify"> std</span><span style=3D"colo=
r:#660" class=3D"m_6200674375113368750styled-by-prettify">::</span><span st=
yle=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify">endl</=
span><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-pre=
ttify">;</span><span style=3D"color:#000" class=3D"m_6200674375113368750sty=
led-by-prettify"> </span><span style=3D"color:#660" class=3D"m_620067437511=
3368750styled-by-prettify">}</span><span style=3D"color:#000" class=3D"m_62=
00674375113368750styled-by-prettify"><br><br></span><span style=3D"color:#0=
08" class=3D"m_6200674375113368750styled-by-prettify">void</span><span styl=
e=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify"> foo0</s=
pan><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-pret=
tify">()</span><span style=3D"color:#000" class=3D"m_6200674375113368750sty=
led-by-prettify"> </span><span style=3D"color:#660" class=3D"m_620067437511=
3368750styled-by-prettify">{</span><span style=3D"color:#000" class=3D"m_62=
00674375113368750styled-by-prettify"><br>=C2=A0 </span><span style=3D"color=
:#008" class=3D"m_6200674375113368750styled-by-prettify">print</span><span =
style=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify">(</s=
pan><span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-pret=
tify">std</span><span style=3D"color:#660" class=3D"m_6200674375113368750st=
yled-by-prettify">::</span><span style=3D"color:#008" class=3D"m_6200674375=
113368750styled-by-prettify">string</span><span style=3D"color:#660" class=
=3D"m_6200674375113368750styled-by-prettify">(</span><span style=3D"color:#=
080" class=3D"m_6200674375113368750styled-by-prettify">"foo"</spa=
n><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-pretti=
fy">));</span><span style=3D"color:#000" class=3D"m_6200674375113368750styl=
ed-by-prettify"> </span><span style=3D"color:#800" class=3D"m_6200674375113=
368750styled-by-prettify">// ok: temporary string is kept alive until after=
the execution of print</span><span style=3D"color:#000" class=3D"m_6200674=
375113368750styled-by-prettify"><br></span><span style=3D"color:#660" class=
=3D"m_6200674375113368750styled-by-prettify">}</span><span style=3D"color:#=
000" class=3D"m_6200674375113368750styled-by-prettify"><br></span><span sty=
le=3D"color:#008" class=3D"m_6200674375113368750styled-by-prettify">void</s=
pan><span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-pret=
tify"> foo1</span><span style=3D"color:#660" class=3D"m_6200674375113368750=
styled-by-prettify">()</span><span style=3D"color:#000" class=3D"m_62006743=
75113368750styled-by-prettify"> </span><span style=3D"color:#660" class=3D"=
m_6200674375113368750styled-by-prettify">{</span><span style=3D"color:#000"=
class=3D"m_6200674375113368750styled-by-prettify"><br>=C2=A0 print_lazy</s=
pan><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-pret=
tify">(</span><span style=3D"color:#000" class=3D"m_6200674375113368750styl=
ed-by-prettify">std</span><span style=3D"color:#660" class=3D"m_62006743751=
13368750styled-by-prettify">::</span><span style=3D"color:#008" class=3D"m_=
6200674375113368750styled-by-prettify">string</span><span style=3D"color:#6=
60" class=3D"m_6200674375113368750styled-by-prettify">(</span><span style=
=3D"color:#080" class=3D"m_6200674375113368750styled-by-prettify">"foo=
"</span><span style=3D"color:#660" class=3D"m_6200674375113368750style=
d-by-prettify">));</span><span style=3D"color:#000" class=3D"m_620067437511=
3368750styled-by-prettify"> </span><span style=3D"color:#800" class=3D"m_62=
00674375113368750styled-by-prettify">// std::string is generated within &qu=
ot;evaluation function" and cannot be kept alive until after the execu=
tion of print_lazy</span><span style=3D"color:#000" class=3D"m_620067437511=
3368750styled-by-prettify"><br></span><span style=3D"color:#660" class=3D"m=
_6200674375113368750styled-by-prettify">}</span><span style=3D"color:#000" =
class=3D"m_6200674375113368750styled-by-prettify"><br></span><span style=3D=
"color:#008" class=3D"m_6200674375113368750styled-by-prettify">void</span><=
span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify"=
> foo2</span><span style=3D"color:#660" class=3D"m_6200674375113368750style=
d-by-prettify">()</span><span style=3D"color:#000" class=3D"m_6200674375113=
368750styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_620=
0674375113368750styled-by-prettify">{</span><span style=3D"color:#000" clas=
s=3D"m_6200674375113368750styled-by-prettify"><br>=C2=A0 </span><span style=
=3D"color:#008" class=3D"m_6200674375113368750styled-by-prettify">print</sp=
an><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-prett=
ify">([]()</span><span style=3D"color:#000" class=3D"m_6200674375113368750s=
tyled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_6200674375=
113368750styled-by-prettify">-></span><span style=3D"color:#000" class=
=3D"m_6200674375113368750styled-by-prettify"> std</span><span style=3D"colo=
r:#660" class=3D"m_6200674375113368750styled-by-prettify">::</span><span st=
yle=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify">string=
_view </span><span style=3D"color:#660" class=3D"m_6200674375113368750style=
d-by-prettify">{</span><span style=3D"color:#000" class=3D"m_62006743751133=
68750styled-by-prettify"> </span><span style=3D"color:#008" class=3D"m_6200=
674375113368750styled-by-prettify">return</span><span style=3D"color:#000" =
class=3D"m_6200674375113368750styled-by-prettify"> std</span><span style=3D=
"color:#660" class=3D"m_6200674375113368750styled-by-prettify">::</span><sp=
an style=3D"color:#008" class=3D"m_6200674375113368750styled-by-prettify">s=
tring</span><span style=3D"color:#660" class=3D"m_6200674375113368750styled=
-by-prettify">(</span><span style=3D"color:#080" class=3D"m_620067437511336=
8750styled-by-prettify">"foo"</span><span style=3D"color:#660" cl=
ass=3D"m_6200674375113368750styled-by-prettify">);</span><span style=3D"col=
or:#000" class=3D"m_6200674375113368750styled-by-prettify"> </span><span st=
yle=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify">})</sp=
an><span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prett=
ify"> </span><span style=3D"color:#800" class=3D"m_6200674375113368750style=
d-by-prettify">// same issue as above, but made explicit for better underst=
anding</span><span style=3D"color:#000" class=3D"m_6200674375113368750style=
d-by-prettify"><br></span><span style=3D"color:#660" class=3D"m_62006743751=
13368750styled-by-prettify">}</span><span style=3D"color:#000" class=3D"m_6=
200674375113368750styled-by-prettify"><br></span></div></code></div><br>If =
temporaries are destroyed by the "evaluation function", print and=
print_lazy cannot be semantically equivalent, and lazy parameters would br=
ing many lifetime issues that are not desirable.</div><div>If foo0 is corre=
ct (and it is), then foo1 should also be correct, but this cannot be if tem=
porary lifetime is bound to the "evaluation function"<br></div><d=
iv><br></div><div>The idea was the temporaries use the caller storage (in t=
he caller stack frame), and are destroyed by the caller after the callee ex=
ecution.</div><div>Here we would need to store a flag for the caller to kno=
w if the temporaries need to be destroyed or not.</div></div></blockquote><=
/div></div><div dir=3D"auto"><br></div><div dir=3D"auto">Thanks, that's=
very clear. So the same ABI can still be used (the callee does not need to=
know whether the expression involves temporaries), but because an evaluati=
on may use stack space in the caller, the callee is strictly forbidden from=
evaluating the expression more than once. This would be UB so a check woul=
d be emitted in debug builds and omitted in optimized release builds.=C2=A0=
</div><div dir=3D"auto"><br></div><div dir=3D"auto">If multiple evaluation =
were really desired, a different ABI would be required such that the callee=
could supply scratch stack space to the evaluation and invoke code to dest=
roy temporaries. But I'm not aware of any use cases for multiple evalua=
tion.=C2=A0</div><div dir=3D"auto"><br></div><div dir=3D"auto"><br></div><d=
iv dir=3D"auto"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote=
" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><=
div dir=3D"ltr"><div>Here could be how the compiler generates print_lazy an=
d foo1:</div><div><div style=3D"background-color:rgb(250,250,250);border-co=
lor:rgb(187,187,187);border-style:solid;border-width:1px" class=3D"m_620067=
4375113368750prettyprint"><code class=3D"m_6200674375113368750prettyprint">=
<div class=3D"m_6200674375113368750subprettyprint"><span style=3D"color:#00=
8" class=3D"m_6200674375113368750styled-by-prettify">void</span><span style=
=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify"> print_la=
zy</span><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by=
-prettify">(</span><span style=3D"color:#000" class=3D"m_620067437511336875=
0styled-by-prettify">std</span><span style=3D"color:#660" class=3D"m_620067=
4375113368750styled-by-prettify">::</span><span style=3D"color:#000" class=
=3D"m_6200674375113368750styled-by-prettify">string_view </span><span style=
=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify">(*</span>=
<span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify=
">sv_expr</span><span style=3D"color:#660" class=3D"m_6200674375113368750st=
yled-by-prettify">)(</span><span style=3D"color:#008" class=3D"m_6200674375=
113368750styled-by-prettify">void</span><span style=3D"color:#660" class=3D=
"m_6200674375113368750styled-by-prettify">*),</span><span style=3D"color:#0=
00" class=3D"m_6200674375113368750styled-by-prettify"> </span><span style=
=3D"color:#008" class=3D"m_6200674375113368750styled-by-prettify">void</spa=
n><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-pretti=
fy">*</span><span style=3D"color:#000" class=3D"m_6200674375113368750styled=
-by-prettify"> stack_p</span><span style=3D"color:#660" class=3D"m_62006743=
75113368750styled-by-prettify">)</span><span style=3D"color:#000" class=3D"=
m_6200674375113368750styled-by-prettify"> </span><span style=3D"color:#660"=
class=3D"m_6200674375113368750styled-by-prettify">{</span><span style=3D"c=
olor:#000" class=3D"m_6200674375113368750styled-by-prettify"><br>=C2=A0 std=
</span><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-p=
rettify">::</span><span style=3D"color:#000" class=3D"m_6200674375113368750=
styled-by-prettify">cout </span><span style=3D"color:#660" class=3D"m_62006=
74375113368750styled-by-prettify"><<</span><span style=3D"color:#000"=
class=3D"m_6200674375113368750styled-by-prettify"> sv_expr</span><span sty=
le=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify">(</span=
><span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettif=
y">stack_p</span><span style=3D"color:#660" class=3D"m_6200674375113368750s=
tyled-by-prettify">)</span><span style=3D"color:#000" class=3D"m_6200674375=
113368750styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_=
6200674375113368750styled-by-prettify"><<</span><span style=3D"color:=
#000" class=3D"m_6200674375113368750styled-by-prettify"> std</span><span st=
yle=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify">::</sp=
an><span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prett=
ify">endl</span><span style=3D"color:#660" class=3D"m_6200674375113368750st=
yled-by-prettify">;</span><span style=3D"color:#000" class=3D"m_62006743751=
13368750styled-by-prettify"> </span><span style=3D"color:#800" class=3D"m_6=
200674375113368750styled-by-prettify">// no lifetime management here</span>=
<span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify=
"><br></span><span style=3D"color:#660" class=3D"m_6200674375113368750style=
d-by-prettify">}</span><span style=3D"color:#000" class=3D"m_62006743751133=
68750styled-by-prettify"><br><br></span><span style=3D"color:#008" class=3D=
"m_6200674375113368750styled-by-prettify">void</span><span style=3D"color:#=
000" class=3D"m_6200674375113368750styled-by-prettify"> foo1</span><span st=
yle=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify">()</sp=
an><span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prett=
ify"> </span><span style=3D"color:#660" class=3D"m_6200674375113368750style=
d-by-prettify">{</span><span style=3D"color:#000" class=3D"m_62006743751133=
68750styled-by-prettify"><br>=C2=A0 </span><span style=3D"color:#800" class=
=3D"m_6200674375113368750styled-by-prettify">// lazy parameter storage</spa=
n><span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-pretti=
fy"><br>=C2=A0 </span><span style=3D"color:#008" class=3D"m_620067437511336=
8750styled-by-prettify">bool</span><span style=3D"color:#000" class=3D"m_62=
00674375113368750styled-by-prettify"> __lazy_executed </span><span style=3D=
"color:#660" class=3D"m_6200674375113368750styled-by-prettify">=3D</span><s=
pan style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify">=
</span><span style=3D"color:#008" class=3D"m_6200674375113368750styled-by-=
prettify">false</span><span style=3D"color:#660" class=3D"m_620067437511336=
8750styled-by-prettify">;</span><span style=3D"color:#000" class=3D"m_62006=
74375113368750styled-by-prettify"><br>=C2=A0 alignas</span><span style=3D"c=
olor:#660" class=3D"m_6200674375113368750styled-by-prettify">(</span><span =
style=3D"color:#008" class=3D"m_6200674375113368750styled-by-prettify">alig=
nof</span><span style=3D"color:#660" class=3D"m_6200674375113368750styled-b=
y-prettify">(</span><span style=3D"color:#000" class=3D"m_62006743751133687=
50styled-by-prettify">std</span><span style=3D"color:#660" class=3D"m_62006=
74375113368750styled-by-prettify">::</span><span style=3D"color:#008" class=
=3D"m_6200674375113368750styled-by-prettify">string</span><span style=3D"co=
lor:#660" class=3D"m_6200674375113368750styled-by-prettify">))</span><span =
style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify"> std=
</span><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-p=
rettify">::</span><span style=3D"color:#008" class=3D"m_6200674375113368750=
styled-by-prettify">byte</span><span style=3D"color:#000" class=3D"m_620067=
4375113368750styled-by-prettify"> __lazy_str_storage</span><span style=3D"c=
olor:#660" class=3D"m_6200674375113368750styled-by-prettify">[</span><span =
style=3D"color:#008" class=3D"m_6200674375113368750styled-by-prettify">size=
of</span><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by=
-prettify">(</span><span style=3D"color:#000" class=3D"m_620067437511336875=
0styled-by-prettify">std</span><span style=3D"color:#660" class=3D"m_620067=
4375113368750styled-by-prettify">::</span><span style=3D"color:#008" class=
=3D"m_6200674375113368750styled-by-prettify">string</span><span style=3D"co=
lor:#660" class=3D"m_6200674375113368750styled-by-prettify">)];</span><span=
style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify"><br=
><br>=C2=A0 </span><span style=3D"color:#800" class=3D"m_620067437511336875=
0styled-by-prettify">// lazy parameter executor</span><span style=3D"color:=
#000" class=3D"m_6200674375113368750styled-by-prettify"><br>=C2=A0 std</spa=
n><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-pretti=
fy">::</span><span style=3D"color:#000" class=3D"m_6200674375113368750style=
d-by-prettify">string_view __lazy</span><span style=3D"color:#660" class=3D=
"m_6200674375113368750styled-by-prettify">(</span><span style=3D"color:#008=
" class=3D"m_6200674375113368750styled-by-prettify">void</span><span style=
=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify">*</span><=
span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify"=
> stack_p</span><span style=3D"color:#660" class=3D"m_6200674375113368750st=
yled-by-prettify">)</span><span style=3D"color:#000" class=3D"m_62006743751=
13368750styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_6=
200674375113368750styled-by-prettify">{</span><span style=3D"color:#000" cl=
ass=3D"m_6200674375113368750styled-by-prettify"><br>=C2=A0 =C2=A0 std</span=
><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettif=
y">::</span><span style=3D"color:#008" class=3D"m_6200674375113368750styled=
-by-prettify">string</span><span style=3D"color:#660" class=3D"m_6200674375=
113368750styled-by-prettify">*</span><span style=3D"color:#000" class=3D"m_=
6200674375113368750styled-by-prettify"> p </span><span style=3D"color:#660"=
class=3D"m_6200674375113368750styled-by-prettify">=3D</span><span style=3D=
"color:#000" class=3D"m_6200674375113368750styled-by-prettify"> </span><spa=
n style=3D"color:#008" class=3D"m_6200674375113368750styled-by-prettify">ne=
w</span><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-=
prettify">(</span><span style=3D"color:#000" class=3D"m_6200674375113368750=
styled-by-prettify">stack_p </span><span style=3D"color:#660" class=3D"m_62=
00674375113368750styled-by-prettify">+</span><span style=3D"color:#000" cla=
ss=3D"m_6200674375113368750styled-by-prettify"> </span><span style=3D"color=
:#800" class=3D"m_6200674375113368750styled-by-prettify">/* __lazy_str_stor=
age offset */</span><span style=3D"color:#660" class=3D"m_62006743751133687=
50styled-by-prettify">)</span><span style=3D"color:#000" class=3D"m_6200674=
375113368750styled-by-prettify"> std</span><span style=3D"color:#660" class=
=3D"m_6200674375113368750styled-by-prettify">::</span><span style=3D"color:=
#008" class=3D"m_6200674375113368750styled-by-prettify">string</span><span =
style=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify">(</s=
pan><span style=3D"color:#080" class=3D"m_6200674375113368750styled-by-pret=
tify">"foo"</span><span style=3D"color:#660" class=3D"m_620067437=
5113368750styled-by-prettify">);</span><span style=3D"color:#000" class=3D"=
m_6200674375113368750styled-by-prettify"><br><br>=C2=A0 =C2=A0 </span><span=
style=3D"color:#800" class=3D"m_6200674375113368750styled-by-prettify">// =
ensure the string is deleted if std::string_view construction throws =C2=A0=
=C2=A0</span><span style=3D"color:#000" class=3D"m_6200674375113368750styl=
ed-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008" class=
=3D"m_6200674375113368750styled-by-prettify">auto</span><span style=3D"colo=
r:#000" class=3D"m_6200674375113368750styled-by-prettify"> str_deleter </sp=
an><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-prett=
ify">=3D</span><span style=3D"color:#000" class=3D"m_6200674375113368750sty=
led-by-prettify"> std</span><span style=3D"color:#660" class=3D"m_620067437=
5113368750styled-by-prettify">::</span><span style=3D"color:#000" class=3D"=
m_6200674375113368750styled-by-prettify">make_scope_exit</span><span style=
=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify">([</span>=
<span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify=
">p</span><span style=3D"color:#660" class=3D"m_6200674375113368750styled-b=
y-prettify">]{</span><span style=3D"color:#000" class=3D"m_6200674375113368=
750styled-by-prettify"> p</span><span style=3D"color:#660" class=3D"m_62006=
74375113368750styled-by-prettify">->~</span><span style=3D"color:#000" c=
lass=3D"m_6200674375113368750styled-by-prettify">std</span><span style=3D"c=
olor:#660" class=3D"m_6200674375113368750styled-by-prettify">::</span><span=
style=3D"color:#008" class=3D"m_6200674375113368750styled-by-prettify">str=
ing</span><span style=3D"color:#660" class=3D"m_6200674375113368750styled-b=
y-prettify">();</span><span style=3D"color:#000" class=3D"m_620067437511336=
8750styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_62006=
74375113368750styled-by-prettify">})</span><span style=3D"color:#000" class=
=3D"m_6200674375113368750styled-by-prettify"><br><br>=C2=A0 =C2=A0 std</spa=
n><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-pretti=
fy">::</span><span style=3D"color:#000" class=3D"m_6200674375113368750style=
d-by-prettify">string_view sv </span><span style=3D"color:#660" class=3D"m_=
6200674375113368750styled-by-prettify">=3D</span><span style=3D"color:#000"=
class=3D"m_6200674375113368750styled-by-prettify"> std</span><span style=
=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify">::</span>=
<span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify=
">string_view</span><span style=3D"color:#660" class=3D"m_62006743751133687=
50styled-by-prettify">(*</span><span style=3D"color:#000" class=3D"m_620067=
4375113368750styled-by-prettify">p</span><span style=3D"color:#660" class=
=3D"m_6200674375113368750styled-by-prettify">);</span><span style=3D"color:=
#000" class=3D"m_6200674375113368750styled-by-prettify"> </span><span style=
=3D"color:#800" class=3D"m_6200674375113368750styled-by-prettify">// no exc=
eption guarantee for this constructor</span><span style=3D"color:#000" clas=
s=3D"m_6200674375113368750styled-by-prettify"><br><br>=C2=A0 =C2=A0 </span>=
<span style=3D"color:#800" class=3D"m_6200674375113368750styled-by-prettify=
">// if creation of the string throws, the object is not created and don=
9;t need to be destroyed</span><span style=3D"color:#000" class=3D"m_620067=
4375113368750styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"co=
lor:#800" class=3D"m_6200674375113368750styled-by-prettify">// The flag wil=
l not be set in that case as the exception is not caught</span><span style=
=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color:#660" class=3D"m_6200674375113368750=
styled-by-prettify">*</span><span style=3D"color:#008" class=3D"m_620067437=
5113368750styled-by-prettify">static_cast</span><span style=3D"color:#660" =
class=3D"m_6200674375113368750styled-by-prettify"><</span><span style=3D=
"color:#008" class=3D"m_6200674375113368750styled-by-prettify">bool</span><=
span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify"=
>*>(</span><span style=3D"color:#000" class=3D"m_6200674375113368750styl=
ed-by-prettify">stack_p </span><span style=3D"color:#660" class=3D"m_620067=
4375113368750styled-by-prettify">+</span><span style=3D"color:#000" class=
=3D"m_6200674375113368750styled-by-prettify"> </span><span style=3D"color:#=
800" class=3D"m_6200674375113368750styled-by-prettify">/* __lazy_executed o=
ffset */</span><span style=3D"color:#660" class=3D"m_6200674375113368750sty=
led-by-prettify">)</span><span style=3D"color:#000" class=3D"m_620067437511=
3368750styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_62=
00674375113368750styled-by-prettify">=3D</span><span style=3D"color:#000" c=
lass=3D"m_6200674375113368750styled-by-prettify"> </span><span style=3D"col=
or:#008" class=3D"m_6200674375113368750styled-by-prettify">true</span><span=
style=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify">;</=
span><span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-pre=
ttify"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 </span><span style=3D"color:#008=
" class=3D"m_6200674375113368750styled-by-prettify">return</span><span styl=
e=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify"> sv</spa=
n><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-pretti=
fy">;</span><span style=3D"color:#000" class=3D"m_6200674375113368750styled=
-by-prettify"> </span><span style=3D"color:#800" class=3D"m_620067437511336=
8750styled-by-prettify">// "NRVO" is mandatory here</span><span s=
tyle=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify"><br>=
=C2=A0 </span><span style=3D"color:#660" class=3D"m_6200674375113368750styl=
ed-by-prettify">}</span><span style=3D"color:#000" class=3D"m_6200674375113=
368750styled-by-prettify"><br><br>=C2=A0 </span><span style=3D"color:#800" =
class=3D"m_6200674375113368750styled-by-prettify">// call to print_lazy</sp=
an><span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prett=
ify"><br>=C2=A0 print_lazy</span><span style=3D"color:#660" class=3D"m_6200=
674375113368750styled-by-prettify">(&</span><span style=3D"color:#000" =
class=3D"m_6200674375113368750styled-by-prettify">__lazy</span><span style=
=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify">,</span><=
span style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify"=
> __builtin_stack_address</span><span style=3D"color:#660" class=3D"m_62006=
74375113368750styled-by-prettify">(</span><span style=3D"color:#066" class=
=3D"m_6200674375113368750styled-by-prettify">0</span><span style=3D"color:#=
660" class=3D"m_6200674375113368750styled-by-prettify">));</span><span styl=
e=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify"><br><br>=
=C2=A0 </span><span style=3D"color:#800" class=3D"m_6200674375113368750styl=
ed-by-prettify">// destroy the temporary string:</span><span style=3D"color=
:#000" class=3D"m_6200674375113368750styled-by-prettify"><br>=C2=A0 </span>=
<span style=3D"color:#008" class=3D"m_6200674375113368750styled-by-prettify=
">if</span><span style=3D"color:#000" class=3D"m_6200674375113368750styled-=
by-prettify"> </span><span style=3D"color:#660" class=3D"m_6200674375113368=
750styled-by-prettify">(</span><span style=3D"color:#000" class=3D"m_620067=
4375113368750styled-by-prettify">__lazy_executed</span><span style=3D"color=
:#660" class=3D"m_6200674375113368750styled-by-prettify">)</span><span styl=
e=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify"> </span>=
<span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify=
">{</span><span style=3D"color:#000" class=3D"m_6200674375113368750styled-b=
y-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008" class=3D"m_=
6200674375113368750styled-by-prettify">static_cast</span><span style=3D"col=
or:#660" class=3D"m_6200674375113368750styled-by-prettify"><</span><span=
style=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify">std=
</span><span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-p=
rettify">::</span><span style=3D"color:#008" class=3D"m_6200674375113368750=
styled-by-prettify">string</span><span style=3D"color:#660" class=3D"m_6200=
674375113368750styled-by-prettify">*>(</span><span style=3D"color:#000" =
class=3D"m_6200674375113368750styled-by-prettify">__lazy_str_storage</span>=
<span style=3D"color:#660" class=3D"m_6200674375113368750styled-by-prettify=
">)->~</span><span style=3D"color:#000" class=3D"m_6200674375113368750st=
yled-by-prettify">std</span><span style=3D"color:#660" class=3D"m_620067437=
5113368750styled-by-prettify">::</span><span style=3D"color:#008" class=3D"=
m_6200674375113368750styled-by-prettify">string</span><span style=3D"color:=
#660" class=3D"m_6200674375113368750styled-by-prettify">();</span><span sty=
le=3D"color:#000" class=3D"m_6200674375113368750styled-by-prettify"><br>=C2=
=A0 </span><span style=3D"color:#660" class=3D"m_6200674375113368750styled-=
by-prettify">}</span><span style=3D"color:#000" class=3D"m_6200674375113368=
750styled-by-prettify"><br></span><span style=3D"color:#660" class=3D"m_620=
0674375113368750styled-by-prettify">}</span><span style=3D"color:#000" clas=
s=3D"m_6200674375113368750styled-by-prettify"><br></span></div></code></div=
></div><div>Of course, this would be generated by the compiler and it would=
not need to be achievable with the same efficiency if written by hand (the=
NRVO here is trivial to do for the compiler in this case).</div><div>Also,=
this is an implementation example to show it is possible, but other implem=
entations with the same guarantees would also be possible.</div><div><br></=
div><div>I hope this little explanation will make things clearer...<br></di=
v></div>
<p></p>
-- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/unsubscribe" target=3D"_blan=
k" rel=3D"noreferrer">https://groups.google.com/a/isocpp.org/d/topic/std-pr=
oposals/5oUZysJB4HE/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_blank" rel=3D"n=
oreferrer">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank" rel=3D"noreferrer">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/e79281d1-55a4-41f0-8f42-95050c8ec679%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank" =
rel=3D"noreferrer">https://groups.google.com/a/isocpp.org/d/msgid/std-propo=
sals/e79281d1-55a4-41f0-8f42-95050c8ec679%40isocpp.org</a>.<br>
</blockquote></div></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/CAJnLdOYy306AQcJg0btk48S1h6oFJQz27tk7=
44KnCVEb%3DnnQ-g%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdOYy306AQc=
Jg0btk48S1h6oFJQz27tk744KnCVEb%3DnnQ-g%40mail.gmail.com</a>.<br />
--000000000000563111056d6934ad--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 30 May 2018 06:29:38 -0700 (PDT)
Raw View
------=_Part_43561_1102200084.1527686978885
Content-Type: multipart/alternative;
boundary="----=_Part_43562_564863776.1527686978885"
------=_Part_43562_564863776.1527686978885
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Wednesday, May 30, 2018 at 4:40:45 AM UTC-4, floria...@gmail.com wrote:
>
> Le mercredi 30 mai 2018 01:22:11 UTC+2, Edward Catmur a =C3=A9crit :
>>
>>
>>
>> On Tue, 29 May 2018, 23:03 Bengt Gustafsson, <bengt.gu...@beamways.com>=
=20
>> wrote:
>>
>>> @florian: Yes, good point: The fact that you don't need a "already=20
>>> evaluated" flag for simple expressions clearly points to the fact that =
the=20
>>> caller side should handle the flag, i.e. the callee should just call th=
e=20
>>> function in case it needs the value. The function can elect to use a fl=
ag=20
>>> or re-evalutate if it can figure out that runtime cost is low, no side=
=20
>>> effects occur and no temporary destructors to call. Using thunks to adj=
ust=20
>>> stack frame offsets is probably wise as it is going to be fairly rare t=
hat=20
>>> forwarding occurs (especially in multiple levels).
>>>
>>> @Nicol: Prohibiting using a lazy parameter more than once seems overly=
=20
>>> restrictive and very error prone, especially if no diagnostic is requir=
ed.=20
>>> Furthermore the caller must keep track of whether the function was call=
ed=20
>>> anyway to handle temporary destruction properly.
>>>
>>
>> In the proposal under discussion, there is no caching of the result of=
=20
>> the evaluation of the passed in expression and so no flag required and n=
o=20
>> destructor call. Multiple use results in multiple evaluation of the=20
>> initializer expression, which may result in UB if the evaluation of the=
=20
>> expression falsifies its own preconditions (e.g. moving out a container =
or=20
>> smart pointer that is required to be non empty).=20
>>
> =20
> The problem here is not caching the result. If you want to evaluate the=
=20
> expression multiple times, then passing an actual callable object would b=
e=20
> preferable. So caching is not needed.
> The real problem is temporaries lifetime. Let me give you an example:
> void print(std::string_view sv) { std::cout << sv << std::endl; }
> void print_lazy([] -> std::string_view sv) { std::cout << sv() << std::
> endl; }
>
> void foo0() {
> print(std::string("foo")); // ok: temporary string is kept alive until=
=20
> after the execution of print
> }
> void foo1() {
> print_lazy(std::string("foo")); // std::string is generated within=20
> "evaluation function" and cannot be kept alive until after the execution =
of=20
> print_lazy
> }
> void foo2() {
> print([]() -> std::string_view { return std::string("foo"); }) // same=
=20
> issue as above, but made explicit for better understanding
> }
>
> If temporaries are destroyed by the "evaluation function", print and=20
> print_lazy cannot be semantically equivalent, and lazy parameters would=
=20
> bring many lifetime issues that are not desirable.
> If foo0 is correct (and it is), then foo1 should also be correct, but thi=
s=20
> cannot be if temporary lifetime is bound to the "evaluation function"
>
Functions that use lazily evaluated expressions are not intended to be=20
equivalent to their non-lazy counterparts. That's *why* we give them lazily=
=20
evaluated expressions; we don't want them to be equivalent.
Yes, temporaries manifested in a lazy expression will not be extended to=20
the lifetime in which the original expression was passed. This is a *good=
=20
thing*. In your example, there is no lifetime issue at all. Temporaries=20
generated by `print_lazy`'s lazy evaluation will be destroyed after=20
`std::cout` is executed, in accord with C++'s usual lifetime rules.
This is a great example of why I say we shouldn't think of lazy evaluation=
=20
as a function call. Because it isn't a function call and shouldn't act like=
=20
one. A normal C++ function cannot spawn a temporary whose lifetime is=20
extended to the end of an expression.
A lazy expression *must* be able to do this. Evaluating one ought to be=20
exactly identical to doing a copy-and-paste of the expression at the point=
=20
of evaluation. Otherwise, there's just no point in bothering.
--=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/350339bf-7b4e-438c-a70d-8227fcf52088%40isocpp.or=
g.
------=_Part_43562_564863776.1527686978885
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, May 30, 2018 at 4:40:45 AM UTC-4, floria...@=
gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt=
r">Le mercredi 30 mai 2018 01:22:11 UTC+2, Edward Catmur a =C3=A9crit=C2=A0=
:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"auto"><div><br><br><di=
v class=3D"gmail_quote"><div dir=3D"ltr">On Tue, 29 May 2018, 23:03 Bengt G=
ustafsson, <<a rel=3D"nofollow">bengt.gu...@beamways.com</a>> wrote:<=
br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">@florian: Yes, goo=
d point: The fact that you don't need a "already evaluated" f=
lag for simple expressions clearly points to the fact that the caller side =
should handle the flag, i.e. the callee should just call the function in ca=
se it needs the value. The function can elect to use a flag or re-evalutate=
if it can figure out that runtime cost is low, no side effects occur and n=
o temporary destructors to call. Using thunks to adjust stack frame offsets=
is probably wise as it is going to be fairly rare that forwarding occurs (=
especially in multiple levels).<div><div><br></div><div>@Nicol: Prohibiting=
using a lazy parameter more than once seems overly restrictive and very er=
ror prone, especially if no diagnostic is required. Furthermore the caller =
must keep track of whether the function was called anyway to handle tempora=
ry destruction properly.<br></div></div></div></blockquote></div></div><div=
dir=3D"auto"><br></div><div dir=3D"auto">In the proposal under discussion,=
there is no caching of the result of the evaluation of the passed in expre=
ssion and so no flag required and no destructor call. Multiple use results =
in multiple evaluation of the initializer expression, which may result in U=
B if the evaluation of the expression falsifies its own preconditions (e.g.=
moving out a container or smart pointer that is required to be non empty).=
<br></div></div></blockquote><div>=C2=A0</div><div>The problem here is not=
caching the result. If you want to evaluate the expression multiple times,=
then passing an actual callable object would be preferable. So caching is =
not needed.<br></div><div>The real problem is temporaries lifetime. Let me =
give you an example:</div><div><div style=3D"background-color:rgb(250,250,2=
50);border-color:rgb(187,187,187);border-style:solid;border-width:1px"><cod=
e><div><span style=3D"color:#008">void</span><span style=3D"color:#000"> </=
span><span style=3D"color:#008">print</span><span style=3D"color:#660">(</s=
pan><span style=3D"color:#000">std</span><span style=3D"color:#660">::</spa=
n><span style=3D"color:#000">string_view sv</span><span style=3D"color:#660=
">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{</=
span><span style=3D"color:#000"> std</span><span style=3D"color:#660">::</s=
pan><span style=3D"color:#000">cout </span><span style=3D"color:#660"><&=
lt;</span><span style=3D"color:#000"> sv </span><span style=3D"color:#660">=
<<</span><span style=3D"color:#000"> std</span><span style=3D"color:#=
660">::</span><span style=3D"color:#000">endl</span><span style=3D"color:#6=
60">;</span><span style=3D"color:#000"> </span><span style=3D"color:#660">}=
</span><span style=3D"color:#000"><br></span><span style=3D"color:#008">voi=
d</span><span style=3D"color:#000"> print_lazy</span><span style=3D"color:#=
660">([]</span><span style=3D"color:#000"> </span><span style=3D"color:#660=
">-></span><span style=3D"color:#000"> std</span><span style=3D"color:#6=
60">::</span><span style=3D"color:#000">string_view sv</span><span style=3D=
"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#660">{</span><span style=3D"color:#000"> std</span><span style=3D"color:=
#660">::</span><span style=3D"color:#000">cout </span><span style=3D"color:=
#660"><<</span><span style=3D"color:#000"> sv</span><span style=3D"co=
lor:#660">()</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660"><<</span><span style=3D"color:#000"> std</span><span style=3D"c=
olor:#660">::</span><span style=3D"color:#000">endl</span><span style=3D"co=
lor:#660">;</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660">}</span><span style=3D"color:#000"><br><br></span><span style=3D"color=
:#008">void</span><span style=3D"color:#000"> foo0</span><span style=3D"col=
or:#660">()</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660">{</span><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"co=
lor:#008">print</span><span style=3D"color:#660">(</span><span style=3D"col=
or:#000">std</span><span style=3D"color:#660">::</span><span style=3D"color=
:#008">string</span><span style=3D"color:#660">(</span><span style=3D"color=
:#080">"foo"</span><span style=3D"color:#660">));</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#800">// ok: temporary strin=
g is kept alive until after the execution of print</span><span style=3D"col=
or:#000"><br></span><span style=3D"color:#660">}</span><span style=3D"color=
:#000"><br></span><span style=3D"color:#008">void</span><span style=3D"colo=
r:#000"> foo1</span><span style=3D"color:#660">()</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#00=
0"><br>=C2=A0 print_lazy</span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#000">std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#008">string</span><span style=3D"color:#660">(</span><span style=
=3D"color:#080">"foo"</span><span style=3D"color:#660">))<wbr>;</=
span><span style=3D"color:#000"> </span><span style=3D"color:#800">// std::=
string is generated within "evaluation function" and cannot be ke=
pt alive until after the execution of print_lazy</span><span style=3D"color=
:#000"><br></span><span style=3D"color:#660">}</span><span style=3D"color:#=
000"><br></span><span style=3D"color:#008">void</span><span style=3D"color:=
#000"> foo2</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 </span><span style=3D"color:#008">print</span><span style=3D"co=
lor:#660">([]()</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#660">-></span><span style=3D"color:#000"> std</span><span style=3D"c=
olor:#660">::</span><span style=3D"color:#000">string_view </span><span sty=
le=3D"color:#660">{</span><span style=3D"color:#000"> </span><span style=3D=
"color:#008">return</span><span style=3D"color:#000"> std</span><span style=
=3D"color:#660">::</span><span style=3D"color:#008">string</span><span styl=
e=3D"color:#660">(</span><span style=3D"color:#080">"foo"</span><=
span style=3D"color:#660">);</span><span style=3D"color:#000"> </span><span=
style=3D"color:#660">})</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#800">// same issue as above, but made explicit for better unde=
rstanding</span><span style=3D"color:#000"><br></span><span style=3D"color:=
#660">}</span><span style=3D"color:#000"><br></span></div></code></div><br>=
If temporaries are destroyed by the "evaluation function", print =
and print_lazy cannot be semantically equivalent, and lazy parameters would=
bring many lifetime issues that are not desirable.</div><div>If foo0 is co=
rrect (and it is), then foo1 should also be correct, but this cannot be if =
temporary lifetime is bound to the "evaluation function"<br></div=
></div></blockquote><div><br></div><div>Functions that use lazily evaluated=
expressions are not intended to be equivalent to their non-lazy counterpar=
ts. That's <i>why</i> we give them lazily evaluated expressions; we don=
't want them to be equivalent.</div><div><br></div><div>Yes, temporarie=
s manifested in a lazy expression will not be extended to the lifetime in w=
hich the original expression was passed. This is a <i>good thing</i>. In yo=
ur example, there is no lifetime issue at all. Temporaries generated by `pr=
int_lazy`'s lazy evaluation will be destroyed after `std::cout` is exec=
uted, in accord with C++'s usual lifetime rules.</div><div><br></div><d=
iv>This is a great example of why I say we shouldn't think of lazy eval=
uation as a function call. Because it isn't a function call and shouldn=
't act like one. A normal C++ function cannot spawn a temporary whose l=
ifetime is extended to the end of an expression.</div><div><br></div><div>A=
lazy expression <i>must</i> be able to do this. Evaluating one ought to be=
exactly identical to doing a copy-and-paste of the expression at the point=
of evaluation. Otherwise, there's just no point in bothering.<br></div=
><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/350339bf-7b4e-438c-a70d-8227fcf52088%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/350339bf-7b4e-438c-a70d-8227fcf52088=
%40isocpp.org</a>.<br />
------=_Part_43562_564863776.1527686978885--
------=_Part_43561_1102200084.1527686978885--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 30 May 2018 15:13:58 +0100
Raw View
--00000000000041e122056d6cf639
Content-Type: text/plain; charset="UTF-8"
On Wed, May 30, 2018 at 2:29 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> Functions that use lazily evaluated expressions are not intended to be
> equivalent to their non-lazy counterparts. That's *why* we give them
> lazily evaluated expressions; we don't want them to be equivalent.
>
> Yes, temporaries manifested in a lazy expression will not be extended to
> the lifetime in which the original expression was passed. This is a *good
> thing*. In your example, there is no lifetime issue at all. Temporaries
> generated by `print_lazy`'s lazy evaluation will be destroyed after
> `std::cout` is executed, in accord with C++'s usual lifetime rules.
>
> This is a great example of why I say we shouldn't think of lazy evaluation
> as a function call. Because it isn't a function call and shouldn't act like
> one. A normal C++ function cannot spawn a temporary whose lifetime is
> extended to the end of an expression.
>
> A lazy expression *must* be able to do this. Evaluating one ought to be
> exactly identical to doing a copy-and-paste of the expression at the point
> of evaluation. Otherwise, there's just no point in bothering.
>
OK, so you're saying that in
void print_lazy([] -> std::string_view sv) { std::cout << sv(); std::cout
<< std::endl; }
// ^ #1
^ #2
void foo1() { print_lazy(std::string("foo")); }
the temporary std::string should be destructed at #1, not at #2.
I agree that that would be a better semantic, but it implies a different
ABI to that proposed (in passing) in P0927; rather than a single code
pointer code whose invocation evaluates the expression, we need two code
pointers with the second destructing temporaries, or a single code pointer
with signature T(void* caller_stack, enum class action { evaluate,
destruct_temporaries}). The caller would still need to reserve stack space
for any temporaries in the lazily evaluated expression, but would not need
to maintain a flag indicating whether temporaries had been constructed, as
calling the code pointer to perform cleanup would be the responsibility of
the callee.
--
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/CAJnLdObEGH9PfO%2B_JVwY5U8-yBD30-vVqzmf5wUqczMvpoOcUg%40mail.gmail.com.
--00000000000041e122056d6cf639
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, May 30, 2018 at 2:29 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Functio=
ns that use lazily evaluated expressions are not intended to be equivalent =
to their non-lazy counterparts. That's <i>why</i> we give them lazily e=
valuated expressions; we don't want them to be equivalent.</div><div><b=
r></div><div>Yes, temporaries manifested in a lazy expression will not be e=
xtended to the lifetime in which the original expression was passed. This i=
s a <i>good thing</i>. In your example, there is no lifetime issue at all. =
Temporaries generated by `print_lazy`'s lazy evaluation will be destroy=
ed after `std::cout` is executed, in accord with C++'s usual lifetime r=
ules.</div><div><br></div><div>This is a great example of why I say we shou=
ldn't think of lazy evaluation as a function call. Because it isn't=
a function call and shouldn't act like one. A normal C++ function cann=
ot spawn a temporary whose lifetime is extended to the end of an expression=
..</div><div><br></div><div>A lazy expression <i>must</i> be able to do this=
.. Evaluating one ought to be exactly identical to doing a copy-and-paste of=
the expression at the point of evaluation. Otherwise, there's just no =
point in bothering.</div></div></blockquote><div><br></div><div>OK, so you&=
#39;re saying that in</div><div><br></div><font face=3D"monospace, monospac=
e">void print_lazy([] -> std::string_view sv) { std::cout << sv();=
std::cout << std::endl; }</font></div><div class=3D"gmail_quote"><fo=
nt face=3D"monospace, monospace">//=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 ^ #1=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ^ #2</font></div><div class=3D"gmail_quote"=
><font face=3D"monospace, monospace">void foo1() { print_lazy(std::string(&=
quot;foo")); }</font></div><div class=3D"gmail_quote"><br></div>the te=
mporary <font face=3D"monospace, monospace">std::string</font> should be de=
structed at #1, not at #2.=C2=A0</div><div class=3D"gmail_extra"><br></div>=
<div class=3D"gmail_extra">I agree that that would be a better semantic, bu=
t it implies a different ABI to that proposed (in passing) in P0927; rather=
than a single code pointer code whose invocation evaluates the expression,=
we need two code pointers with the second destructing temporaries, or a si=
ngle code pointer with signature <font face=3D"monospace, monospace">T(void=
* caller_stack, enum class action { evaluate, destruct_temporaries})</font>=
.. The caller would still need to reserve stack space for any temporaries in=
the lazily evaluated expression, but would not need to maintain a flag ind=
icating whether temporaries had been constructed, as calling the code point=
er to perform cleanup would be the responsibility of the callee.</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/CAJnLdObEGH9PfO%2B_JVwY5U8-yBD30-vVqz=
mf5wUqczMvpoOcUg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdObEGH9PfO=
%2B_JVwY5U8-yBD30-vVqzmf5wUqczMvpoOcUg%40mail.gmail.com</a>.<br />
--00000000000041e122056d6cf639--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 30 May 2018 07:31:05 -0700 (PDT)
Raw View
------=_Part_11327_1180530236.1527690665095
Content-Type: multipart/alternative;
boundary="----=_Part_11328_1257363815.1527690665095"
------=_Part_11328_1257363815.1527690665095
Content-Type: text/plain; charset="UTF-8"
On Wednesday, May 30, 2018 at 10:14:02 AM UTC-4, Edward Catmur wrote:
>
> On Wed, May 30, 2018 at 2:29 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> Functions that use lazily evaluated expressions are not intended to be
>> equivalent to their non-lazy counterparts. That's *why* we give them
>> lazily evaluated expressions; we don't want them to be equivalent.
>>
>> Yes, temporaries manifested in a lazy expression will not be extended to
>> the lifetime in which the original expression was passed. This is a *good
>> thing*. In your example, there is no lifetime issue at all. Temporaries
>> generated by `print_lazy`'s lazy evaluation will be destroyed after
>> `std::cout` is executed, in accord with C++'s usual lifetime rules.
>>
>> This is a great example of why I say we shouldn't think of lazy
>> evaluation as a function call. Because it isn't a function call and
>> shouldn't act like one. A normal C++ function cannot spawn a temporary
>> whose lifetime is extended to the end of an expression.
>>
>> A lazy expression *must* be able to do this. Evaluating one ought to be
>> exactly identical to doing a copy-and-paste of the expression at the point
>> of evaluation. Otherwise, there's just no point in bothering.
>>
>
> OK, so you're saying that in
>
> void print_lazy([] -> std::string_view sv) { std::cout << sv(); std::cout
> << std::endl; }
> // ^ #1
> ^ #2
> void foo1() { print_lazy(std::string("foo")); }
>
> the temporary std::string should be destructed at #1, not at #2.
>
Yes.
I agree that that would be a better semantic, but it implies a different
> ABI to that proposed (in passing) in P0927; rather than a single code
> pointer code whose invocation evaluates the expression, we need two code
> pointers with the second destructing temporaries, or a single code pointer
> with signature T(void* caller_stack, enum class action { evaluate,
> destruct_temporaries}). The caller would still need to reserve stack
> space for any temporaries in the lazily evaluated expression, but would not
> need to maintain a flag indicating whether temporaries had been
> constructed, as calling the code pointer to perform cleanup would be the
> responsibility of the callee.
>
ABI is essentially irrelevant, because the only way you can have lazy
expressions work *correctly* is if the function(s) that uses them are
inlined, relative to the function that provided the expression.
The only cross-ABI way to make lazy expressions work is to make them an
actual function, with the expected C++ semantics. At which point... they're
not lazy expressions anymore. They're just a transparent way to turn an
expression into a (lighter-weight) lambda.
Basically, functions that capture lazy expressions have to be treated like
template functions to some degree.
--
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/374a1840-8e1b-424f-890c-6aec0d05abc2%40isocpp.org.
------=_Part_11328_1257363815.1527690665095
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, May 30, 2018 at 10:14:02 AM UTC-4, E=
dward Catmur wrote:<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"><div><div class=3D"gmail_quote">On Wed, May 30, 2018 at 2:29 PM, Nico=
l Bolas <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf=
-obfuscated-mailto=3D"6_DG16KzAAAJ" rel=3D"nofollow" onmousedown=3D"this.hr=
ef=3D'javascript:';return true;" onclick=3D"this.href=3D'javasc=
ript:';return true;">jmck...@gmail.com</a>></span> wrote:<br><blockq=
uote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr"><div>Functions that use lazily eva=
luated expressions are not intended to be equivalent to their non-lazy coun=
terparts. That's <i>why</i> we give them lazily evaluated expressions; =
we don't want them to be equivalent.</div><div><br></div><div>Yes, temp=
oraries manifested in a lazy expression will not be extended to the lifetim=
e in which the original expression was passed. This is a <i>good thing</i>.=
In your example, there is no lifetime issue at all. Temporaries generated =
by `print_lazy`'s lazy evaluation will be destroyed after `std::cout` i=
s executed, in accord with C++'s usual lifetime rules.</div><div><br></=
div><div>This is a great example of why I say we shouldn't think of laz=
y evaluation as a function call. Because it isn't a function call and s=
houldn't act like one. A normal C++ function cannot spawn a temporary w=
hose lifetime is extended to the end of an expression.</div><div><br></div>=
<div>A lazy expression <i>must</i> be able to do this. Evaluating one ought=
to be exactly identical to doing a copy-and-paste of the expression at the=
point of evaluation. Otherwise, there's just no point in bothering.</d=
iv></div></blockquote><div><br></div><div>OK, so you're saying that in<=
/div><div><br></div><font face=3D"monospace, monospace">void print_lazy([] =
-> std::string_view sv) { std::cout << sv(); std::cout << st=
d::endl; }</font></div><div class=3D"gmail_quote"><font face=3D"monospace, =
monospace">//=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ^=
#1=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 ^ #2</font></div><div class=3D"gmail_quote"><font face=3D"monospace,=
monospace">void foo1() { print_lazy(std::string("foo"))<wbr>; }<=
/font></div><div class=3D"gmail_quote"><br></div>the temporary <font face=
=3D"monospace, monospace">std::string</font> should be destructed at #1, no=
t at #2.=C2=A0</div></div></blockquote><div><br></div><div>Yes.</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=
></div><div>I agree that that would be a better semantic, but it implies a =
different ABI to that proposed (in passing) in P0927; rather than a single =
code pointer code whose invocation evaluates the expression, we need two co=
de pointers with the second destructing temporaries, or a single code point=
er with signature <font face=3D"monospace, monospace">T(void* caller_stack,=
enum class action { evaluate, destruct_temporaries})</font>. The caller wo=
uld still need to reserve stack space for any temporaries in the lazily eva=
luated expression, but would not need to maintain a flag indicating whether=
temporaries had been constructed, as calling the code pointer to perform c=
leanup would be the responsibility of the callee.</div></div></blockquote><=
div><br></div><div></div><div>ABI is essentially irrelevant, because the on=
ly way you can have lazy expressions work <i>correctly</i> is if the functi=
on(s) that uses them are inlined, relative to the function that provided th=
e expression.</div><div><br></div><div>The only cross-ABI way to make lazy =
expressions work is to make them an actual function, with the expected C++ =
semantics. At which point... they're not lazy expressions anymore. They=
're just a transparent way to turn an expression into a (lighter-weight=
) lambda.</div><div><br></div><div>Basically, functions that capture lazy e=
xpressions have to be treated like template functions to some degree.<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/374a1840-8e1b-424f-890c-6aec0d05abc2%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/374a1840-8e1b-424f-890c-6aec0d05abc2=
%40isocpp.org</a>.<br />
------=_Part_11328_1257363815.1527690665095--
------=_Part_11327_1180530236.1527690665095--
.
Author: florian.csdt@gmail.com
Date: Wed, 30 May 2018 07:46:39 -0700 (PDT)
Raw View
------=_Part_44870_1437523387.1527691599322
Content-Type: multipart/alternative;
boundary="----=_Part_44871_514643184.1527691599323"
------=_Part_44871_514643184.1527691599323
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
I have the impression you misunderstood my point, so let me rephrase it.
In my example, there is 3 expressions we need to consider:
print_lazy(std::string("foo")): call expression from the caller
std::string("foo"): lazy expression defined in the caller, executed in the=
=20
callee
std::cout << sv_expr() << std::endl: expression in the callee triggering=20
the execution of the lazy expression
To be fair, the lazy expression returns a std::string_view, so should be=20
implicitly transformed into std::string_view(std::string("foo"))
Now my point is, the temporary std::string object created by the lazy=20
expression must outlive the callee expression (std::cout << sv_expr() <<=20
std::endl).
But if you follow naively lifetime rules, this temporary will be destroyed=
=20
after the std::string_view is created and before std::cout << sv_expr() is=
=20
executed.
And the program will try to access unallocated data.
*This* is the issue I pointed out and that need to be solved.
If a proposal makes this code undefined behavior, then the whole feature is=
=20
broken from the beginning.
Actually, I even think the lazy expression should outlive the whole=20
execution of the caller expression (print_lazy(std::string("foo"))).
This is what we expect from a regular expression, I don't see why it should=
=20
be different with lazy expressions.
What I proposed is to extend the lifetime of the std::string temporary=20
until the caller expression (print_lazy(std::string("foo"))) is completely=
=20
done by letting the caller the responsibility to destroy it.
I also proposed a possible implementation of this solution.
Just a sidenote: when I talk about function here and I show passing=20
functions, it's only a way for me to show a possible implementation to make=
=20
the concept easier to understand.
Those functions should not appear at the language level.
Le mercredi 30 mai 2018 16:31:05 UTC+2, Nicol Bolas a =C3=A9crit :
>
>
>
> On Wednesday, May 30, 2018 at 10:14:02 AM UTC-4, Edward Catmur wrote:
>>
>> On Wed, May 30, 2018 at 2:29 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>> Functions that use lazily evaluated expressions are not intended to be=
=20
>>> equivalent to their non-lazy counterparts. That's *why* we give them=20
>>> lazily evaluated expressions; we don't want them to be equivalent.
>>>
>>> Yes, temporaries manifested in a lazy expression will not be extended t=
o=20
>>> the lifetime in which the original expression was passed. This is a *go=
od=20
>>> thing*. In your example, there is no lifetime issue at all. Temporaries=
=20
>>> generated by `print_lazy`'s lazy evaluation will be destroyed after=20
>>> `std::cout` is executed, in accord with C++'s usual lifetime rules.
>>>
>>> This is a great example of why I say we shouldn't think of lazy=20
>>> evaluation as a function call. Because it isn't a function call and=20
>>> shouldn't act like one. A normal C++ function cannot spawn a temporary=
=20
>>> whose lifetime is extended to the end of an expression.
>>>
>>> A lazy expression *must* be able to do this. Evaluating one ought to be=
=20
>>> exactly identical to doing a copy-and-paste of the expression at the po=
int=20
>>> of evaluation. Otherwise, there's just no point in bothering.
>>>
>>
>> OK, so you're saying that in
>>
>> void print_lazy([] -> std::string_view sv) { std::cout << sv(); std::cou=
t=20
>> << std::endl; }
>> // ^ #1 =
=20
>> ^ #2
>> void foo1() { print_lazy(std::string("foo")); }
>>
>> the temporary std::string should be destructed at #1, not at #2.=20
>>
>
> Yes.
>
I don't think this is reasonable as it is completely different from current=
=20
lifetime rules, without any benefit.
=20
>
> I agree that that would be a better semantic, but it implies a different=
=20
>> ABI to that proposed (in passing) in P0927; rather than a single code=20
>> pointer code whose invocation evaluates the expression, we need two code=
=20
>> pointers with the second destructing temporaries, or a single code point=
er=20
>> with signature T(void* caller_stack, enum class action { evaluate,=20
>> destruct_temporaries}). The caller would still need to reserve stack=20
>> space for any temporaries in the lazily evaluated expression, but would =
not=20
>> need to maintain a flag indicating whether temporaries had been=20
>> constructed, as calling the code pointer to perform cleanup would be the=
=20
>> responsibility of the callee.
>>
>
> ABI is essentially irrelevant, because the only way you can have lazy=20
> expressions work *correctly* is if the function(s) that uses them are=20
> inlined, relative to the function that provided the expression.
>
That's not true, there are many ways to implement this to have the correct=
=20
behavior without inlining. Edward's solution is one.
And as I said before, I don't what you call "the *correct* behavior" is=20
what we want.
=20
>
> The only cross-ABI way to make lazy expressions work is to make them an=
=20
> actual function, with the expected C++ semantics. At which point... they'=
re=20
> not lazy expressions anymore. They're just a transparent way to turn an=
=20
> expression into a (lighter-weight) lambda.
>
Yes, so what? C++ is ABI agnostic, you repeat this often enough. And now=20
you want to specify language constructions to solve an implementation/ABI=
=20
issue?
Remember that the concept of inlining itself is not part of C++. This is a=
=20
useful optimization that makes sense only at the assembly level.
=20
>
> Basically, functions that capture lazy expressions have to be treated lik=
e=20
> template functions to some degree.
>
This is where you did not follow the proposal. There is no need to create a=
=20
template like function to capture lazy expressions.
And my example implementation proves it. That's why I wrote it, to explain=
=20
how it could be possible to not have template-like nor lambda-like=20
constructions for this to work.
It doesn't even rely on inlining to be efficient. Inlining will make faster=
=20
though, but I see no reason for it to be required.
--=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/440ee683-4e50-4a60-a28a-3ccd552f2f7e%40isocpp.or=
g.
------=_Part_44871_514643184.1527691599323
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div><div>I have the impression you misunderstood my point=
, so let me rephrase it.<br><br>In my example, there is 3 expressions we ne=
ed to consider:<br><span style=3D"font-family: courier new, monospace;">pri=
nt_lazy(std::string("foo"))</span>: call expression from the call=
er<br><span style=3D"font-family: courier new, monospace;">std::string(&quo=
t;foo")</span>: lazy expression defined in the caller, executed in the=
callee<br><span style=3D"font-family: courier new, monospace;">std::cout &=
lt;< sv_expr() << std::endl</span>: expression in the callee trigg=
ering the execution of the lazy expression<br><br>To
be fair, the lazy expression returns a <span style=3D"font-family: courier=
new, monospace;">std::string_view</span>, so should be=20
implicitly transformed into <span style=3D"font-family: courier new, monosp=
ace;">std::string_view(std::string("foo"))</span><br><br>Now
my point is, the temporary std::string object created by the lazy=20
expression must outlive the callee expression (<span style=3D"font-family: =
courier new, monospace;">std::cout <<=20
sv_expr() << std::endl</span>).<br>But if you follow naively lifetime=
rules, this temporary will be destroyed after the <span style=3D"font-fami=
ly: courier new, monospace;">std::string_view</span> is created and before =
<span style=3D"font-family: courier new, monospace;">std::cout << sv_=
expr()</span> is executed.</div><div>And the program will try to access una=
llocated data.<br></div><div><b>This</b> is the issue I pointed out and tha=
t need to be solved.</div><div>If a proposal makes this code undefined beha=
vior, then the whole feature is broken from the beginning.<br><div><br></di=
v>Actually, I even think the lazy expression should outlive the whole execu=
tion of the caller expression (<span style=3D"font-family: courier new, mon=
ospace;">print_lazy(std::string("foo"))</span>).</div><div>This i=
s what we expect from a regular expression, I don't see why it should b=
e different with lazy expressions.<br></div><div><br></div><div>What I prop=
osed is to extend the lifetime of the <span style=3D"font-family: courier n=
ew, monospace;">std::string</span> temporary until the caller expression (<=
span style=3D"font-family: courier new, monospace;">print_lazy(std::string(=
"foo"))</span>) is completely done by letting the caller the resp=
onsibility to destroy it.</div><div>I also proposed a possible implementati=
on of this solution.</div><div><br></div>Just
a sidenote: when I talk about function here and I show passing=20
functions, it's only a way for me to show a possible implementation to=
=20
make the concept easier to understand.<br>Those functions should not appear=
at the language level.</div><div><br></div><br><br>Le mercredi 30 mai 2018=
16:31:05 UTC+2, Nicol Bolas a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;"><div dir=3D"ltr"><br><br>On Wednesday, May 30, 2018 at 10=
:14:02 AM UTC-4, Edward Catmur wrote:<blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr"><div><div class=3D"gmail_quote">On Wed, May 30, 2018 at =
2:29 PM, Nicol Bolas <span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmai=
l.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"m=
argin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"l=
tr"><div>Functions that use lazily evaluated expressions are not intended t=
o be equivalent to their non-lazy counterparts. That's <i>why</i> we gi=
ve them lazily evaluated expressions; we don't want them to be equivale=
nt.</div><div><br></div><div>Yes, temporaries manifested in a lazy expressi=
on will not be extended to the lifetime in which the original expression wa=
s passed. This is a <i>good thing</i>. In your example, there is no lifetim=
e issue at all. Temporaries generated by `print_lazy`'s lazy evaluation=
will be destroyed after `std::cout` is executed, in accord with C++'s =
usual lifetime rules.</div><div><br></div><div>This is a great example of w=
hy I say we shouldn't think of lazy evaluation as a function call. Beca=
use it isn't a function call and shouldn't act like one. A normal C=
++ function cannot spawn a temporary whose lifetime is extended to the end =
of an expression.</div><div><br></div><div>A lazy expression <i>must</i> be=
able to do this. Evaluating one ought to be exactly identical to doing a c=
opy-and-paste of the expression at the point of evaluation. Otherwise, ther=
e's just no point in bothering.</div></div></blockquote><div><br></div>=
<div>OK, so you're saying that in</div><div><br></div><font face=3D"mon=
ospace, monospace">void print_lazy([] -> std::string_view sv) { std::cou=
t << sv(); std::cout << std::endl; }</font></div><div class=3D"=
gmail_quote"><font face=3D"monospace, monospace">//=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ^ #1=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ^ #2</font></div><div class=
=3D"gmail_quote"><font face=3D"monospace, monospace">void foo1() { print_la=
zy(std::string("foo"))<wbr>; }</font></div><div class=3D"gmail_qu=
ote"><br></div>the temporary <font face=3D"monospace, monospace">std::strin=
g</font> should be destructed at #1, not at #2.=C2=A0</div></div></blockquo=
te><div><br></div><div>Yes.</div></div></blockquote><div><br></div><div>I d=
on't think this is reasonable as it is completely different from curren=
t lifetime rules, without any benefit.<br></div><div>=C2=A0</div><blockquot=
e 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><br></div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div></div><div>I agree th=
at that would be a better semantic, but it implies a different ABI to that =
proposed (in passing) in P0927; rather than a single code pointer code whos=
e invocation evaluates the expression, we need two code pointers with the s=
econd destructing temporaries, or a single code pointer with signature <fon=
t face=3D"monospace, monospace">T(void* caller_stack, enum class action { e=
valuate, destruct_temporaries})</font>. The caller would still need to rese=
rve stack space for any temporaries in the lazily evaluated expression, but=
would not need to maintain a flag indicating whether temporaries had been =
constructed, as calling the code pointer to perform cleanup would be the re=
sponsibility of the callee.</div></div></blockquote><div><br></div><div></d=
iv><div>ABI is essentially irrelevant, because the only way you can have la=
zy expressions work <i>correctly</i> is if the function(s) that uses them a=
re inlined, relative to the function that provided the expression.</div></d=
iv></blockquote><div><br></div><div>That's not true, there are many way=
s to implement this to have the correct behavior without inlining. Edward&#=
39;s solution is one.</div><div>And as I said before, I don't what you =
call "the <i>correct</i> behavior" is what we want.<br></div><div=
>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
<div><br></div><div>The only cross-ABI way to make lazy expressions work is=
to make them an actual function, with the expected C++ semantics. At which=
point... they're not lazy expressions anymore. They're just a tran=
sparent way to turn an expression into a (lighter-weight) lambda.</div></di=
v></blockquote><div><br></div><div>Yes, so what? C++ is ABI agnostic, you r=
epeat this often enough. And now you want to specify language constructions=
to solve an implementation/ABI issue?</div><div>Remember that the concept =
of inlining itself is not part of C++. This is a useful optimization that m=
akes sense only at the assembly level.<br></div><div>=C2=A0</div><blockquot=
e 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><br></div><div>Bas=
ically, functions that capture lazy expressions have to be treated like tem=
plate functions to some degree.<br></div></div></blockquote><div><br></div>=
This is where you did not follow the proposal. There is no need to create a=
template like function to capture lazy expressions.<br>And my example impl=
ementation proves it. That's why I wrote it, to explain how it could be=
possible to not have template-like nor lambda-like constructions for this =
to work.<br>It doesn't even rely on inlining to be efficient. Inlining =
will make faster though, but I see no reason for it to be required.<br></di=
v>
<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/440ee683-4e50-4a60-a28a-3ccd552f2f7e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/440ee683-4e50-4a60-a28a-3ccd552f2f7e=
%40isocpp.org</a>.<br />
------=_Part_44871_514643184.1527691599323--
------=_Part_44870_1437523387.1527691599322--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 30 May 2018 08:25:44 -0700 (PDT)
Raw View
------=_Part_32762_509406687.1527693944168
Content-Type: multipart/alternative;
boundary="----=_Part_32763_1253682709.1527693944168"
------=_Part_32763_1253682709.1527693944168
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Wednesday, May 30, 2018 at 10:46:39 AM UTC-4, floria...@gmail.com wrote:
>
> I have the impression you misunderstood my point, so let me rephrase it.
>
> In my example, there is 3 expressions we need to consider:
> print_lazy(std::string("foo")): call expression from the caller
> std::string("foo"): lazy expression defined in the caller, executed in=20
> the callee
> std::cout << sv_expr() << std::endl: expression in the callee triggering=
=20
> the execution of the lazy expression
>
> To be fair, the lazy expression returns a std::string_view, so should be=
=20
> implicitly transformed into std::string_view(std::string("foo"))
>
> Now my point is, the temporary std::string object created by the lazy=20
> expression must outlive the callee expression (std::cout << sv_expr() <<=
=20
> std::endl).
>
Why "must" it? Just because it would have if the expression weren't lazily=
=20
evaluated?
But if you follow naively lifetime rules, this temporary will be destroyed=
=20
> after the std::string_view is created and before std::cout << sv_expr()=
=20
> is executed.
>
That's only true if you think of `sv_expr()` as a function call.
If you think of it as being the exact equivalent to `std::cout <<=20
std::string_view(std::string("foo"));`, then it works just fine. Evaluating=
=20
that expression will manifest a temporary. And per C++ rules, by the way=20
that temporary is used within the evaluated expression, the lifetime of=20
that temporary will be the lifetime of the whole expression in which it is=
=20
used. And the "whole expression" includes `std::cout <<`.
This is why thinking of lazy expressions as functions is a bad thing. They=
=20
aren't functions; they don't act like functions, and they can do things=20
functions cannot normally do.
And the program will try to access unallocated data.
> *This* is the issue I pointed out and that need to be solved.
> If a proposal makes this code undefined behavior, then the whole feature=
=20
> is broken from the beginning.
>
> Actually, I even think the lazy expression should outlive the whole=20
> execution of the caller expression (print_lazy(std::string("foo"))).
> This is what we expect from a regular expression, I don't see why it=20
> should be different with lazy expressions.
>
I don't see why we should expect lazy expressions to behave exactly like=20
non-lazy ones.
What I proposed is to extend the lifetime of the std::string temporary=20
> until the caller expression (print_lazy(std::string("foo"))) is=20
> completely done by letting the caller the responsibility to destroy it.
> I also proposed a possible implementation of this solution.
>
> Just a sidenote: when I talk about function here and I show passing=20
> functions, it's only a way for me to show a possible implementation to ma=
ke=20
> the concept easier to understand.
> Those functions should not appear at the language level.
>
>
>
> Le mercredi 30 mai 2018 16:31:05 UTC+2, Nicol Bolas a =C3=A9crit :
>>
>>
>>
>> On Wednesday, May 30, 2018 at 10:14:02 AM UTC-4, Edward Catmur wrote:
>>>
>>> On Wed, May 30, 2018 at 2:29 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>
>>>> Functions that use lazily evaluated expressions are not intended to be=
=20
>>>> equivalent to their non-lazy counterparts. That's *why* we give them=
=20
>>>> lazily evaluated expressions; we don't want them to be equivalent.
>>>>
>>>> Yes, temporaries manifested in a lazy expression will not be extended=
=20
>>>> to the lifetime in which the original expression was passed. This is a=
*good=20
>>>> thing*. In your example, there is no lifetime issue at all.=20
>>>> Temporaries generated by `print_lazy`'s lazy evaluation will be destro=
yed=20
>>>> after `std::cout` is executed, in accord with C++'s usual lifetime rul=
es.
>>>>
>>>> This is a great example of why I say we shouldn't think of lazy=20
>>>> evaluation as a function call. Because it isn't a function call and=20
>>>> shouldn't act like one. A normal C++ function cannot spawn a temporary=
=20
>>>> whose lifetime is extended to the end of an expression.
>>>>
>>>> A lazy expression *must* be able to do this. Evaluating one ought to=
=20
>>>> be exactly identical to doing a copy-and-paste of the expression at th=
e=20
>>>> point of evaluation. Otherwise, there's just no point in bothering.
>>>>
>>>
>>> OK, so you're saying that in
>>>
>>> void print_lazy([] -> std::string_view sv) { std::cout << sv();=20
>>> std::cout << std::endl; }
>>> // ^ #1 =
=20
>>> ^ #2
>>> void foo1() { print_lazy(std::string("foo")); }
>>>
>>> the temporary std::string should be destructed at #1, not at #2.=20
>>>
>>
>> Yes.
>>
>
> I don't think this is reasonable as it is completely different from=20
> current lifetime rules, without any benefit.
> =20
>
>>
>> I agree that that would be a better semantic, but it implies a different=
=20
>>> ABI to that proposed (in passing) in P0927; rather than a single code=
=20
>>> pointer code whose invocation evaluates the expression, we need two cod=
e=20
>>> pointers with the second destructing temporaries, or a single code poin=
ter=20
>>> with signature T(void* caller_stack, enum class action { evaluate,=20
>>> destruct_temporaries}). The caller would still need to reserve stack=20
>>> space for any temporaries in the lazily evaluated expression, but would=
not=20
>>> need to maintain a flag indicating whether temporaries had been=20
>>> constructed, as calling the code pointer to perform cleanup would be th=
e=20
>>> responsibility of the callee.
>>>
>>
>> ABI is essentially irrelevant, because the only way you can have lazy=20
>> expressions work *correctly* is if the function(s) that uses them are=20
>> inlined, relative to the function that provided the expression.
>>
>
> That's not true, there are many ways to implement this to have the correc=
t=20
> behavior without inlining. Edward's solution is one.
> And as I said before, I don't what you call "the *correct* behavior" is=
=20
> what we want.
> =20
>
>>
>> The only cross-ABI way to make lazy expressions work is to make them an=
=20
>> actual function, with the expected C++ semantics. At which point... they=
're=20
>> not lazy expressions anymore. They're just a transparent way to turn an=
=20
>> expression into a (lighter-weight) lambda.
>>
>
> Yes, so what? C++ is ABI agnostic, you repeat this often enough. And now=
=20
> you want to specify language constructions to solve an implementation/ABI=
=20
> issue?
> Remember that the concept of inlining itself is not part of C++. This is =
a=20
> useful optimization that makes sense only at the assembly level.
> =20
>
>>
>> Basically, functions that capture lazy expressions have to be treated=20
>> like template functions to some degree.
>>
>
> This is where you did not follow the proposal. There is no need to create=
=20
> a template like function to capture lazy expressions.
> And my example implementation proves it. That's why I wrote it, to explai=
n=20
> how it could be possible to not have template-like nor lambda-like=20
> constructions for this to work.
> It doesn't even rely on inlining to be efficient. Inlining will make=20
> faster though, but I see no reason for it to be required.
>
--=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/2180c559-59a1-46bb-afc4-2d06595193b0%40isocpp.or=
g.
------=_Part_32763_1253682709.1527693944168
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, May 30, 2018 at 10:46:39 AM UTC-4, floria...=
@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div><div>I have the impression you misunderstood my point, so let me r=
ephrase it.<br><br>In my example, there is 3 expressions we need to conside=
r:<br><span style=3D"font-family:courier new,monospace">print_lazy(std::str=
ing("foo"))</span><wbr>: call expression from the caller<br><span=
style=3D"font-family:courier new,monospace">std::string("foo")</=
span>: lazy expression defined in the caller, executed in the callee<br><sp=
an style=3D"font-family:courier new,monospace">std::cout << sv_expr()=
<< std::endl</span>: expression in the callee triggering the executi=
on of the lazy expression<br><br>To
be fair, the lazy expression returns a <span style=3D"font-family:courier =
new,monospace">std::string_view</span>, so should be=20
implicitly transformed into <span style=3D"font-family:courier new,monospac=
e">std::string_view(std::string("<wbr>foo"))</span><br><br>Now
my point is, the temporary std::string object created by the lazy=20
expression must outlive the callee expression (<span style=3D"font-family:c=
ourier new,monospace">std::cout <<=20
sv_expr() << std::endl</span>).<br></div></div></div></blockquote><di=
v><br></div><div>Why "must" it? Just because it would have if the=
expression weren't lazily evaluated?<br></div><div><br></div><blockquo=
te 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><div>But if you f=
ollow naively lifetime rules, this temporary will be destroyed after the <s=
pan style=3D"font-family:courier new,monospace">std::string_view</span> is =
created and before <span style=3D"font-family:courier new,monospace">std::c=
out << sv_expr()</span> is executed.</div></div></div></blockquote><d=
iv><br></div><div>That's only true if you think of `sv_expr()` as a fun=
ction call.</div><div><br></div><div>If you think of it as being the exact =
equivalent to `std::cout << std::string_view(std::string("foo&qu=
ot;));`, then it works just fine. Evaluating that expression will manifest =
a temporary. And per C++ rules, by the way that temporary is used within th=
e evaluated expression, the lifetime of that temporary will be the lifetime=
of the whole expression in which it is used. And the "whole expressio=
n" includes `std::cout <<`.<br></div><div><br></div><div>This is=
why thinking of lazy expressions as functions is a bad thing. They aren=
9;t functions; they don't act like functions, and they can do things fu=
nctions cannot normally do.<br></div><div><br></div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div dir=3D"ltr"><div><div>And the program will try t=
o access unallocated data.<br></div><div><b>This</b> is the issue I pointed=
out and that need to be solved.</div><div>If a proposal makes this code un=
defined behavior, then the whole feature is broken from the beginning.<br><=
div><br></div>Actually, I even think the lazy expression should outlive the=
whole execution of the caller expression (<span style=3D"font-family:couri=
er new,monospace">print_lazy(std::string("foo")<wbr>)</span>).</d=
iv><div>This is what we expect from a regular expression, I don't see w=
hy it should be different with lazy expressions.<br></div></div></div></blo=
ckquote><div><br></div><div>I don't see why we should expect lazy expre=
ssions to behave exactly like non-lazy ones.<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><div></div><di=
v></div><div>What I proposed is to extend the lifetime of the <span style=
=3D"font-family:courier new,monospace">std::string</span> temporary until t=
he caller expression (<span style=3D"font-family:courier new,monospace">pri=
nt_lazy(std::string("foo")<wbr>)</span>) is completely done by le=
tting the caller the responsibility to destroy it.</div><div>I also propose=
d a possible implementation of this solution.</div><div><br></div>Just
a sidenote: when I talk about function here and I show passing=20
functions, it's only a way for me to show a possible implementation to=
=20
make the concept easier to understand.<br>Those functions should not appear=
at the language level.</div><div><br></div><br><br>Le mercredi 30 mai 2018=
16:31:05 UTC+2, Nicol Bolas a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_=
quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddi=
ng-left:1ex"><div dir=3D"ltr"><br><br>On Wednesday, May 30, 2018 at 10:14:0=
2 AM UTC-4, Edward Catmur wrote:<blockquote class=3D"gmail_quote" style=3D"=
margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><di=
v dir=3D"ltr"><div><div class=3D"gmail_quote">On Wed, May 30, 2018 at 2:29 =
PM, Nicol Bolas <span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com=
</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin=
:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><=
div>Functions that use lazily evaluated expressions are not intended to be =
equivalent to their non-lazy counterparts. That's <i>why</i> we give th=
em lazily evaluated expressions; we don't want them to be equivalent.</=
div><div><br></div><div>Yes, temporaries manifested in a lazy expression wi=
ll not be extended to the lifetime in which the original expression was pas=
sed. This is a <i>good thing</i>. In your example, there is no lifetime iss=
ue at all. Temporaries generated by `print_lazy`'s lazy evaluation will=
be destroyed after `std::cout` is executed, in accord with C++'s usual=
lifetime rules.</div><div><br></div><div>This is a great example of why I =
say we shouldn't think of lazy evaluation as a function call. Because i=
t isn't a function call and shouldn't act like one. A normal C++ fu=
nction cannot spawn a temporary whose lifetime is extended to the end of an=
expression.</div><div><br></div><div>A lazy expression <i>must</i> be able=
to do this. Evaluating one ought to be exactly identical to doing a copy-a=
nd-paste of the expression at the point of evaluation. Otherwise, there'=
;s just no point in bothering.</div></div></blockquote><div><br></div><div>=
OK, so you're saying that in</div><div><br></div><font face=3D"monospac=
e, monospace">void print_lazy([] -> std::string_view sv) { std::cout <=
;< sv(); std::cout << std::endl; }</font></div><div class=3D"gmail=
_quote"><font face=3D"monospace, monospace">//=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ^ #1=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ^ #2</font></div><div class=3D"gm=
ail_quote"><font face=3D"monospace, monospace">void foo1() { print_lazy(std=
::string("foo"))<wbr>; }</font></div><div class=3D"gmail_quote"><=
br></div>the temporary <font face=3D"monospace, monospace">std::string</fon=
t> should be destructed at #1, not at #2.=C2=A0</div></div></blockquote><di=
v><br></div><div>Yes.</div></div></blockquote><div><br></div><div>I don'=
;t think this is reasonable as it is completely different from current life=
time rules, without any benefit.<br></div><div>=C2=A0</div><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr"><div><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div></div><div>I agree that that w=
ould be a better semantic, but it implies a different ABI to that proposed =
(in passing) in P0927; rather than a single code pointer code whose invocat=
ion evaluates the expression, we need two code pointers with the second des=
tructing temporaries, or a single code pointer with signature <font face=3D=
"monospace, monospace">T(void* caller_stack, enum class action { evaluate, =
destruct_temporaries})</font>. The caller would still need to reserve stack=
space for any temporaries in the lazily evaluated expression, but would no=
t need to maintain a flag indicating whether temporaries had been construct=
ed, as calling the code pointer to perform cleanup would be the responsibil=
ity of the callee.</div></div></blockquote><div><br></div><div></div><div>A=
BI is essentially irrelevant, because the only way you can have lazy expres=
sions work <i>correctly</i> is if the function(s) that uses them are inline=
d, relative to the function that provided the expression.</div></div></bloc=
kquote><div><br></div><div>That's not true, there are many ways to impl=
ement this to have the correct behavior without inlining. Edward's solu=
tion is one.</div><div>And as I said before, I don't what you call &quo=
t;the <i>correct</i> behavior" is what we want.<br></div><div>=C2=A0</=
div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><br></div=
><div>The only cross-ABI way to make lazy expressions work is to make them =
an actual function, with the expected C++ semantics. At which point... they=
're not lazy expressions anymore. They're just a transparent way to=
turn an expression into a (lighter-weight) lambda.</div></div></blockquote=
><div><br></div><div>Yes, so what? C++ is ABI agnostic, you repeat this oft=
en enough. And now you want to specify language constructions to solve an i=
mplementation/ABI issue?</div><div>Remember that the concept of inlining it=
self is not part of C++. This is a useful optimization that makes sense onl=
y at the assembly level.<br></div><div>=C2=A0</div><blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr"><div><br></div><div>Basically, functions t=
hat capture lazy expressions have to be treated like template functions to =
some degree.<br></div></div></blockquote><div><br></div>This is where you d=
id not follow the proposal. There is no need to create a template like func=
tion to capture lazy expressions.<br>And my example implementation proves i=
t. That's why I wrote it, to explain how it could be possible to not ha=
ve template-like nor lambda-like constructions for this to work.<br>It does=
n't even rely on inlining to be efficient. Inlining will make faster th=
ough, but I see no reason for it to be required.<br></div></blockquote></di=
v>
<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/2180c559-59a1-46bb-afc4-2d06595193b0%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/2180c559-59a1-46bb-afc4-2d06595193b0=
%40isocpp.org</a>.<br />
------=_Part_32763_1253682709.1527693944168--
------=_Part_32762_509406687.1527693944168--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 30 May 2018 08:35:47 -0700 (PDT)
Raw View
------=_Part_5878_192611950.1527694547574
Content-Type: multipart/alternative;
boundary="----=_Part_5879_137275103.1527694547574"
------=_Part_5879_137275103.1527694547574
Content-Type: text/plain; charset="UTF-8"
On Wednesday, May 30, 2018 at 10:46:39 AM UTC-4, floria...@gmail.com wrote:
>
>
>
>>
>> I agree that that would be a better semantic, but it implies a different
>>> ABI to that proposed (in passing) in P0927; rather than a single code
>>> pointer code whose invocation evaluates the expression, we need two code
>>> pointers with the second destructing temporaries, or a single code pointer
>>> with signature T(void* caller_stack, enum class action { evaluate,
>>> destruct_temporaries}). The caller would still need to reserve stack
>>> space for any temporaries in the lazily evaluated expression, but would not
>>> need to maintain a flag indicating whether temporaries had been
>>> constructed, as calling the code pointer to perform cleanup would be the
>>> responsibility of the callee.
>>>
>>
>> ABI is essentially irrelevant, because the only way you can have lazy
>> expressions work *correctly* is if the function(s) that uses them are
>> inlined, relative to the function that provided the expression.
>>
>
> That's not true, there are many ways to implement this to have the correct
> behavior without inlining. Edward's solution is one.
>
And as I said before, I don't what you call "the *correct* behavior" is
> what we want.
>
>
>> The only cross-ABI way to make lazy expressions work is to make them an
>> actual function, with the expected C++ semantics. At which point... they're
>> not lazy expressions anymore. They're just a transparent way to turn an
>> expression into a (lighter-weight) lambda.
>>
>
> Yes, so what? C++ is ABI agnostic, you repeat this often enough. And now
> you want to specify language constructions to solve an implementation/ABI
> issue?
>
No, I want to specify lazy expressions so that they're *expressions*, not
function calls. So that they work exactly as if you had copy-and-pasted the
expression at the site of use.
The only way to do that is to allow the compiler to "instantiate" every
function that captures a lazy expression. That is, there can't be some
generic interface between caller and callee; the compiler must generate
special-case code at every capture of an expression.
What you want makes lazy expressions into function calls.
Remember that the concept of inlining itself is not part of C++.
>
Tell that to `constexpr` functions. Those are required to be inlined (in
the sense that a TU that uses a `constexpr` function must be able to see
its definition). The same goes for template functions; you can't
instantiate a template without having its definition visible to you.
That's what I'm talking about here.
--
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/d02edbed-b27b-4993-8347-18e53d3ac25f%40isocpp.org.
------=_Part_5879_137275103.1527694547574
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, May 30, 2018 at 10:46:39 AM UTC-4, floria...=
@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0;ma=
rgin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"lt=
r"><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margi=
n-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
<div></div><div>I agree that that would be a better semantic, but it implie=
s a different ABI to that proposed (in passing) in P0927; rather than a sin=
gle code pointer code whose invocation evaluates the expression, we need tw=
o code pointers with the second destructing temporaries, or a single code p=
ointer with signature <font face=3D"monospace, monospace">T(void* caller_st=
ack, enum class action { evaluate, destruct_temporaries})</font>. The calle=
r would still need to reserve stack space for any temporaries in the lazily=
evaluated expression, but would not need to maintain a flag indicating whe=
ther temporaries had been constructed, as calling the code pointer to perfo=
rm cleanup would be the responsibility of the callee.</div></div></blockquo=
te><div><br></div><div></div><div>ABI is essentially irrelevant, because th=
e only way you can have lazy expressions work <i>correctly</i> is if the fu=
nction(s) that uses them are inlined, relative to the function that provide=
d the expression.</div></div></blockquote><div><br></div><div>That's no=
t true, there are many ways to implement this to have the correct behavior =
without inlining. Edward's solution is one. <br></div></div></blockquot=
e><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>And as=
I said before, I don't what you call "the <i>correct</i> behavior=
" is what we want.<br></div><div>=C2=A0</div><blockquote class=3D"gmai=
l_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr"><div></div><div>The only cross-ABI way to m=
ake lazy expressions work is to make them an actual function, with the expe=
cted C++ semantics. At which point... they're not lazy expressions anym=
ore. They're just a transparent way to turn an expression into a (light=
er-weight) lambda.</div></div></blockquote><div><br></div><div>Yes, so what=
? C++ is ABI agnostic, you repeat this often enough. And now you want to sp=
ecify language constructions to solve an implementation/ABI issue?</div></d=
iv></blockquote><div><br></div><div>No, I want to specify lazy expressions =
so that they're <i>expressions</i>, not function calls. So that they wo=
rk exactly as if you had copy-and-pasted the expression at the site of use.=
</div><div><br></div><div>The only way to do that is to allow the compiler =
to "instantiate" every function that captures a lazy expression. =
That is, there can't be some generic interface between caller and calle=
e; the compiler must generate special-case code at every capture of an expr=
ession.</div><div></div><div><br></div><div>What you want makes lazy expres=
sions into function calls.<br></div><div><br></div><blockquote class=3D"gma=
il_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid=
;padding-left: 1ex;"><div dir=3D"ltr"><div>Remember that the concept of inl=
ining itself is not part of C++.</div></div></blockquote><div><br></div><di=
v>Tell that to `constexpr` functions. Those are required to be inlined (in =
the sense that a TU that uses a `constexpr` function must be able to see it=
s definition). The same goes for template functions; you can't instanti=
ate a template without having its definition visible to you.</div><div><br>=
</div><div>That's what I'm talking about here.<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/d02edbed-b27b-4993-8347-18e53d3ac25f%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/d02edbed-b27b-4993-8347-18e53d3ac25f=
%40isocpp.org</a>.<br />
------=_Part_5879_137275103.1527694547574--
------=_Part_5878_192611950.1527694547574--
.
Author: mihailnajdenov@gmail.com
Date: Wed, 30 May 2018 09:04:45 -0700 (PDT)
Raw View
------=_Part_45098_1098185413.1527696285171
Content-Type: multipart/alternative;
boundary="----=_Part_45099_919005202.1527696285171"
------=_Part_45099_919005202.1527696285171
Content-Type: text/plain; charset="UTF-8"
On Wednesday, May 30, 2018 at 6:35:47 PM UTC+3, Nicol Bolas wrote:
>
> On Wednesday, May 30, 2018 at 10:46:39 AM UTC-4, floria...@gmail.com
> wrote:
>>
>>
>>
>>>
>>> I agree that that would be a better semantic, but it implies a different
>>>> ABI to that proposed (in passing) in P0927; rather than a single code
>>>> pointer code whose invocation evaluates the expression, we need two code
>>>> pointers with the second destructing temporaries, or a single code pointer
>>>> with signature T(void* caller_stack, enum class action { evaluate,
>>>> destruct_temporaries}). The caller would still need to reserve stack
>>>> space for any temporaries in the lazily evaluated expression, but would not
>>>> need to maintain a flag indicating whether temporaries had been
>>>> constructed, as calling the code pointer to perform cleanup would be the
>>>> responsibility of the callee.
>>>>
>>>
>>> ABI is essentially irrelevant, because the only way you can have lazy
>>> expressions work *correctly* is if the function(s) that uses them are
>>> inlined, relative to the function that provided the expression.
>>>
>>
>> That's not true, there are many ways to implement this to have the
>> correct behavior without inlining. Edward's solution is one.
>>
> And as I said before, I don't what you call "the *correct* behavior" is
>> what we want.
>>
>>
>>> The only cross-ABI way to make lazy expressions work is to make them an
>>> actual function, with the expected C++ semantics. At which point... they're
>>> not lazy expressions anymore. They're just a transparent way to turn an
>>> expression into a (lighter-weight) lambda.
>>>
>>
>> Yes, so what? C++ is ABI agnostic, you repeat this often enough. And now
>> you want to specify language constructions to solve an implementation/ABI
>> issue?
>>
>
> No, I want to specify lazy expressions so that they're *expressions*, not
> function calls. So that they work exactly as if you had copy-and-pasted the
> expression at the site of use.
>
Any particular reason to want them to behave exactly like that? Any pointer
or examples of why this is required?
To this point I understood layzies are like this (correct me if I am wrong)
void f()
{
call(string("hello"));
}
becomes
void f()
{
{
auto s = string("hello");
call(s);
}
}
*However* the auto s = string("hello") is executed *not* *before* the
function call, but *from within* the function call, going back to the
original context with all the locals visible and so on.
That model seems to me pretty "natural" and easy to understand.
What are the benefits of the model you are talking about, how easy it is to
be implemented and at what cost?
What are the downsides?
>
> The only way to do that is to allow the compiler to "instantiate" every
> function that captures a lazy expression. That is, there can't be some
> generic interface between caller and callee; the compiler must generate
> special-case code at every capture of an expression.
>
> What you want makes lazy expressions into function calls.
>
> Remember that the concept of inlining itself is not part of C++.
>>
>
> Tell that to `constexpr` functions. Those are required to be inlined (in
> the sense that a TU that uses a `constexpr` function must be able to see
> its definition). The same goes for template functions; you can't
> instantiate a template without having its definition visible to you.
>
> That's what I'm talking about here.
>
--
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/5a411cf3-8012-4118-90d0-2193ed416ad5%40isocpp.org.
------=_Part_45099_919005202.1527696285171
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, May 30, 2018 at 6:35:47 PM UTC+3, Ni=
col Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt=
r">On Wednesday, May 30, 2018 at 10:46:39 AM UTC-4, <a>floria...@gmail.com<=
/a> 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"><div>=C2=
=A0</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><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></div><=
div>I agree that that would be a better semantic, but it implies a differen=
t ABI to that proposed (in passing) in P0927; rather than a single code poi=
nter code whose invocation evaluates the expression, we need two code point=
ers with the second destructing temporaries, or a single code pointer with =
signature <font face=3D"monospace, monospace">T(void* caller_stack, enum cl=
ass action { evaluate, destruct_temporaries})</font>. The caller would stil=
l need to reserve stack space for any temporaries in the lazily evaluated e=
xpression, but would not need to maintain a flag indicating whether tempora=
ries had been constructed, as calling the code pointer to perform cleanup w=
ould be the responsibility of the callee.</div></div></blockquote><div><br>=
</div><div></div><div>ABI is essentially irrelevant, because the only way y=
ou can have lazy expressions work <i>correctly</i> is if the function(s) th=
at uses them are inlined, relative to the function that provided the expres=
sion.</div></div></blockquote><div><br></div><div>That's not true, ther=
e are many ways to implement this to have the correct behavior without inli=
ning. Edward's solution is one. <br></div></div></blockquote><blockquot=
e 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>And as I said before, I=
don't what you call "the <i>correct</i> behavior" is what we=
want.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D=
"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr"><div></div><div>The only cross-ABI way to make lazy expressi=
ons work is to make them an actual function, with the expected C++ semantic=
s. At which point... they're not lazy expressions anymore. They're =
just a transparent way to turn an expression into a (lighter-weight) lambda=
..</div></div></blockquote><div><br></div><div>Yes, so what? C++ is ABI agno=
stic, you repeat this often enough. And now you want to specify language co=
nstructions to solve an implementation/ABI issue?</div></div></blockquote><=
div><br></div><div>No, I want to specify lazy expressions so that they'=
re <i>expressions</i>, not function calls. So that they work exactly as if =
you had copy-and-pasted the expression at the site of use.</div></div></blo=
ckquote><div><br></div><div>Any particular reason to want them to behave ex=
actly like that? Any pointer or examples of why this is required? =C2=A0</d=
iv><div><br></div><div>To this point I understood layzies are like this (co=
rrect me if I am wrong)</div><div><span style=3D"text-align: left; color: r=
gb(34, 34, 34); text-transform: none; text-indent: 0px; letter-spacing: nor=
mal; font-size: 13px; font-style: normal; font-variant: normal; font-weight=
: 400; text-decoration: none; word-spacing: 0px; display: inline !important=
; white-space: normal; orphans: 2; float: none; -webkit-text-stroke-width: =
0px; background-color: transparent;"><font face=3D"courier new,monospace">v=
oid f()</font></span></div><div><font face=3D"courier new,monospace">{</fon=
t></div><div><font face=3D"courier new,monospace">=C2=A0 call(string("=
hello"));</font></div><div><font face=3D"courier new,monospace">}</fon=
t></div><div><font face=3D"courier new,monospace"></font><font face=3D"cour=
ier new,monospace"></font><br></div><div>becomes</div><div><br></div><div><=
font face=3D"courier new,monospace">void f()</font></div><div><font face=3D=
"courier new,monospace">{</font></div><div><font face=3D"courier new,monosp=
ace">=C2=A0{</font></div><div><font face=3D"courier new,monospace">=C2=A0 a=
uto s =3D=C2=A0<span style=3D"text-align: left; color: rgb(34, 34, 34); tex=
t-transform: none; text-indent: 0px; letter-spacing: normal; font-size: 13p=
x; font-style: normal; font-variant: normal; font-weight: 400; text-decorat=
ion: none; word-spacing: 0px; display: inline !important; white-space: norm=
al; orphans: 2; float: none; -webkit-text-stroke-width: 0px; background-col=
or: transparent;">string("hello");</span></font></div><div><span =
style=3D"text-align: left; color: rgb(34, 34, 34); text-transform: none; te=
xt-indent: 0px; letter-spacing: normal; font-size: 13px; font-style: normal=
; font-variant: normal; font-weight: 400; text-decoration: none; word-spaci=
ng: 0px; display: inline !important; white-space: normal; orphans: 2; float=
: none; -webkit-text-stroke-width: 0px; background-color: transparent;"><fo=
nt face=3D"courier new,monospace">=C2=A0 call(s);</font></span></div><div><=
span style=3D"text-align: left; color: rgb(34, 34, 34); text-transform: non=
e; text-indent: 0px; letter-spacing: normal; font-size: 13px; font-style: n=
ormal; font-variant: normal; font-weight: 400; text-decoration: none; word-=
spacing: 0px; display: inline !important; white-space: normal; orphans: 2; =
float: none; -webkit-text-stroke-width: 0px; background-color: transparent;=
"><font face=3D"courier new,monospace">=C2=A0}</font></span></div><div><spa=
n style=3D"text-align: left; color: rgb(34, 34, 34); text-transform: none; =
text-indent: 0px; letter-spacing: normal; font-size: 13px; font-style: norm=
al; font-variant: normal; font-weight: 400; text-decoration: none; word-spa=
cing: 0px; display: inline !important; white-space: normal; orphans: 2; flo=
at: none; -webkit-text-stroke-width: 0px; background-color: transparent;"><=
font face=3D"courier new,monospace">}</font></span></div><div><span style=
=3D"text-align: left; color: rgb(34, 34, 34); text-transform: none; text-in=
dent: 0px; letter-spacing: normal; font-size: 13px; font-style: normal; fon=
t-variant: normal; font-weight: 400; text-decoration: none; word-spacing: 0=
px; display: inline !important; white-space: normal; orphans: 2; float: non=
e; -webkit-text-stroke-width: 0px; background-color: transparent;"><font fa=
ce=3D"arial,sans-serif"></font><font face=3D"courier new,monospace"></font>=
<font face=3D"courier new,monospace"></font><br></span></div><div><span sty=
le=3D"text-align: left; color: rgb(34, 34, 34); text-transform: none; text-=
indent: 0px; letter-spacing: normal; font-size: 13px; font-style: normal; f=
ont-variant: normal; font-weight: 400; text-decoration: none; word-spacing:=
0px; display: inline !important; white-space: normal; orphans: 2; float: n=
one; -webkit-text-stroke-width: 0px; background-color: transparent;"><font =
face=3D"arial,sans-serif"><i>However</i> the=C2=A0<span style=3D"display: i=
nline !important; float: none; background-color: transparent; color: rgb(34=
, 34, 34); font-family: courier new,monospace; font-size: 13px; font-style:=
normal; font-variant: normal; font-weight: 400; letter-spacing: normal; or=
phans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-t=
ransform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-s=
pacing: 0px;">auto s =3D=C2=A0</span><span style=3D"background-color: trans=
parent; border-bottom-color: rgb(34, 34, 34); border-bottom-style: none; bo=
rder-bottom-width: 0px; border-image-outset: 0; border-image-repeat: stretc=
h; border-image-slice: 100%; border-image-source: none; border-image-width:=
1; border-left-color: rgb(34, 34, 34); border-left-style: none; border-lef=
t-width: 0px; border-right-color: rgb(34, 34, 34); border-right-style: none=
; border-right-width: 0px; border-top-color: rgb(34, 34, 34); border-top-st=
yle: none; border-top-width: 0px; color: rgb(34, 34, 34); display: inline; =
float: none; font-family: courier new,monospace; font-size: 13px; font-styl=
e: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; =
margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; o=
rphans: 2; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padd=
ing-top: 0px; text-align: left; text-decoration: none; text-indent: 0px; te=
xt-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; wo=
rd-spacing: 0px;"></span><span style=3D"background-color: transparent; bord=
er-bottom-color: rgb(34, 34, 34); border-bottom-style: none; border-bottom-=
width: 0px; border-image-outset: 0; border-image-repeat: stretch; border-im=
age-slice: 100%; border-image-source: none; border-image-width: 1; border-l=
eft-color: rgb(34, 34, 34); border-left-style: none; border-left-width: 0px=
; border-right-color: rgb(34, 34, 34); border-right-style: none; border-rig=
ht-width: 0px; border-top-color: rgb(34, 34, 34); border-top-style: none; b=
order-top-width: 0px; color: rgb(34, 34, 34); display: inline; float: none;=
font-family: courier new,monospace; font-size: 13px; font-style: normal; f=
ont-variant: normal; font-weight: 400; letter-spacing: normal; margin-botto=
m: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; orphans: 2; p=
adding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px=
; text-align: left; text-decoration: none; text-indent: 0px; text-transform=
: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: =
0px;">string("hello") <font face=3D"arial,sans-serif">is executed=
<i>not</i> <i>before</i> the function call, but <i>from within</i> the fun=
ction call, going back to the original context with all the locals visible =
and so on.</font></span></font></span></div><div><span style=3D"text-align:=
left; color: rgb(34, 34, 34); text-transform: none; text-indent: 0px; lett=
er-spacing: normal; font-size: 13px; font-style: normal; font-variant: norm=
al; font-weight: 400; text-decoration: none; word-spacing: 0px; display: in=
line !important; white-space: normal; orphans: 2; float: none; -webkit-text=
-stroke-width: 0px; background-color: transparent;"><font face=3D"arial,san=
s-serif"><span style=3D"background-color: transparent; border-bottom-color:=
rgb(34, 34, 34); border-bottom-style: none; border-bottom-width: 0px; bord=
er-image-outset: 0; border-image-repeat: stretch; border-image-slice: 100%;=
border-image-source: none; border-image-width: 1; border-left-color: rgb(3=
4, 34, 34); border-left-style: none; border-left-width: 0px; border-right-c=
olor: rgb(34, 34, 34); border-right-style: none; border-right-width: 0px; b=
order-top-color: rgb(34, 34, 34); border-top-style: none; border-top-width:=
0px; color: rgb(34, 34, 34); display: inline; float: none; font-family: co=
urier new,monospace; font-size: 13px; font-style: normal; font-variant: nor=
mal; font-weight: 400; letter-spacing: normal; margin-bottom: 0px; margin-l=
eft: 0px; margin-right: 0px; margin-top: 0px; orphans: 2; padding-bottom: 0=
px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: le=
ft; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-=
text-stroke-width: 0px; white-space: normal; word-spacing: 0px;"><font face=
=3D"arial,sans-serif"><br></font></span></font></span></div><div><span styl=
e=3D"text-align: left; color: rgb(34, 34, 34); text-transform: none; text-i=
ndent: 0px; letter-spacing: normal; font-size: 13px; font-style: normal; fo=
nt-variant: normal; font-weight: 400; text-decoration: none; word-spacing: =
0px; display: inline !important; white-space: normal; orphans: 2; float: no=
ne; -webkit-text-stroke-width: 0px; background-color: transparent;"><font f=
ace=3D"arial,sans-serif"><span style=3D"background-color: transparent; bord=
er-bottom-color: rgb(34, 34, 34); border-bottom-style: none; border-bottom-=
width: 0px; border-image-outset: 0; border-image-repeat: stretch; border-im=
age-slice: 100%; border-image-source: none; border-image-width: 1; border-l=
eft-color: rgb(34, 34, 34); border-left-style: none; border-left-width: 0px=
; border-right-color: rgb(34, 34, 34); border-right-style: none; border-rig=
ht-width: 0px; border-top-color: rgb(34, 34, 34); border-top-style: none; b=
order-top-width: 0px; color: rgb(34, 34, 34); display: inline; float: none;=
font-family: courier new,monospace; font-size: 13px; font-style: normal; f=
ont-variant: normal; font-weight: 400; letter-spacing: normal; margin-botto=
m: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; orphans: 2; p=
adding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px=
; text-align: left; text-decoration: none; text-indent: 0px; text-transform=
: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: =
0px;"><font face=3D"arial,sans-serif">That model seems to me pretty "n=
atural" and easy to understand.=C2=A0</font></span></font></span></div=
><div><span style=3D"text-align: left; color: rgb(34, 34, 34); text-transfo=
rm: none; text-indent: 0px; letter-spacing: normal; font-size: 13px; font-s=
tyle: normal; font-variant: normal; font-weight: 400; text-decoration: none=
; word-spacing: 0px; display: inline !important; white-space: normal; orpha=
ns: 2; float: none; -webkit-text-stroke-width: 0px; background-color: trans=
parent;"><font face=3D"arial,sans-serif"><span style=3D"background-color: t=
ransparent; border-bottom-color: rgb(34, 34, 34); border-bottom-style: none=
; border-bottom-width: 0px; border-image-outset: 0; border-image-repeat: st=
retch; border-image-slice: 100%; border-image-source: none; border-image-wi=
dth: 1; border-left-color: rgb(34, 34, 34); border-left-style: none; border=
-left-width: 0px; border-right-color: rgb(34, 34, 34); border-right-style: =
none; border-right-width: 0px; border-top-color: rgb(34, 34, 34); border-to=
p-style: none; border-top-width: 0px; color: rgb(34, 34, 34); display: inli=
ne; float: none; font-family: courier new,monospace; font-size: 13px; font-=
style: normal; font-variant: normal; font-weight: 400; letter-spacing: norm=
al; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0p=
x; orphans: 2; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; =
padding-top: 0px; text-align: left; text-decoration: none; text-indent: 0px=
; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal=
; word-spacing: 0px;"><font face=3D"arial,sans-serif"><br></font></span></f=
ont></span></div><div><span style=3D"text-align: left; color: rgb(34, 34, 3=
4); text-transform: none; text-indent: 0px; letter-spacing: normal; font-si=
ze: 13px; font-style: normal; font-variant: normal; font-weight: 400; text-=
decoration: none; word-spacing: 0px; display: inline !important; white-spac=
e: normal; orphans: 2; float: none; -webkit-text-stroke-width: 0px; backgro=
und-color: transparent;"><font face=3D"arial,sans-serif"><span style=3D"bac=
kground-color: transparent; border-bottom-color: rgb(34, 34, 34); border-bo=
ttom-style: none; border-bottom-width: 0px; border-image-outset: 0; border-=
image-repeat: stretch; border-image-slice: 100%; border-image-source: none;=
border-image-width: 1; border-left-color: rgb(34, 34, 34); border-left-sty=
le: none; border-left-width: 0px; border-right-color: rgb(34, 34, 34); bord=
er-right-style: none; border-right-width: 0px; border-top-color: rgb(34, 34=
, 34); border-top-style: none; border-top-width: 0px; color: rgb(34, 34, 34=
); display: inline; float: none; font-family: courier new,monospace; font-s=
ize: 13px; font-style: normal; font-variant: normal; font-weight: 400; lett=
er-spacing: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px=
; margin-top: 0px; orphans: 2; padding-bottom: 0px; padding-left: 0px; padd=
ing-right: 0px; padding-top: 0px; text-align: left; text-decoration: none; =
text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; whi=
te-space: normal; word-spacing: 0px;"><font face=3D"arial,sans-serif">What =
are the benefits of the model you are talking about, how easy it is to be i=
mplemented and at what cost?</font></span></font></span></div><div><font fa=
ce=3D"arial,sans-serif">W<span style=3D"text-align: left; color: rgb(34, 34=
, 34); text-transform: none; text-indent: 0px; letter-spacing: normal; font=
-size: 13px; font-style: normal; font-variant: normal; font-weight: 400; te=
xt-decoration: none; word-spacing: 0px; display: inline !important; white-s=
pace: normal; orphans: 2; float: none; -webkit-text-stroke-width: 0px; back=
ground-color: transparent;"><span style=3D"margin: 0px; padding: 0px; borde=
r: 0px rgb(34, 34, 34); border-image: none; text-align: left; color: rgb(34=
, 34, 34); text-transform: none; text-indent: 0px; letter-spacing: normal; =
font-size: 13px; font-style: normal; font-variant: normal; font-weight: 400=
; text-decoration: none; word-spacing: 0px; display: inline; white-space: n=
ormal; orphans: 2; float: none; -webkit-text-stroke-width: 0px; background-=
color: transparent;">hat are the downsides?=C2=A0</span></span></font><span=
style=3D"text-align: left; color: rgb(34, 34, 34); text-transform: none; t=
ext-indent: 0px; letter-spacing: normal; font-size: 13px; font-style: norma=
l; font-variant: normal; font-weight: 400; text-decoration: none; word-spac=
ing: 0px; display: inline !important; white-space: normal; orphans: 2; floa=
t: none; -webkit-text-stroke-width: 0px; background-color: transparent;"><s=
pan style=3D"margin: 0px; padding: 0px; border: 0px rgb(34, 34, 34); border=
-image: none; text-align: left; color: rgb(34, 34, 34); text-transform: non=
e; text-indent: 0px; letter-spacing: normal; font-size: 13px; font-style: n=
ormal; font-variant: normal; font-weight: 400; text-decoration: none; word-=
spacing: 0px; display: inline; white-space: normal; orphans: 2; float: none=
; -webkit-text-stroke-width: 0px; background-color: transparent;"><br></spa=
n></span></div><div><font face=3D"arial,sans-serif"></font><span style=3D"t=
ext-align: left; color: rgb(34, 34, 34); text-transform: none; text-indent:=
0px; letter-spacing: normal; font-size: 13px; font-style: normal; font-var=
iant: normal; font-weight: 400; text-decoration: none; word-spacing: 0px; d=
isplay: inline !important; white-space: normal; orphans: 2; float: none; -w=
ebkit-text-stroke-width: 0px; background-color: transparent;"><font face=3D=
"arial,sans-serif"><span style=3D"background-color: transparent; border-bot=
tom-color: rgb(34, 34, 34); border-bottom-style: none; border-bottom-width:=
0px; border-image-outset: 0; border-image-repeat: stretch; border-image-sl=
ice: 100%; border-image-source: none; border-image-width: 1; border-left-co=
lor: rgb(34, 34, 34); border-left-style: none; border-left-width: 0px; bord=
er-right-color: rgb(34, 34, 34); border-right-style: none; border-right-wid=
th: 0px; border-top-color: rgb(34, 34, 34); border-top-style: none; border-=
top-width: 0px; color: rgb(34, 34, 34); display: inline; float: none; font-=
family: courier new,monospace; font-size: 13px; font-style: normal; font-va=
riant: normal; font-weight: 400; letter-spacing: normal; margin-bottom: 0px=
; margin-left: 0px; margin-right: 0px; margin-top: 0px; orphans: 2; padding=
-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text=
-align: left; text-decoration: none; text-indent: 0px; text-transform: none=
; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px;">=
<font face=3D"arial,sans-serif"><br></font></span></font></span></div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
div><br></div><div>The only way to do that is to allow the compiler to &quo=
t;instantiate" every function that captures a lazy expression. That is=
, there can't be some generic interface between caller and callee; the =
compiler must generate special-case code at every capture of an expression.=
</div><div></div><div><br></div><div>What you want makes lazy expressions i=
nto function calls.<br></div><div><br></div><blockquote class=3D"gmail_quot=
e" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-l=
eft:1ex"><div dir=3D"ltr"><div>Remember that the concept of inlining itself=
is not part of C++.</div></div></blockquote><div><br></div><div>Tell that =
to `constexpr` functions. Those are required to be inlined (in the sense th=
at a TU that uses a `constexpr` function must be able to see its definition=
). The same goes for template functions; you can't instantiate a templa=
te without having its definition visible to you.</div><div><br></div><div>T=
hat's what I'm talking about here.<br></div></div></blockquote></di=
v>
<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/5a411cf3-8012-4118-90d0-2193ed416ad5%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5a411cf3-8012-4118-90d0-2193ed416ad5=
%40isocpp.org</a>.<br />
------=_Part_45099_919005202.1527696285171--
------=_Part_45098_1098185413.1527696285171--
.
Author: florian.csdt@gmail.com
Date: Wed, 30 May 2018 09:14:49 -0700 (PDT)
Raw View
------=_Part_35733_1802710882.1527696889580
Content-Type: multipart/alternative;
boundary="----=_Part_35734_219922843.1527696889581"
------=_Part_35734_219922843.1527696889581
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le mercredi 30 mai 2018 17:25:44 UTC+2, Nicol Bolas a =C3=A9crit :
>
> On Wednesday, May 30, 2018 at 10:46:39 AM UTC-4, floria...@gmail.com=20
> wrote:
>>
>> I have the impression you misunderstood my point, so let me rephrase it.
>>
>> In my example, there is 3 expressions we need to consider:
>> print_lazy(std::string("foo")): call expression from the caller
>> std::string("foo"): lazy expression defined in the caller, executed in=
=20
>> the callee
>> std::cout << sv_expr() << std::endl: expression in the callee triggering=
=20
>> the execution of the lazy expression
>>
>> To be fair, the lazy expression returns a std::string_view, so should be=
=20
>> implicitly transformed into std::string_view(std::string("foo"))
>>
>> Now my point is, the temporary std::string object created by the lazy=20
>> expression must outlive the callee expression (std::cout << sv_expr() <<=
=20
>> std::endl).
>>
>
> Why "must" it? Just because it would have if the expression weren't lazil=
y=20
> evaluated?
>
Because you just said (below in your reply) so: it should behave as if the=
=20
lazy expression were copied into the callee expression:
so in that case: std::cout << sv_expr() << std::endl; should be equivalent=
=20
to std::cout << std::string_view(std::string("foo")) << std::endl;
If you consider the latter, the temporary std::string is not destroyed=20
before the execution of the whole expression is complete: it outlives the=
=20
expression (even if it is destroyed just before the next expression).
That is exactly what I said. Even though, I think it is not enough.
> But if you follow naively lifetime rules, this temporary will be destroye=
d=20
>> after the std::string_view is created and before std::cout << sv_expr()=
=20
>> is executed.
>>
>
> That's only true if you think of `sv_expr()` as a function call.
>
> If you think of it as being the exact equivalent to `std::cout <<=20
> std::string_view(std::string("foo"));`, then it works just fine. Evaluati=
ng=20
> that expression will manifest a temporary. And per C++ rules, by the way=
=20
> that temporary is used within the evaluated expression, the lifetime of=
=20
> that temporary will be the lifetime of the whole expression in which it i=
s=20
> used. And the "whole expression" includes `std::cout <<`.
>
> This is why thinking of lazy expressions as functions is a bad thing. The=
y=20
> aren't functions; they don't act like functions, and they can do things=
=20
> functions cannot normally do.
>
I don't think lazy expressions as functions, but it is not a replacement=20
either. If you want replacement, this is not lazy parameters you want, but=
=20
some kind of macros.
=20
>
> And the program will try to access unallocated data.
>> *This* is the issue I pointed out and that need to be solved.
>> If a proposal makes this code undefined behavior, then the whole feature=
=20
>> is broken from the beginning.
>>
>> Actually, I even think the lazy expression should outlive the whole=20
>> execution of the caller expression (print_lazy(std::string("foo"))).
>> This is what we expect from a regular expression, I don't see why it=20
>> should be different with lazy expressions.
>>
>
> I don't see why we should expect lazy expressions to behave exactly like=
=20
> non-lazy ones.
>
To be consistent. To avoid random bugs. To ease the understandability of=20
the concept. To avoid dangling references because of some very arcane rules=
..
Choose the one you prefer.
For me the difference is: it can be delayed or not executed at all. But the=
=20
rest should be identical.
Apart from syntax at the callee site, there should be no difference between=
=20
a call without lazy parameters, and a call with lazy parameters where those=
=20
have not side effect and are actually used by the callee.
This is possible only if the temporaries outlives the *caller* expression.
For instance:
void print(std::string_view sv) {
std::string_view sv2 =3D sv;
std::cout << sv2 << std::endl;
std::cerr << sv2 << std::endl;
}
void print_lazy([] -> std::string_view sv_expr) {
std::string_view sv2 =3D sv();
std::cout << sv2 << std::endl;
std::cerr << sv2 << std::endl;
}
void foo0() { print(std::string("foo")); } // definitely correct
void foo1() { print_lazy(std::string("foo")); } // Is this correct?
void foo2() { print([] -> std::string_view { return std::string("foo");=20
}()); } // not correct
foo0() is correct, there is no doubt about it.
foo2() is not correct, and I think that's perfectly fine.
But with what you say, foo1() is not correct (as std::string("foo") has=20
been destroyed before printing).
What I'm saying is: foo1() should also be correct.
=20
> ...
> =20
>
>> The only cross-ABI way to make lazy expressions work is to make them an=
=20
>> actual function, with the expected C++ semantics. At which point... they=
're=20
>> not lazy expressions anymore. They're just a transparent way to turn an=
=20
>> expression into a (lighter-weight) lambda.
>>
>
> Yes, so what? C++ is ABI agnostic, you repeat this often enough. And now=
=20
> you want to specify language constructions to solve an implementation/ABI=
=20
> issue?
>
> No, I want to specify lazy expressions so that they're *expressions*, not=
=20
> function calls. So that they work exactly as if you had copy-and-pasted t=
he=20
> expression at the site of use.
>
This is not lazy expressions, this is macros...
=20
>
> The only way to do that is to allow the compiler to "instantiate" every=
=20
> function that captures a lazy expression. That is, there can't be some=20
> generic interface between caller and callee; the compiler must generate=
=20
> special-case code at every capture of an expression.
>
Again, no: Edward's implementation gave you *exactly* the effect you want.
The compiler needs to generate code for the lazy expression at every call=
=20
site, of course.
But there is no need to "instantiate" the function that will use the lazy=
=20
expression: this has been proved many times now.
And there is no problem about generating piece of code on the fly at each=
=20
call site, otherwise templates would be dead...
=20
>
> What you want makes lazy expressions into function calls.
>
That's definitely not what I want. Otherwise I wouldn't propose to extend=
=20
lifetime of temporaries...
=20
>
> Remember that the concept of inlining itself is not part of C++.
>>
>
> Tell that to `constexpr` functions. Those are required to be inlined (in=
=20
> the sense that a TU that uses a `constexpr` function must be able to see=
=20
> its definition). The same goes for template functions; you can't=20
> instantiate a template without having its definition visible to you.
>
constexpr functions are not required to be inlined. They are required to=20
have the definition visible I agree. But a compiler not inlining a call to=
=20
a constexpr function is still compliant.
The inline keyword is not about inlining. It is about multiple definitions=
=20
in multiple TUs...
As an example: https://godbolt.org/g/hMSvZE
Back to point: even what you say is not needed: it is possible to call a=20
function taking lazy parameters without knowing the definition of that=20
function. My implementation should make it pretty clear.
=20
>
> That's what I'm talking about here.
>
=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 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/c782130b-8ff7-4339-b047-0024a1f6a9c2%40isocpp.or=
g.
------=_Part_35734_219922843.1527696889581
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le mercredi 30 mai 2018 17:25:44 UTC+2, Nicol Bola=
s a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">On Wednesday, May 30, 2018 at 10:46:39 AM UTC-4, <a>floria...@gmai=
l.com</a> 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"><d=
iv><div>I have the impression you misunderstood my point, so let me rephras=
e it.<br><br>In my example, there is 3 expressions we need to consider:<br>=
<span style=3D"font-family:courier new,monospace">print_lazy(std::string(&q=
uot;foo"))</span><wbr>: call expression from the caller<br><span style=
=3D"font-family:courier new,monospace">std::string("foo")</span>:=
lazy expression defined in the caller, executed in the callee<br><span sty=
le=3D"font-family:courier new,monospace">std::cout << sv_expr() <&=
lt; std::endl</span>: expression in the callee triggering the execution of =
the lazy expression<br><br>To
be fair, the lazy expression returns a <span style=3D"font-family:courier =
new,monospace">std::string_view</span>, so should be=20
implicitly transformed into <span style=3D"font-family:courier new,monospac=
e">std::string_view(std::string("<wbr>foo"))</span><br><br>Now
my point is, the temporary std::string object created by the lazy=20
expression must outlive the callee expression (<span style=3D"font-family:c=
ourier new,monospace">std::cout <<=20
sv_expr() << std::endl</span>).<br></div></div></div></blockquote><di=
v><br></div><div>Why "must" it? Just because it would have if the=
expression weren't lazily evaluated?<br></div></div></blockquote><div>=
<br></div><div>Because you just said (below in your reply) so: it should be=
have as if the lazy expression were copied into the callee expression:</div=
><div>so in that case: <span style=3D"font-family: courier new, monospace;"=
>std::cout << sv_expr() << std::endl;</span> should be equivale=
nt to <span style=3D"font-family: courier new, monospace;">std::cout <&l=
t; std::string_view(std::string("foo")) << std::endl;</span=
></div><div><br></div><div>If you consider the latter, the temporary <span =
style=3D"font-family: courier new, monospace;">std::string</span> is not de=
stroyed before the execution of the whole expression is complete: it outliv=
es the expression (even if it is destroyed just before the next expression)=
..</div><div>That is exactly what I said. Even though, I think it is not eno=
ugh.<br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><=
div dir=3D"ltr"><div></div><div><br></div><blockquote class=3D"gmail_quote"=
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-lef=
t:1ex"><div dir=3D"ltr"><div><div>But if you follow naively lifetime rules,=
this temporary will be destroyed after the <span style=3D"font-family:cour=
ier new,monospace">std::string_view</span> is created and before <span styl=
e=3D"font-family:courier new,monospace">std::cout << sv_expr()</span>=
is executed.</div></div></div></blockquote><div><br></div><div>That's =
only true if you think of `sv_expr()` as a function call.</div><div><br></d=
iv><div>If you think of it as being the exact equivalent to `std::cout <=
< std::string_view(std::string("<wbr>foo"));`, then it works j=
ust fine. Evaluating that expression will manifest a temporary. And per C++=
rules, by the way that temporary is used within the evaluated expression, =
the lifetime of that temporary will be the lifetime of the whole expression=
in which it is used. And the "whole expression" includes `std::c=
out <<`.<br></div><div><br></div><div>This is why thinking of lazy ex=
pressions as functions is a bad thing. They aren't functions; they don&=
#39;t act like functions, and they can do things functions cannot normally =
do.<br></div></div></blockquote><div><br></div><div>I don't think lazy =
expressions as functions, but it is not a replacement either. If you want r=
eplacement, this is not lazy parameters you want, but some kind of macros.<=
br></div><div>=C2=A0</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></div><div><br></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1=
ex"><div dir=3D"ltr"><div><div>And the program will try to access unallocat=
ed data.<br></div><div><b>This</b> is the issue I pointed out and that need=
to be solved.</div><div>If a proposal makes this code undefined behavior, =
then the whole feature is broken from the beginning.<br><div><br></div>Actu=
ally, I even think the lazy expression should outlive the whole execution o=
f the caller expression (<span style=3D"font-family:courier new,monospace">=
print_lazy(std::string("foo")<wbr>)</span>).</div><div>This is wh=
at we expect from a regular expression, I don't see why it should be di=
fferent with lazy expressions.<br></div></div></div></blockquote><div><br><=
/div><div>I don't see why we should expect lazy expressions to behave e=
xactly like non-lazy ones.<br></div></div></blockquote><div><br></div><div>=
To be consistent. To avoid random bugs. To ease the understandability of th=
e concept. To avoid dangling references because of some very arcane rules.<=
br></div><div>Choose the one you prefer.</div><div>For me the difference is=
: it can be delayed or not executed at all. But the rest should be identica=
l.</div><div><br></div><div>Apart from syntax at the callee site, there sho=
uld be no difference between a call without lazy parameters, and a call wit=
h lazy parameters where those have not side effect and are actually used by=
the callee.</div><div>This is possible only if the temporaries outlives th=
e <b>caller</b> expression.</div><div><br></div><div>For instance:</div><di=
v><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: #008;" class=3D"styled-by-prettify">void</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">print</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">std</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">string_view sv</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 std</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">st=
ring_view sv2 </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> sv=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><c=
ode class=3D"prettyprint"><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 std</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">cout </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
<<</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> s=
v2 </span><span style=3D"color: #660;" class=3D"styled-by-prettify"><<=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">endl</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"></span></code><code class=3D"prettypr=
int"><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 s=
td</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">cerr </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify"><<</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> sv2 </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><<</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">endl</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"></span></code><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">vo=
id</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> print_l=
azy</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: #660;" class=3D"styled-by-prettify">-></span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">string_view sv_expr</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #00=
0;" 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"><br>=C2=A0 std</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify">string_view sv2 </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> sv</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">();</span><code class=3D"prettyprint"><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 std</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">cout </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify"><<</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> sv2 << std::endl;</span></code><code class=3D"prettypri=
nt"><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 st=
d</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">cerr </span><span=
style=3D"color: #660;" class=3D"styled-by-prettify"><<</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> sv2 << std::endl;=
</span></code><span style=3D"color: #000;" class=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><br>void foo0(=
) { print(std::string("foo")); } // definitely correct<br>void fo=
o1() { print_lazy(std::string("foo")); } // Is this correct?<br>v=
oid foo2() { print([] -> std::string_view { return std::string("foo=
"); }()); } // not correct<br></span></div></code></div><span style=3D=
"font-family: courier new, monospace;">foo0()</span> is correct, there is n=
o doubt about it.</div><div><span style=3D"font-family: courier new, monosp=
ace;">foo2()</span> is not correct, and I think that's perfectly fine.<=
/div><div><br></div><div>But with what you say, <span style=3D"font-family:=
courier new, monospace;">foo1()</span> is not correct (as <span style=3D"f=
ont-family: courier new, monospace;">std::string("foo")</span> ha=
s been destroyed before printing).</div><div>What I'm saying is: <span =
style=3D"font-family: courier new, monospace;">foo1()</span> should also be=
correct.</div><div><br></div><div><br></div><div>=C2=A0</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
#ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div dir=3D"ltr">...<div>=
=C2=A0</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>T=
he
only cross-ABI way to make lazy expressions work is to make them an=20
actual function, with the expected C++ semantics. At which point...=20
they're not lazy expressions anymore. They're just a transparent wa=
y to=20
turn an expression into a (lighter-weight) lambda.</div></div></blockquote>=
<div><br></div><div>Yes,
so what? C++ is ABI agnostic, you repeat this often enough. And now you
want to specify language constructions to solve an implementation/ABI=20
issue?</div></div></div></blockquote><div><blockquote class=3D"gmail_quote"=
style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 2=
04); padding-left: 1ex;"><div><div style=3D"overflow: auto"><div style=3D"m=
ax-height: 10000px;"><div dir=3D"ltr"><div class=3D"F0XO1GC-Db-b"><div><br>=
</div></div><div>No, I want to specify lazy expressions so that they're=
<i>expressions</i>, not function calls. So that they work exactly as if yo=
u had copy-and-pasted the expression at the site of use.</div></div></div><=
/div></div></blockquote><div><br></div><div>This is not lazy expressions, t=
his is macros...<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote=
" style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, =
204); padding-left: 1ex;"><div><div style=3D"overflow: auto"><div style=3D"=
max-height: 10000px;"><div dir=3D"ltr"><div><br></div><div>The
only way to do that is to allow the compiler to "instantiate" ev=
ery=20
function that captures a lazy expression. That is, there can't be some=
=20
generic interface between caller and callee; the compiler must generate=20
special-case code at every capture of an expression.</div></div></div></div=
></div></blockquote><div><br></div><div>Again, no: Edward's implementat=
ion gave you <b>exactly</b> the effect you want.</div><div>The compiler nee=
ds to generate code for the lazy expression at every call site, of course.<=
/div><div>But there is no need to "instantiate" the function that=
will use the lazy expression: this has been proved many times now.</div><d=
iv><br></div><div>And there is no problem about generating piece of code on=
the fly at each call site, otherwise templates would be dead...<br></div><=
div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px =
0px 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><=
div><div style=3D"overflow: auto"><div style=3D"max-height: 10000px;"><div =
dir=3D"ltr"><div><br></div><div>What you want makes lazy expressions into f=
unction calls.<br></div></div></div></div></div></blockquote><div><br></div=
><div>That's definitely not what I want. Otherwise I wouldn't propo=
se to extend lifetime of temporaries...<br></div><div>=C2=A0</div><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1=
px solid rgb(204, 204, 204); padding-left: 1ex;"><div><div style=3D"overflo=
w: auto"><div style=3D"max-height: 10000px;"><div dir=3D"ltr"><div></div><d=
iv class=3D"F0XO1GC-Db-b"><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>Remember that the concept of inlining itself is=
not part of C++.</div></div></blockquote><div><br></div></div><div>Tell
that to `constexpr` functions. Those are required to be inlined (in the
sense that a TU that uses a `constexpr` function must be able to see=20
its definition). The same goes for template functions; you can't=20
instantiate a template without having its definition visible to you.</div><=
/div></div></div></div></blockquote><div><br></div><div><span style=3D"font=
-family: courier new, monospace;">constexpr</span> functions are not requir=
ed to be inlined. They are required to have the definition visible I agree.=
But a compiler not inlining a call to a <span style=3D"font-family: courie=
r new, monospace;">constexpr</span> function is still compliant.</div><div>=
The <span style=3D"font-family: courier new, monospace;">inline</span> keyw=
ord is not about inlining. It is about multiple definitions in multiple TUs=
....</div><div>As an example: https://godbolt.org/g/hMSvZE</div><div><br></d=
iv><div>Back to point: even what you say is not needed: it is possible to c=
all a function taking lazy parameters without knowing the definition of tha=
t function. My implementation should make it pretty clear.<br></div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px =
0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div>=
<div style=3D"overflow: auto"><div style=3D"max-height: 10000px;"><div dir=
=3D"ltr"><div><br></div><div>That's what I'm talking about here.<br=
></div></div></div></div></div></blockquote>=C2=A0 <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/c782130b-8ff7-4339-b047-0024a1f6a9c2%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/c782130b-8ff7-4339-b047-0024a1f6a9c2=
%40isocpp.org</a>.<br />
------=_Part_35734_219922843.1527696889581--
------=_Part_35733_1802710882.1527696889580--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 30 May 2018 09:42:06 -0700 (PDT)
Raw View
------=_Part_45009_1709828131.1527698526176
Content-Type: multipart/alternative;
boundary="----=_Part_45010_661946430.1527698526177"
------=_Part_45010_661946430.1527698526177
Content-Type: text/plain; charset="UTF-8"
On Wednesday, May 30, 2018 at 12:04:45 PM UTC-4, mihailn...@gmail.com wrote:
>
> On Wednesday, May 30, 2018 at 6:35:47 PM UTC+3, Nicol Bolas wrote:
>>
>> On Wednesday, May 30, 2018 at 10:46:39 AM UTC-4, floria...@gmail.com
>> wrote:
>>>
>>>
>>>
>>>>
>>>> I agree that that would be a better semantic, but it implies a
>>>>> different ABI to that proposed (in passing) in P0927; rather than a single
>>>>> code pointer code whose invocation evaluates the expression, we need two
>>>>> code pointers with the second destructing temporaries, or a single code
>>>>> pointer with signature T(void* caller_stack, enum class action {
>>>>> evaluate, destruct_temporaries}). The caller would still need to
>>>>> reserve stack space for any temporaries in the lazily evaluated expression,
>>>>> but would not need to maintain a flag indicating whether temporaries had
>>>>> been constructed, as calling the code pointer to perform cleanup would be
>>>>> the responsibility of the callee.
>>>>>
>>>>
>>>> ABI is essentially irrelevant, because the only way you can have lazy
>>>> expressions work *correctly* is if the function(s) that uses them are
>>>> inlined, relative to the function that provided the expression.
>>>>
>>>
>>> That's not true, there are many ways to implement this to have the
>>> correct behavior without inlining. Edward's solution is one.
>>>
>> And as I said before, I don't what you call "the *correct* behavior" is
>>> what we want.
>>>
>>>
>>>> The only cross-ABI way to make lazy expressions work is to make them an
>>>> actual function, with the expected C++ semantics. At which point... they're
>>>> not lazy expressions anymore. They're just a transparent way to turn an
>>>> expression into a (lighter-weight) lambda.
>>>>
>>>
>>> Yes, so what? C++ is ABI agnostic, you repeat this often enough. And now
>>> you want to specify language constructions to solve an implementation/ABI
>>> issue?
>>>
>>
>> No, I want to specify lazy expressions so that they're *expressions*,
>> not function calls. So that they work exactly as if you had copy-and-pasted
>> the expression at the site of use.
>>
>
> Any particular reason to want them to behave exactly like that? Any
> pointer or examples of why this is required?
>
> To this point I understood layzies are like this (correct me if I am wrong)
> void f()
> {
> call(string("hello"));
> }
>
> becomes
>
> void f()
> {
> {
> auto s = string("hello");
> call(s);
> }
> }
>
> *However* the auto s = string("hello") is executed *not* *before* the
> function call, but *from within* the function call, going back to the
> original context with all the locals visible and so on.
>
> That model seems to me pretty "natural" and easy to understand.
>
A function in C++ is isolated from any non-global state outside of its
parameters. That's a basic aspect of how functions work.
The model you're talking about breaks this. A parameter will start
manipulating memory outside of that function's scope and outside of the
scope of that function's parameters. It will create temporaries to objects
outside of that function's scope. It will begin the lifetime of objects
whose lifetime ends well outside of its own scope. That now makes it
difficult to reason about the results of that expression.
For example, consider the case where one of the sub-expressions of a
captured expression throws, and the function that evaluates the expression
catches it, so that the exception doesn't get back to the function that
provided the expression. Well, what happens to the temporaries created by
the captured expression *prior* to the throw?
In normal expressions (and in copy-and-paste lazy evaluation), the way this
works is normal. Any temporaries created are destroyed by stack unwinding.
Those temporaries were created in the current scope, so when the scope
exits, those temporaries are destroyed.
But with your way, temporaries are manifested *outside* of the scope
they're created in. They are supposed to live beyond that scope. So if you
catch the exception before the scope leaves... what happens to them? When
do they get destroyed? What is the right answer?
If those temporaries are not destroyed, then now you have a situation where
some of the temporaries were successfully created and some were not. How
does that work when you leave the capturing function? And if they are
destroyed... how does that make sense? You haven't unwound the stack past
their scope, so there's no reason for them to be destroyed.
So I would say that copy-and-paste evaluation seems more "natural" and
"easy to understand".
--
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/17034296-932f-4c1a-a22d-d93e1745c3ba%40isocpp.org.
------=_Part_45010_661946430.1527698526177
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, May 30, 2018 at 12:04:45 PM UTC-4, mihailn..=
..@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"=
ltr">On Wednesday, May 30, 2018 at 6:35:47 PM UTC+3, Nicol Bolas wrote:<blo=
ckquote 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">On Wednesday, May 30, =
2018 at 10:46:39 AM UTC-4, <a>floria...@gmail.com</a> wrote:<blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc=
solid;padding-left:1ex"><div dir=3D"ltr"><div>=C2=A0</div><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr"><div><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div></div><div>I agree that that w=
ould be a better semantic, but it implies a different ABI to that proposed =
(in passing) in P0927; rather than a single code pointer code whose invocat=
ion evaluates the expression, we need two code pointers with the second des=
tructing temporaries, or a single code pointer with signature <font face=3D=
"monospace, monospace">T(void* caller_stack, enum class action { evaluate, =
destruct_temporaries})</font>. The caller would still need to reserve stack=
space for any temporaries in the lazily evaluated expression, but would no=
t need to maintain a flag indicating whether temporaries had been construct=
ed, as calling the code pointer to perform cleanup would be the responsibil=
ity of the callee.</div></div></blockquote><div><br></div><div></div><div>A=
BI is essentially irrelevant, because the only way you can have lazy expres=
sions work <i>correctly</i> is if the function(s) that uses them are inline=
d, relative to the function that provided the expression.</div></div></bloc=
kquote><div><br></div><div>That's not true, there are many ways to impl=
ement this to have the correct behavior without inlining. Edward's solu=
tion is one. <br></div></div></blockquote><blockquote class=3D"gmail_quote"=
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-lef=
t:1ex"><div dir=3D"ltr"><div>And as I said before, I don't what you cal=
l "the <i>correct</i> behavior" is what we want.<br></div><div>=
=C2=A0</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><=
/div><div>The only cross-ABI way to make lazy expressions work is to make t=
hem an actual function, with the expected C++ semantics. At which point... =
they're not lazy expressions anymore. They're just a transparent wa=
y to turn an expression into a (lighter-weight) lambda.</div></div></blockq=
uote><div><br></div><div>Yes, so what? C++ is ABI agnostic, you repeat this=
often enough. And now you want to specify language constructions to solve =
an implementation/ABI issue?</div></div></blockquote><div><br></div><div>No=
, I want to specify lazy expressions so that they're <i>expressions</i>=
, not function calls. So that they work exactly as if you had copy-and-past=
ed the expression at the site of use.</div></div></blockquote><div><br></di=
v><div>Any particular reason to want them to behave exactly like that? Any =
pointer or examples of why this is required? =C2=A0</div><div><br></div><di=
v>To this point I understood layzies are like this (correct me if I am wron=
g)</div><div><span style=3D"text-align:left;color:rgb(34,34,34);text-transf=
orm:none;text-indent:0px;letter-spacing:normal;font-size:13px;font-style:no=
rmal;font-variant:normal;font-weight:400;text-decoration:none;word-spacing:=
0px;display:inline!important;white-space:normal;float:none;background-color=
:transparent"><font face=3D"courier new,monospace">void f()</font></span></=
div><div><font face=3D"courier new,monospace">{</font></div><div><font face=
=3D"courier new,monospace">=C2=A0 call(string("hello"));</font></=
div><div><font face=3D"courier new,monospace">}</font></div><div><font face=
=3D"courier new,monospace"></font><font face=3D"courier new,monospace"></fo=
nt><br></div><div>becomes</div><div><br></div><div><font face=3D"courier ne=
w,monospace">void f()</font></div><div><font face=3D"courier new,monospace"=
>{</font></div><div><font face=3D"courier new,monospace">=C2=A0{</font></di=
v><div><font face=3D"courier new,monospace">=C2=A0 auto s =3D=C2=A0<span st=
yle=3D"text-align:left;color:rgb(34,34,34);text-transform:none;text-indent:=
0px;letter-spacing:normal;font-size:13px;font-style:normal;font-variant:nor=
mal;font-weight:400;text-decoration:none;word-spacing:0px;display:inline!im=
portant;white-space:normal;float:none;background-color:transparent">string(=
"hello");</span></font></div><div><span style=3D"text-align:left;=
color:rgb(34,34,34);text-transform:none;text-indent:0px;letter-spacing:norm=
al;font-size:13px;font-style:normal;font-variant:normal;font-weight:400;tex=
t-decoration:none;word-spacing:0px;display:inline!important;white-space:nor=
mal;float:none;background-color:transparent"><font face=3D"courier new,mono=
space">=C2=A0 call(s);</font></span></div><div><span style=3D"text-align:le=
ft;color:rgb(34,34,34);text-transform:none;text-indent:0px;letter-spacing:n=
ormal;font-size:13px;font-style:normal;font-variant:normal;font-weight:400;=
text-decoration:none;word-spacing:0px;display:inline!important;white-space:=
normal;float:none;background-color:transparent"><font face=3D"courier new,m=
onospace">=C2=A0}</font></span></div><div><span style=3D"text-align:left;co=
lor:rgb(34,34,34);text-transform:none;text-indent:0px;letter-spacing:normal=
;font-size:13px;font-style:normal;font-variant:normal;font-weight:400;text-=
decoration:none;word-spacing:0px;display:inline!important;white-space:norma=
l;float:none;background-color:transparent"><font face=3D"courier new,monosp=
ace">}</font></span></div><div><span style=3D"text-align:left;color:rgb(34,=
34,34);text-transform:none;text-indent:0px;letter-spacing:normal;font-size:=
13px;font-style:normal;font-variant:normal;font-weight:400;text-decoration:=
none;word-spacing:0px;display:inline!important;white-space:normal;float:non=
e;background-color:transparent"><font face=3D"arial,sans-serif"></font><fon=
t face=3D"courier new,monospace"></font><font face=3D"courier new,monospace=
"></font><br></span></div><div><span style=3D"text-align:left;color:rgb(34,=
34,34);text-transform:none;text-indent:0px;letter-spacing:normal;font-size:=
13px;font-style:normal;font-variant:normal;font-weight:400;text-decoration:=
none;word-spacing:0px;display:inline!important;white-space:normal;float:non=
e;background-color:transparent"><font face=3D"arial,sans-serif"><i>However<=
/i> the=C2=A0<span style=3D"display:inline!important;float:none;background-=
color:transparent;color:rgb(34,34,34);font-family:courier new,monospace;fon=
t-size:13px;font-style:normal;font-variant:normal;font-weight:400;letter-sp=
acing:normal;text-align:left;text-decoration:none;text-indent:0px;text-tran=
sform:none;white-space:normal;word-spacing:0px">auto s =3D=C2=A0</span><spa=
n style=3D"background-color:transparent;border-bottom-color:rgb(34,34,34);b=
order-bottom-style:none;border-bottom-width:0px;border-left-color:rgb(34,34=
,34);border-left-style:none;border-left-width:0px;border-right-color:rgb(34=
,34,34);border-right-style:none;border-right-width:0px;border-top-color:rgb=
(34,34,34);border-top-style:none;border-top-width:0px;color:rgb(34,34,34);d=
isplay:inline;float:none;font-family:courier new,monospace;font-size:13px;f=
ont-style:normal;font-variant:normal;font-weight:400;letter-spacing:normal;=
margin-bottom:0px;margin-left:0px;margin-right:0px;margin-top:0px;padding-b=
ottom:0px;padding-left:0px;padding-right:0px;padding-top:0px;text-align:lef=
t;text-decoration:none;text-indent:0px;text-transform:none;white-space:norm=
al;word-spacing:0px"></span><span style=3D"background-color:transparent;bor=
der-bottom-color:rgb(34,34,34);border-bottom-style:none;border-bottom-width=
:0px;border-left-color:rgb(34,34,34);border-left-style:none;border-left-wid=
th:0px;border-right-color:rgb(34,34,34);border-right-style:none;border-righ=
t-width:0px;border-top-color:rgb(34,34,34);border-top-style:none;border-top=
-width:0px;color:rgb(34,34,34);display:inline;float:none;font-family:courie=
r new,monospace;font-size:13px;font-style:normal;font-variant:normal;font-w=
eight:400;letter-spacing:normal;margin-bottom:0px;margin-left:0px;margin-ri=
ght:0px;margin-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0p=
x;padding-top:0px;text-align:left;text-decoration:none;text-indent:0px;text=
-transform:none;white-space:normal;word-spacing:0px">string("hello&quo=
t;) <font face=3D"arial,sans-serif">is executed <i>not</i> <i>before</i> th=
e function call, but <i>from within</i> the function call, going back to th=
e original context with all the locals visible and so on.</font></span></fo=
nt></span> <br></div></div></blockquote><blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-le=
ft: 1ex;"><div dir=3D"ltr"><div><span style=3D"text-align:left;color:rgb(34=
,34,34);text-transform:none;text-indent:0px;letter-spacing:normal;font-size=
:13px;font-style:normal;font-variant:normal;font-weight:400;text-decoration=
:none;word-spacing:0px;display:inline!important;white-space:normal;float:no=
ne;background-color:transparent"><font face=3D"arial,sans-serif"><span styl=
e=3D"background-color:transparent;border-bottom-color:rgb(34,34,34);border-=
bottom-style:none;border-bottom-width:0px;border-left-color:rgb(34,34,34);b=
order-left-style:none;border-left-width:0px;border-right-color:rgb(34,34,34=
);border-right-style:none;border-right-width:0px;border-top-color:rgb(34,34=
,34);border-top-style:none;border-top-width:0px;color:rgb(34,34,34);display=
:inline;float:none;font-family:courier new,monospace;font-size:13px;font-st=
yle:normal;font-variant:normal;font-weight:400;letter-spacing:normal;margin=
-bottom:0px;margin-left:0px;margin-right:0px;margin-top:0px;padding-bottom:=
0px;padding-left:0px;padding-right:0px;padding-top:0px;text-align:left;text=
-decoration:none;text-indent:0px;text-transform:none;white-space:normal;wor=
d-spacing:0px"><font face=3D"arial,sans-serif"><br></font></span></font></s=
pan></div><div><span style=3D"text-align:left;color:rgb(34,34,34);text-tran=
sform:none;text-indent:0px;letter-spacing:normal;font-size:13px;font-style:=
normal;font-variant:normal;font-weight:400;text-decoration:none;word-spacin=
g:0px;display:inline!important;white-space:normal;float:none;background-col=
or:transparent"><font face=3D"arial,sans-serif"><span style=3D"background-c=
olor:transparent;border-bottom-color:rgb(34,34,34);border-bottom-style:none=
;border-bottom-width:0px;border-left-color:rgb(34,34,34);border-left-style:=
none;border-left-width:0px;border-right-color:rgb(34,34,34);border-right-st=
yle:none;border-right-width:0px;border-top-color:rgb(34,34,34);border-top-s=
tyle:none;border-top-width:0px;color:rgb(34,34,34);display:inline;float:non=
e;font-family:courier new,monospace;font-size:13px;font-style:normal;font-v=
ariant:normal;font-weight:400;letter-spacing:normal;margin-bottom:0px;margi=
n-left:0px;margin-right:0px;margin-top:0px;padding-bottom:0px;padding-left:=
0px;padding-right:0px;padding-top:0px;text-align:left;text-decoration:none;=
text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><f=
ont face=3D"arial,sans-serif">That model seems to me pretty "natural&q=
uot; and easy to understand.</font></span></font></span></div></div></block=
quote><div><br></div><div>A function in C++ is isolated from any non-global=
state outside of its parameters. That's a basic aspect of how function=
s work.</div><div><br></div><div>The model you're talking about breaks =
this. A parameter will start manipulating memory outside of that function&#=
39;s scope and outside of the scope of that function's parameters. It w=
ill create temporaries to objects outside of that function's scope. It =
will begin the lifetime of objects whose lifetime ends well outside of its =
own scope. That now makes it difficult to reason about the results of that =
expression.</div><div><br></div><div>For example, consider the case where o=
ne of the sub-expressions of a captured expression throws, and the function=
that evaluates the expression catches it, so that the exception doesn'=
t get back to the function that provided the expression. Well, what happens=
to the temporaries created by the captured expression <i>prior</i> to the =
throw?</div><div><br></div><div>In normal expressions (and in copy-and-past=
e lazy evaluation), the way this works is normal. Any temporaries created a=
re destroyed by stack unwinding. Those temporaries were created in the curr=
ent scope, so when the scope exits, those temporaries are destroyed.</div><=
div><br></div><div>But with your way, temporaries are manifested <i>outside=
</i> of the scope they're created in. They are supposed to live beyond =
that scope. So if you catch the exception before the scope leaves... what h=
appens to them? When do they get destroyed? What is the right answer?</div>=
<div><br></div><div>If those temporaries are not destroyed, then now you ha=
ve a situation where some of the temporaries were successfully created and =
some were not. How does that work when you leave the capturing function? An=
d if they are destroyed... how does that make sense? You haven't unwoun=
d the stack past their scope, so there's no reason for them to be destr=
oyed.<br></div><div></div><div><br></div><div>So I would say that copy-and-=
paste evaluation seems more "natural" and "easy to understan=
d".<br></div><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/17034296-932f-4c1a-a22d-d93e1745c3ba%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/17034296-932f-4c1a-a22d-d93e1745c3ba=
%40isocpp.org</a>.<br />
------=_Part_45010_661946430.1527698526177--
------=_Part_45009_1709828131.1527698526176--
.
Author: florian.csdt@gmail.com
Date: Wed, 30 May 2018 09:47:14 -0700 (PDT)
Raw View
------=_Part_30192_927003590.1527698834185
Content-Type: multipart/alternative;
boundary="----=_Part_30193_1632524272.1527698834185"
------=_Part_30193_1632524272.1527698834185
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le mercredi 30 mai 2018 18:42:06 UTC+2, Nicol Bolas a =C3=A9crit :
>
> On Wednesday, May 30, 2018 at 12:04:45 PM UTC-4, mihailn...@gmail.com=20
> wrote:
>>
>> On Wednesday, May 30, 2018 at 6:35:47 PM UTC+3, Nicol Bolas wrote:
>>>
>>> On Wednesday, May 30, 2018 at 10:46:39 AM UTC-4, floria...@gmail.com=20
>>> wrote:
>>>>
>>>> =20
>>>>
>>>>>
>>>>> I agree that that would be a better semantic, but it implies a=20
>>>>>> different ABI to that proposed (in passing) in P0927; rather than a =
single=20
>>>>>> code pointer code whose invocation evaluates the expression, we need=
two=20
>>>>>> code pointers with the second destructing temporaries, or a single c=
ode=20
>>>>>> pointer with signature T(void* caller_stack, enum class action {=20
>>>>>> evaluate, destruct_temporaries}). The caller would still need to=20
>>>>>> reserve stack space for any temporaries in the lazily evaluated expr=
ession,=20
>>>>>> but would not need to maintain a flag indicating whether temporaries=
had=20
>>>>>> been constructed, as calling the code pointer to perform cleanup wou=
ld be=20
>>>>>> the responsibility of the callee.
>>>>>>
>>>>>
>>>>> ABI is essentially irrelevant, because the only way you can have lazy=
=20
>>>>> expressions work *correctly* is if the function(s) that uses them are=
=20
>>>>> inlined, relative to the function that provided the expression.
>>>>>
>>>>
>>>> That's not true, there are many ways to implement this to have the=20
>>>> correct behavior without inlining. Edward's solution is one.=20
>>>>
>>> And as I said before, I don't what you call "the *correct* behavior" is=
=20
>>>> what we want.
>>>> =20
>>>>
>>>>> The only cross-ABI way to make lazy expressions work is to make them=
=20
>>>>> an actual function, with the expected C++ semantics. At which point..=
..=20
>>>>> they're not lazy expressions anymore. They're just a transparent way =
to=20
>>>>> turn an expression into a (lighter-weight) lambda.
>>>>>
>>>>
>>>> Yes, so what? C++ is ABI agnostic, you repeat this often enough. And=
=20
>>>> now you want to specify language constructions to solve an=20
>>>> implementation/ABI issue?
>>>>
>>>
>>> No, I want to specify lazy expressions so that they're *expressions*,=
=20
>>> not function calls. So that they work exactly as if you had copy-and-pa=
sted=20
>>> the expression at the site of use.
>>>
>>
>> Any particular reason to want them to behave exactly like that? Any=20
>> pointer or examples of why this is required? =20
>>
>> To this point I understood layzies are like this (correct me if I am=20
>> wrong)
>> void f()
>> {
>> call(string("hello"));
>> }
>>
>> becomes
>>
>> void f()
>> {
>> {
>> auto s =3D string("hello");
>> call(s);
>> }
>> }
>>
>> *However* the auto s =3D string("hello") is executed *not* *before* the=
=20
>> function call, but *from within* the function call, going back to the=20
>> original context with all the locals visible and so on.=20
>>
>
>> That model seems to me pretty "natural" and easy to understand.
>>
>
> A function in C++ is isolated from any non-global state outside of its=20
> parameters. That's a basic aspect of how functions work.
>
> The model you're talking about breaks this. A parameter will start=20
> manipulating memory outside of that function's scope and outside of the=
=20
> scope of that function's parameters. It will create temporaries to object=
s=20
> outside of that function's scope. It will begin the lifetime of objects=
=20
> whose lifetime ends well outside of its own scope. That now makes it=20
> difficult to reason about the results of that expression.
>
> For example, consider the case where one of the sub-expressions of a=20
> captured expression throws, and the function that evaluates the expressio=
n=20
> catches it, so that the exception doesn't get back to the function that=
=20
> provided the expression. Well, what happens to the temporaries created by=
=20
> the captured expression *prior* to the throw?
>
> In normal expressions (and in copy-and-paste lazy evaluation), the way=20
> this works is normal. Any temporaries created are destroyed by stack=20
> unwinding. Those temporaries were created in the current scope, so when t=
he=20
> scope exits, those temporaries are destroyed.
>
> But with your way, temporaries are manifested *outside* of the scope=20
> they're created in. They are supposed to live beyond that scope. So if yo=
u=20
> catch the exception before the scope leaves... what happens to them? When=
=20
> do they get destroyed? What is the right answer?
>
> If those temporaries are not destroyed, then now you have a situation=20
> where some of the temporaries were successfully created and some were not=
..=20
> How does that work when you leave the capturing function? And if they are=
=20
> destroyed... how does that make sense? You haven't unwound the stack past=
=20
> their scope, so there's no reason for them to be destroyed.
>
All those questions have been answered and solved by the example=20
implementation I gave.
Execptions look natural.
The lazy evaluation scope is a bit different from other scopes in the sense=
=20
that it is not nested with other scopes, it is in "parallel". But lifetime=
=20
of temporaries within this scope follow classical rules.
=20
>
> So I would say that copy-and-paste evaluation seems more "natural" and=20
> "easy to understand".
>
>
--=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/79e284e2-ecd3-4b64-9a14-a8e303d5ad27%40isocpp.or=
g.
------=_Part_30193_1632524272.1527698834185
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le mercredi 30 mai 2018 18:42:06 UTC+2, Nicol Bola=
s a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">On Wednesday, May 30, 2018 at 12:04:45 PM UTC-4, <a>mihailn...@gma=
il.com</a> 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">O=
n Wednesday, May 30, 2018 at 6:35:47 PM UTC+3, Nicol Bolas wrote:<blockquot=
e class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px=
#ccc solid;padding-left:1ex"><div dir=3D"ltr">On Wednesday, May 30, 2018 a=
t 10:46:39 AM UTC-4, <a>floria...@gmail.com</a> 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"><div>=C2=A0</div><blockquote class=3D"g=
mail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;=
padding-left:1ex"><div dir=3D"ltr"><div><br></div><blockquote class=3D"gmai=
l_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr"><div></div><div>I agree that that would be =
a better semantic, but it implies a different ABI to that proposed (in pass=
ing) in P0927; rather than a single code pointer code whose invocation eval=
uates the expression, we need two code pointers with the second destructing=
temporaries, or a single code pointer with signature <font face=3D"monospa=
ce, monospace">T(void* caller_stack, enum class action { evaluate, destruct=
_temporaries})</font>. The caller would still need to reserve stack space f=
or any temporaries in the lazily evaluated expression, but would not need t=
o maintain a flag indicating whether temporaries had been constructed, as c=
alling the code pointer to perform cleanup would be the responsibility of t=
he callee.</div></div></blockquote><div><br></div><div></div><div>ABI is es=
sentially irrelevant, because the only way you can have lazy expressions wo=
rk <i>correctly</i> is if the function(s) that uses them are inlined, relat=
ive to the function that provided the expression.</div></div></blockquote><=
div><br></div><div>That's not true, there are many ways to implement th=
is to have the correct behavior without inlining. Edward's solution is =
one. <br></div></div></blockquote><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>And as I said before, I don't what you call &quo=
t;the <i>correct</i> behavior" is what we want.<br></div><div>=C2=A0</=
div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div></div><di=
v>The only cross-ABI way to make lazy expressions work is to make them an a=
ctual function, with the expected C++ semantics. At which point... they'=
;re not lazy expressions anymore. They're just a transparent way to tur=
n an expression into a (lighter-weight) lambda.</div></div></blockquote><di=
v><br></div><div>Yes, so what? C++ is ABI agnostic, you repeat this often e=
nough. And now you want to specify language constructions to solve an imple=
mentation/ABI issue?</div></div></blockquote><div><br></div><div>No, I want=
to specify lazy expressions so that they're <i>expressions</i>, not fu=
nction calls. So that they work exactly as if you had copy-and-pasted the e=
xpression at the site of use.</div></div></blockquote><div><br></div><div>A=
ny particular reason to want them to behave exactly like that? Any pointer =
or examples of why this is required? =C2=A0</div><div><br></div><div>To thi=
s point I understood layzies are like this (correct me if I am wrong)</div>=
<div><span style=3D"text-align:left;color:rgb(34,34,34);text-transform:none=
;text-indent:0px;letter-spacing:normal;font-size:13px;font-style:normal;fon=
t-variant:normal;font-weight:400;text-decoration:none;word-spacing:0px;disp=
lay:inline!important;white-space:normal;float:none;background-color:transpa=
rent"><font face=3D"courier new,monospace">void f()</font></span></div><div=
><font face=3D"courier new,monospace">{</font></div><div><font face=3D"cour=
ier new,monospace">=C2=A0 call(string("hello"));</font></div><div=
><font face=3D"courier new,monospace">}</font></div><div><font face=3D"cour=
ier new,monospace"></font><font face=3D"courier new,monospace"></font><br><=
/div><div>becomes</div><div><br></div><div><font face=3D"courier new,monosp=
ace">void f()</font></div><div><font face=3D"courier new,monospace">{</font=
></div><div><font face=3D"courier new,monospace">=C2=A0{</font></div><div><=
font face=3D"courier new,monospace">=C2=A0 auto s =3D=C2=A0<span style=3D"t=
ext-align:left;color:rgb(34,34,34);text-transform:none;text-indent:0px;lett=
er-spacing:normal;font-size:13px;font-style:normal;font-variant:normal;font=
-weight:400;text-decoration:none;word-spacing:0px;display:inline!important;=
white-space:normal;float:none;background-color:transparent">string("he=
llo");</span></font></div><div><span style=3D"text-align:left;color:rg=
b(34,34,34);text-transform:none;text-indent:0px;letter-spacing:normal;font-=
size:13px;font-style:normal;font-variant:normal;font-weight:400;text-decora=
tion:none;word-spacing:0px;display:inline!important;white-space:normal;floa=
t:none;background-color:transparent"><font face=3D"courier new,monospace">=
=C2=A0 call(s);</font></span></div><div><span style=3D"text-align:left;colo=
r:rgb(34,34,34);text-transform:none;text-indent:0px;letter-spacing:normal;f=
ont-size:13px;font-style:normal;font-variant:normal;font-weight:400;text-de=
coration:none;word-spacing:0px;display:inline!important;white-space:normal;=
float:none;background-color:transparent"><font face=3D"courier new,monospac=
e">=C2=A0}</font></span></div><div><span style=3D"text-align:left;color:rgb=
(34,34,34);text-transform:none;text-indent:0px;letter-spacing:normal;font-s=
ize:13px;font-style:normal;font-variant:normal;font-weight:400;text-decorat=
ion:none;word-spacing:0px;display:inline!important;white-space:normal;float=
:none;background-color:transparent"><font face=3D"courier new,monospace">}<=
/font></span></div><div><span style=3D"text-align:left;color:rgb(34,34,34);=
text-transform:none;text-indent:0px;letter-spacing:normal;font-size:13px;fo=
nt-style:normal;font-variant:normal;font-weight:400;text-decoration:none;wo=
rd-spacing:0px;display:inline!important;white-space:normal;float:none;backg=
round-color:transparent"><font face=3D"arial,sans-serif"></font><font face=
=3D"courier new,monospace"></font><font face=3D"courier new,monospace"></fo=
nt><br></span></div><div><span style=3D"text-align:left;color:rgb(34,34,34)=
;text-transform:none;text-indent:0px;letter-spacing:normal;font-size:13px;f=
ont-style:normal;font-variant:normal;font-weight:400;text-decoration:none;w=
ord-spacing:0px;display:inline!important;white-space:normal;float:none;back=
ground-color:transparent"><font face=3D"arial,sans-serif"><i>However</i> th=
e=C2=A0<span style=3D"display:inline!important;float:none;background-color:=
transparent;color:rgb(34,34,34);font-family:courier new,monospace;font-size=
:13px;font-style:normal;font-variant:normal;font-weight:400;letter-spacing:=
normal;text-align:left;text-decoration:none;text-indent:0px;text-transform:=
none;white-space:normal;word-spacing:0px">auto s =3D=C2=A0</span><span styl=
e=3D"background-color:transparent;border-bottom-color:rgb(34,34,34);border-=
bottom-style:none;border-bottom-width:0px;border-left-color:rgb(34,34,34);b=
order-left-style:none;border-left-width:0px;border-right-color:rgb(34,34,34=
);border-right-style:none;border-right-width:0px;border-top-color:rgb(34,34=
,34);border-top-style:none;border-top-width:0px;color:rgb(34,34,34);display=
:inline;float:none;font-family:courier new,monospace;font-size:13px;font-st=
yle:normal;font-variant:normal;font-weight:400;letter-spacing:normal;margin=
-bottom:0px;margin-left:0px;margin-right:0px;margin-top:0px;padding-bottom:=
0px;padding-left:0px;padding-right:0px;padding-top:0px;text-align:left;text=
-decoration:none;text-indent:0px;text-transform:none;white-space:normal;wor=
d-spacing:0px"></span><span style=3D"background-color:transparent;border-bo=
ttom-color:rgb(34,34,34);border-bottom-style:none;border-bottom-width:0px;b=
order-left-color:rgb(34,34,34);border-left-style:none;border-left-width:0px=
;border-right-color:rgb(34,34,34);border-right-style:none;border-right-widt=
h:0px;border-top-color:rgb(34,34,34);border-top-style:none;border-top-width=
:0px;color:rgb(34,34,34);display:inline;float:none;font-family:courier new,=
monospace;font-size:13px;font-style:normal;font-variant:normal;font-weight:=
400;letter-spacing:normal;margin-bottom:0px;margin-left:0px;margin-right:0p=
x;margin-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;padd=
ing-top:0px;text-align:left;text-decoration:none;text-indent:0px;text-trans=
form:none;white-space:normal;word-spacing:0px">string("hello") <f=
ont face=3D"arial,sans-serif">is executed <i>not</i> <i>before</i> the func=
tion call, but <i>from within</i> the function call, going back to the orig=
inal context with all the locals visible and so on.</font></span></font></s=
pan> <br></div></div></blockquote><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><span style=3D"text-align:left;color:rgb(34,34,34);t=
ext-transform:none;text-indent:0px;letter-spacing:normal;font-size:13px;fon=
t-style:normal;font-variant:normal;font-weight:400;text-decoration:none;wor=
d-spacing:0px;display:inline!important;white-space:normal;float:none;backgr=
ound-color:transparent"><font face=3D"arial,sans-serif"><span style=3D"back=
ground-color:transparent;border-bottom-color:rgb(34,34,34);border-bottom-st=
yle:none;border-bottom-width:0px;border-left-color:rgb(34,34,34);border-lef=
t-style:none;border-left-width:0px;border-right-color:rgb(34,34,34);border-=
right-style:none;border-right-width:0px;border-top-color:rgb(34,34,34);bord=
er-top-style:none;border-top-width:0px;color:rgb(34,34,34);display:inline;f=
loat:none;font-family:courier new,monospace;font-size:13px;font-style:norma=
l;font-variant:normal;font-weight:400;letter-spacing:normal;margin-bottom:0=
px;margin-left:0px;margin-right:0px;margin-top:0px;padding-bottom:0px;paddi=
ng-left:0px;padding-right:0px;padding-top:0px;text-align:left;text-decorati=
on:none;text-indent:0px;text-transform:none;white-space:normal;word-spacing=
:0px"><font face=3D"arial,sans-serif"><br></font></span></font></span></div=
><div><span style=3D"text-align:left;color:rgb(34,34,34);text-transform:non=
e;text-indent:0px;letter-spacing:normal;font-size:13px;font-style:normal;fo=
nt-variant:normal;font-weight:400;text-decoration:none;word-spacing:0px;dis=
play:inline!important;white-space:normal;float:none;background-color:transp=
arent"><font face=3D"arial,sans-serif"><span style=3D"background-color:tran=
sparent;border-bottom-color:rgb(34,34,34);border-bottom-style:none;border-b=
ottom-width:0px;border-left-color:rgb(34,34,34);border-left-style:none;bord=
er-left-width:0px;border-right-color:rgb(34,34,34);border-right-style:none;=
border-right-width:0px;border-top-color:rgb(34,34,34);border-top-style:none=
;border-top-width:0px;color:rgb(34,34,34);display:inline;float:none;font-fa=
mily:courier new,monospace;font-size:13px;font-style:normal;font-variant:no=
rmal;font-weight:400;letter-spacing:normal;margin-bottom:0px;margin-left:0p=
x;margin-right:0px;margin-top:0px;padding-bottom:0px;padding-left:0px;paddi=
ng-right:0px;padding-top:0px;text-align:left;text-decoration:none;text-inde=
nt:0px;text-transform:none;white-space:normal;word-spacing:0px"><font face=
=3D"arial,sans-serif">That model seems to me pretty "natural" and=
easy to understand.</font></span></font></span></div></div></blockquote><d=
iv><br></div><div>A function in C++ is isolated from any non-global state o=
utside of its parameters. That's a basic aspect of how functions work.<=
/div><div><br></div><div>The model you're talking about breaks this. A =
parameter will start manipulating memory outside of that function's sco=
pe and outside of the scope of that function's parameters. It will crea=
te temporaries to objects outside of that function's scope. It will beg=
in the lifetime of objects whose lifetime ends well outside of its own scop=
e. That now makes it difficult to reason about the results of that expressi=
on.</div><div><br></div><div>For example, consider the case where one of th=
e sub-expressions of a captured expression throws, and the function that ev=
aluates the expression catches it, so that the exception doesn't get ba=
ck to the function that provided the expression. Well, what happens to the =
temporaries created by the captured expression <i>prior</i> to the throw?</=
div><div><br></div><div>In normal expressions (and in copy-and-paste lazy e=
valuation), the way this works is normal. Any temporaries created are destr=
oyed by stack unwinding. Those temporaries were created in the current scop=
e, so when the scope exits, those temporaries are destroyed.</div><div><br>=
</div><div>But with your way, temporaries are manifested <i>outside</i> of =
the scope they're created in. They are supposed to live beyond that sco=
pe. So if you catch the exception before the scope leaves... what happens t=
o them? When do they get destroyed? What is the right answer?</div><div><br=
></div><div>If those temporaries are not destroyed, then now you have a sit=
uation where some of the temporaries were successfully created and some wer=
e not. How does that work when you leave the capturing function? And if the=
y are destroyed... how does that make sense? You haven't unwound the st=
ack past their scope, so there's no reason for them to be destroyed.<br=
></div></div></blockquote><div><br></div><div>All those questions have been=
answered and solved by the example implementation I gave.</div><div>Execpt=
ions look natural.</div><div><br></div><div>The lazy evaluation scope is a =
bit different from other scopes in the sense that it is not nested with oth=
er scopes, it is in "parallel". But lifetime of temporaries withi=
n this scope follow classical rules.<br></div><div>=C2=A0</div><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"><div></div><div></div><di=
v><br></div><div>So I would say that copy-and-paste evaluation seems more &=
quot;natural" and "easy to understand".<br></div><br></div><=
/blockquote></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/79e284e2-ecd3-4b64-9a14-a8e303d5ad27%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/79e284e2-ecd3-4b64-9a14-a8e303d5ad27=
%40isocpp.org</a>.<br />
------=_Part_30193_1632524272.1527698834185--
------=_Part_30192_927003590.1527698834185--
.
Author: florian.csdt@gmail.com
Date: Wed, 30 May 2018 10:00:10 -0700 (PDT)
Raw View
------=_Part_45134_1508410851.1527699610852
Content-Type: multipart/alternative;
boundary="----=_Part_45135_154769154.1527699610853"
------=_Part_45135_154769154.1527699610853
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le mercredi 30 mai 2018 18:47:14 UTC+2, floria...@gmail.com a =C3=A9crit :
>
>
>
> Le mercredi 30 mai 2018 18:42:06 UTC+2, Nicol Bolas a =C3=A9crit :
>>
>> On Wednesday, May 30, 2018 at 12:04:45 PM UTC-4, mihailn...@gmail.com=20
>> wrote:
>>>
>>> On Wednesday, May 30, 2018 at 6:35:47 PM UTC+3, Nicol Bolas wrote:
>>>>
>>>> On Wednesday, May 30, 2018 at 10:46:39 AM UTC-4, floria...@gmail.com=
=20
>>>> wrote:
>>>>>
>>>>> =20
>>>>>
>>>>>>
>>>>>> I agree that that would be a better semantic, but it implies a=20
>>>>>>> different ABI to that proposed (in passing) in P0927; rather than a=
single=20
>>>>>>> code pointer code whose invocation evaluates the expression, we nee=
d two=20
>>>>>>> code pointers with the second destructing temporaries, or a single =
code=20
>>>>>>> pointer with signature T(void* caller_stack, enum class action {=20
>>>>>>> evaluate, destruct_temporaries}). The caller would still need to=20
>>>>>>> reserve stack space for any temporaries in the lazily evaluated exp=
ression,=20
>>>>>>> but would not need to maintain a flag indicating whether temporarie=
s had=20
>>>>>>> been constructed, as calling the code pointer to perform cleanup wo=
uld be=20
>>>>>>> the responsibility of the callee.
>>>>>>>
>>>>>>
>>>>>> ABI is essentially irrelevant, because the only way you can have laz=
y=20
>>>>>> expressions work *correctly* is if the function(s) that uses them=20
>>>>>> are inlined, relative to the function that provided the expression.
>>>>>>
>>>>>
>>>>> That's not true, there are many ways to implement this to have the=20
>>>>> correct behavior without inlining. Edward's solution is one.=20
>>>>>
>>>> And as I said before, I don't what you call "the *correct* behavior"=
=20
>>>>> is what we want.
>>>>> =20
>>>>>
>>>>>> The only cross-ABI way to make lazy expressions work is to make them=
=20
>>>>>> an actual function, with the expected C++ semantics. At which point.=
...=20
>>>>>> they're not lazy expressions anymore. They're just a transparent way=
to=20
>>>>>> turn an expression into a (lighter-weight) lambda.
>>>>>>
>>>>>
>>>>> Yes, so what? C++ is ABI agnostic, you repeat this often enough. And=
=20
>>>>> now you want to specify language constructions to solve an=20
>>>>> implementation/ABI issue?
>>>>>
>>>>
>>>> No, I want to specify lazy expressions so that they're *expressions*,=
=20
>>>> not function calls. So that they work exactly as if you had copy-and-p=
asted=20
>>>> the expression at the site of use.
>>>>
>>>
>>> Any particular reason to want them to behave exactly like that? Any=20
>>> pointer or examples of why this is required? =20
>>>
>>> To this point I understood layzies are like this (correct me if I am=20
>>> wrong)
>>> void f()
>>> {
>>> call(string("hello"));
>>> }
>>>
>>> becomes
>>>
>>> void f()
>>> {
>>> {
>>> auto s =3D string("hello");
>>> call(s);
>>> }
>>> }
>>>
>>> *However* the auto s =3D string("hello") is executed *not* *before* the=
=20
>>> function call, but *from within* the function call, going back to the=
=20
>>> original context with all the locals visible and so on.=20
>>>
>>
>>> That model seems to me pretty "natural" and easy to understand.
>>>
>>
>> A function in C++ is isolated from any non-global state outside of its=
=20
>> parameters. That's a basic aspect of how functions work.
>>
>> The model you're talking about breaks this. A parameter will start=20
>> manipulating memory outside of that function's scope and outside of the=
=20
>> scope of that function's parameters. It will create temporaries to objec=
ts=20
>> outside of that function's scope. It will begin the lifetime of objects=
=20
>> whose lifetime ends well outside of its own scope. That now makes it=20
>> difficult to reason about the results of that expression.
>>
>> For example, consider the case where one of the sub-expressions of a=20
>> captured expression throws, and the function that evaluates the expressi=
on=20
>> catches it, so that the exception doesn't get back to the function that=
=20
>> provided the expression. Well, what happens to the temporaries created b=
y=20
>> the captured expression *prior* to the throw?
>>
>> In normal expressions (and in copy-and-paste lazy evaluation), the way=
=20
>> this works is normal. Any temporaries created are destroyed by stack=20
>> unwinding. Those temporaries were created in the current scope, so when =
the=20
>> scope exits, those temporaries are destroyed.
>>
>> But with your way, temporaries are manifested *outside* of the scope=20
>> they're created in. They are supposed to live beyond that scope. So if y=
ou=20
>> catch the exception before the scope leaves... what happens to them? Whe=
n=20
>> do they get destroyed? What is the right answer?
>>
>> If those temporaries are not destroyed, then now you have a situation=20
>> where some of the temporaries were successfully created and some were no=
t.=20
>> How does that work when you leave the capturing function? And if they ar=
e=20
>> destroyed... how does that make sense? You haven't unwound the stack pas=
t=20
>> their scope, so there's no reason for them to be destroyed.
>>
>
> All those questions have been answered and solved by the example=20
> implementation I gave.
> Execptions look natural.
>
> The lazy evaluation scope is a bit different from other scopes in the=20
> sense that it is not nested with other scopes, it is in "parallel". But=
=20
> lifetime of temporaries within this scope follow classical rules.
> =20
>
If you want more complete answer, here I go:
If an exception is thrown by the lazy expression, the lazy expression code=
=20
destroys the successfully created objects, and lets the flag as it is (so=
=20
the caller will not try to destroy any of them).
After that, the exception is forwarded to the callee with classical means=
=20
and the callee can catch the exception if needed.
And what if the lazy evaluation doesn't throw, but the callee does:
The caller will destroy the lazy scope as usual... (this is something I=20
forgot in my implementation, but trivially fixable with a std::scope_exit=
=20
for instance)
Also, you seem to mix scope and storage: the scope of the lazy evaluation=
=20
is completely and nicely defined: it is the same scope as if it were not=20
lazy.
The storage used depends on the ABI (how the stack frames are handled), but=
=20
that's completely implementation defined.
--=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/33d0ed50-03d1-4c84-bb7c-d69145c926fd%40isocpp.or=
g.
------=_Part_45135_154769154.1527699610853
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le mercredi 30 mai 2018 18:47:14 UTC+2, floria...@=
gmail.com a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><=
div dir=3D"ltr"><br><br>Le mercredi 30 mai 2018 18:42:06 UTC+2, Nicol Bolas=
a =C3=A9crit=C2=A0:<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=
">On Wednesday, May 30, 2018 at 12:04:45 PM UTC-4, <a>mihailn...@gmail.com<=
/a> 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">On Wedne=
sday, May 30, 2018 at 6:35:47 PM UTC+3, Nicol Bolas wrote:<blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr">On Wednesday, May 30, 2018 at 10:46=
:39 AM UTC-4, <a>floria...@gmail.com</a> wrote:<blockquote class=3D"gmail_q=
uote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddin=
g-left:1ex"><div dir=3D"ltr"><div>=C2=A0</div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding=
-left:1ex"><div dir=3D"ltr"><div><br></div><blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr"><div></div><div>I agree that that would be a bette=
r semantic, but it implies a different ABI to that proposed (in passing) in=
P0927; rather than a single code pointer code whose invocation evaluates t=
he expression, we need two code pointers with the second destructing tempor=
aries, or a single code pointer with signature <font face=3D"monospace, mon=
ospace">T(void* caller_stack, enum class action { evaluate, destruct_tempor=
aries})</font>. The caller would still need to reserve stack space for any =
temporaries in the lazily evaluated expression, but would not need to maint=
ain a flag indicating whether temporaries had been constructed, as calling =
the code pointer to perform cleanup would be the responsibility of the call=
ee.</div></div></blockquote><div><br></div><div></div><div>ABI is essential=
ly irrelevant, because the only way you can have lazy expressions work <i>c=
orrectly</i> is if the function(s) that uses them are inlined, relative to =
the function that provided the expression.</div></div></blockquote><div><br=
></div><div>That's not true, there are many ways to implement this to h=
ave the correct behavior without inlining. Edward's solution is one. <b=
r></div></div></blockquote><blockquote class=3D"gmail_quote" style=3D"margi=
n:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div>And as I said before, I don't what you call "the <i>=
correct</i> behavior" is what we want.<br></div><div>=C2=A0</div><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div></div><div>The onl=
y cross-ABI way to make lazy expressions work is to make them an actual fun=
ction, with the expected C++ semantics. At which point... they're not l=
azy expressions anymore. They're just a transparent way to turn an expr=
ession into a (lighter-weight) lambda.</div></div></blockquote><div><br></d=
iv><div>Yes, so what? C++ is ABI agnostic, you repeat this often enough. An=
d now you want to specify language constructions to solve an implementation=
/ABI issue?</div></div></blockquote><div><br></div><div>No, I want to speci=
fy lazy expressions so that they're <i>expressions</i>, not function ca=
lls. So that they work exactly as if you had copy-and-pasted the expression=
at the site of use.</div></div></blockquote><div><br></div><div>Any partic=
ular reason to want them to behave exactly like that? Any pointer or exampl=
es of why this is required? =C2=A0</div><div><br></div><div>To this point I=
understood layzies are like this (correct me if I am wrong)</div><div><spa=
n style=3D"text-align:left;color:rgb(34,34,34);text-transform:none;text-ind=
ent:0px;letter-spacing:normal;font-size:13px;font-style:normal;font-variant=
:normal;font-weight:400;text-decoration:none;word-spacing:0px;display:inlin=
e!important;white-space:normal;float:none;background-color:transparent"><fo=
nt face=3D"courier new,monospace">void f()</font></span></div><div><font fa=
ce=3D"courier new,monospace">{</font></div><div><font face=3D"courier new,m=
onospace">=C2=A0 call(string("hello"));</font></div><div><font fa=
ce=3D"courier new,monospace">}</font></div><div><font face=3D"courier new,m=
onospace"></font><font face=3D"courier new,monospace"></font><br></div><div=
>becomes</div><div><br></div><div><font face=3D"courier new,monospace">void=
f()</font></div><div><font face=3D"courier new,monospace">{</font></div><d=
iv><font face=3D"courier new,monospace">=C2=A0{</font></div><div><font face=
=3D"courier new,monospace">=C2=A0 auto s =3D=C2=A0<span style=3D"text-align=
:left;color:rgb(34,34,34);text-transform:none;text-indent:0px;letter-spacin=
g:normal;font-size:13px;font-style:normal;font-variant:normal;font-weight:4=
00;text-decoration:none;word-spacing:0px;display:inline!important;white-spa=
ce:normal;float:none;background-color:transparent">string("hello"=
);</span></font></div><div><span style=3D"text-align:left;color:rgb(34,34,3=
4);text-transform:none;text-indent:0px;letter-spacing:normal;font-size:13px=
;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none=
;word-spacing:0px;display:inline!important;white-space:normal;float:none;ba=
ckground-color:transparent"><font face=3D"courier new,monospace">=C2=A0 cal=
l(s);</font></span></div><div><span style=3D"text-align:left;color:rgb(34,3=
4,34);text-transform:none;text-indent:0px;letter-spacing:normal;font-size:1=
3px;font-style:normal;font-variant:normal;font-weight:400;text-decoration:n=
one;word-spacing:0px;display:inline!important;white-space:normal;float:none=
;background-color:transparent"><font face=3D"courier new,monospace">=C2=A0}=
</font></span></div><div><span style=3D"text-align:left;color:rgb(34,34,34)=
;text-transform:none;text-indent:0px;letter-spacing:normal;font-size:13px;f=
ont-style:normal;font-variant:normal;font-weight:400;text-decoration:none;w=
ord-spacing:0px;display:inline!important;white-space:normal;float:none;back=
ground-color:transparent"><font face=3D"courier new,monospace">}</font></sp=
an></div><div><span style=3D"text-align:left;color:rgb(34,34,34);text-trans=
form:none;text-indent:0px;letter-spacing:normal;font-size:13px;font-style:n=
ormal;font-variant:normal;font-weight:400;text-decoration:none;word-spacing=
:0px;display:inline!important;white-space:normal;float:none;background-colo=
r:transparent"><font face=3D"arial,sans-serif"></font><font face=3D"courier=
new,monospace"></font><font face=3D"courier new,monospace"></font><br></sp=
an></div><div><span style=3D"text-align:left;color:rgb(34,34,34);text-trans=
form:none;text-indent:0px;letter-spacing:normal;font-size:13px;font-style:n=
ormal;font-variant:normal;font-weight:400;text-decoration:none;word-spacing=
:0px;display:inline!important;white-space:normal;float:none;background-colo=
r:transparent"><font face=3D"arial,sans-serif"><i>However</i> the=C2=A0<spa=
n style=3D"display:inline!important;float:none;background-color:transparent=
;color:rgb(34,34,34);font-family:courier new,monospace;font-size:13px;font-=
style:normal;font-variant:normal;font-weight:400;letter-spacing:normal;text=
-align:left;text-decoration:none;text-indent:0px;text-transform:none;white-=
space:normal;word-spacing:0px">auto s =3D=C2=A0</span><span style=3D"backgr=
ound-color:transparent;border-bottom-color:rgb(34,34,34);border-bottom-styl=
e:none;border-bottom-width:0px;border-left-color:rgb(34,34,34);border-left-=
style:none;border-left-width:0px;border-right-color:rgb(34,34,34);border-ri=
ght-style:none;border-right-width:0px;border-top-color:rgb(34,34,34);border=
-top-style:none;border-top-width:0px;color:rgb(34,34,34);display:inline;flo=
at:none;font-family:courier new,monospace;font-size:13px;font-style:normal;=
font-variant:normal;font-weight:400;letter-spacing:normal;margin-bottom:0px=
;margin-left:0px;margin-right:0px;margin-top:0px;padding-bottom:0px;padding=
-left:0px;padding-right:0px;padding-top:0px;text-align:left;text-decoration=
:none;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0=
px"></span><span style=3D"background-color:transparent;border-bottom-color:=
rgb(34,34,34);border-bottom-style:none;border-bottom-width:0px;border-left-=
color:rgb(34,34,34);border-left-style:none;border-left-width:0px;border-rig=
ht-color:rgb(34,34,34);border-right-style:none;border-right-width:0px;borde=
r-top-color:rgb(34,34,34);border-top-style:none;border-top-width:0px;color:=
rgb(34,34,34);display:inline;float:none;font-family:courier new,monospace;f=
ont-size:13px;font-style:normal;font-variant:normal;font-weight:400;letter-=
spacing:normal;margin-bottom:0px;margin-left:0px;margin-right:0px;margin-to=
p:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:0px=
;text-align:left;text-decoration:none;text-indent:0px;text-transform:none;w=
hite-space:normal;word-spacing:0px">string("hello") <font face=3D=
"arial,sans-serif">is executed <i>not</i> <i>before</i> the function call, =
but <i>from within</i> the function call, going back to the original contex=
t with all the locals visible and so on.</font></span></font></span> <br></=
div></div></blockquote><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><span style=3D"text-align:left;color:rgb(34,34,34);text-transform=
:none;text-indent:0px;letter-spacing:normal;font-size:13px;font-style:norma=
l;font-variant:normal;font-weight:400;text-decoration:none;word-spacing:0px=
;display:inline!important;white-space:normal;float:none;background-color:tr=
ansparent"><font face=3D"arial,sans-serif"><span style=3D"background-color:=
transparent;border-bottom-color:rgb(34,34,34);border-bottom-style:none;bord=
er-bottom-width:0px;border-left-color:rgb(34,34,34);border-left-style:none;=
border-left-width:0px;border-right-color:rgb(34,34,34);border-right-style:n=
one;border-right-width:0px;border-top-color:rgb(34,34,34);border-top-style:=
none;border-top-width:0px;color:rgb(34,34,34);display:inline;float:none;fon=
t-family:courier new,monospace;font-size:13px;font-style:normal;font-varian=
t:normal;font-weight:400;letter-spacing:normal;margin-bottom:0px;margin-lef=
t:0px;margin-right:0px;margin-top:0px;padding-bottom:0px;padding-left:0px;p=
adding-right:0px;padding-top:0px;text-align:left;text-decoration:none;text-=
indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><font f=
ace=3D"arial,sans-serif"><br></font></span></font></span></div><div><span s=
tyle=3D"text-align:left;color:rgb(34,34,34);text-transform:none;text-indent=
:0px;letter-spacing:normal;font-size:13px;font-style:normal;font-variant:no=
rmal;font-weight:400;text-decoration:none;word-spacing:0px;display:inline!i=
mportant;white-space:normal;float:none;background-color:transparent"><font =
face=3D"arial,sans-serif"><span style=3D"background-color:transparent;borde=
r-bottom-color:rgb(34,34,34);border-bottom-style:none;border-bottom-width:0=
px;border-left-color:rgb(34,34,34);border-left-style:none;border-left-width=
:0px;border-right-color:rgb(34,34,34);border-right-style:none;border-right-=
width:0px;border-top-color:rgb(34,34,34);border-top-style:none;border-top-w=
idth:0px;color:rgb(34,34,34);display:inline;float:none;font-family:courier =
new,monospace;font-size:13px;font-style:normal;font-variant:normal;font-wei=
ght:400;letter-spacing:normal;margin-bottom:0px;margin-left:0px;margin-righ=
t:0px;margin-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;=
padding-top:0px;text-align:left;text-decoration:none;text-indent:0px;text-t=
ransform:none;white-space:normal;word-spacing:0px"><font face=3D"arial,sans=
-serif">That model seems to me pretty "natural" and easy to under=
stand.</font></span></font></span></div></div></blockquote><div><br></div><=
div>A function in C++ is isolated from any non-global state outside of its =
parameters. That's a basic aspect of how functions work.</div><div><br>=
</div><div>The model you're talking about breaks this. A parameter will=
start manipulating memory outside of that function's scope and outside=
of the scope of that function's parameters. It will create temporaries=
to objects outside of that function's scope. It will begin the lifetim=
e of objects whose lifetime ends well outside of its own scope. That now ma=
kes it difficult to reason about the results of that expression.</div><div>=
<br></div><div>For example, consider the case where one of the sub-expressi=
ons of a captured expression throws, and the function that evaluates the ex=
pression catches it, so that the exception doesn't get back to the func=
tion that provided the expression. Well, what happens to the temporaries cr=
eated by the captured expression <i>prior</i> to the throw?</div><div><br><=
/div><div>In normal expressions (and in copy-and-paste lazy evaluation), th=
e way this works is normal. Any temporaries created are destroyed by stack =
unwinding. Those temporaries were created in the current scope, so when the=
scope exits, those temporaries are destroyed.</div><div><br></div><div>But=
with your way, temporaries are manifested <i>outside</i> of the scope they=
're created in. They are supposed to live beyond that scope. So if you =
catch the exception before the scope leaves... what happens to them? When d=
o they get destroyed? What is the right answer?</div><div><br></div><div>If=
those temporaries are not destroyed, then now you have a situation where s=
ome of the temporaries were successfully created and some were not. How doe=
s that work when you leave the capturing function? And if they are destroye=
d... how does that make sense? You haven't unwound the stack past their=
scope, so there's no reason for them to be destroyed.<br></div></div><=
/blockquote><div><br></div><div>All those questions have been answered and =
solved by the example implementation I gave.</div><div>Execptions look natu=
ral.</div><div><br></div><div>The lazy evaluation scope is a bit different =
from other scopes in the sense that it is not nested with other scopes, it =
is in "parallel". But lifetime of temporaries within this scope f=
ollow classical rules.<br></div><div>=C2=A0</div></div></blockquote><div>If=
you want more complete answer, here I go:</div><div><br></div><div>If an e=
xception is thrown by the lazy expression, the lazy expression code destroy=
s the successfully created objects, and lets the flag as it is (so the call=
er will not try to destroy any of them).</div><div>After that, the exceptio=
n is forwarded to the callee with classical means and the callee can catch =
the exception if needed.</div><div><br></div><div>And what if the lazy eval=
uation doesn't throw, but the callee does:</div><div>The caller will de=
stroy the lazy scope as usual... (this is something I forgot in my implemen=
tation, but trivially fixable with a std::scope_exit for instance)<br></div=
><div><br></div><div><br></div><div>Also, you seem to mix scope and storage=
: the scope of the lazy evaluation is completely and nicely defined: it is =
the same scope as if it were not lazy.<br></div><div>The storage used depen=
ds on the ABI (how the stack frames are handled), but that's completely=
implementation defined.<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/33d0ed50-03d1-4c84-bb7c-d69145c926fd%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/33d0ed50-03d1-4c84-bb7c-d69145c926fd=
%40isocpp.org</a>.<br />
------=_Part_45135_154769154.1527699610853--
------=_Part_45134_1508410851.1527699610852--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 30 May 2018 10:39:38 -0700 (PDT)
Raw View
------=_Part_45384_473074634.1527701978672
Content-Type: multipart/alternative;
boundary="----=_Part_45385_1809606358.1527701978673"
------=_Part_45385_1809606358.1527701978673
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Wednesday, May 30, 2018 at 1:00:10 PM UTC-4, floria...@gmail.com wrote:
>
> Le mercredi 30 mai 2018 18:47:14 UTC+2, floria...@gmail.com a =C3=A9crit =
:
>>
>>
>>
>> Le mercredi 30 mai 2018 18:42:06 UTC+2, Nicol Bolas a =C3=A9crit :
>>>
>>> A function in C++ is isolated from any non-global state outside of its=
=20
>>> parameters. That's a basic aspect of how functions work.
>>>
>>> The model you're talking about breaks this. A parameter will start=20
>>> manipulating memory outside of that function's scope and outside of the=
=20
>>> scope of that function's parameters. It will create temporaries to obje=
cts=20
>>> outside of that function's scope. It will begin the lifetime of objects=
=20
>>> whose lifetime ends well outside of its own scope. That now makes it=20
>>> difficult to reason about the results of that expression.
>>>
>>> For example, consider the case where one of the sub-expressions of a=20
>>> captured expression throws, and the function that evaluates the express=
ion=20
>>> catches it, so that the exception doesn't get back to the function that=
=20
>>> provided the expression. Well, what happens to the temporaries created =
by=20
>>> the captured expression *prior* to the throw?
>>>
>>> In normal expressions (and in copy-and-paste lazy evaluation), the way=
=20
>>> this works is normal. Any temporaries created are destroyed by stack=20
>>> unwinding. Those temporaries were created in the current scope, so when=
the=20
>>> scope exits, those temporaries are destroyed.
>>>
>>> But with your way, temporaries are manifested *outside* of the scope=20
>>> they're created in. They are supposed to live beyond that scope. So if =
you=20
>>> catch the exception before the scope leaves... what happens to them? Wh=
en=20
>>> do they get destroyed? What is the right answer?
>>>
>>> If those temporaries are not destroyed, then now you have a situation=
=20
>>> where some of the temporaries were successfully created and some were n=
ot.=20
>>> How does that work when you leave the capturing function? And if they a=
re=20
>>> destroyed... how does that make sense? You haven't unwound the stack pa=
st=20
>>> their scope, so there's no reason for them to be destroyed.
>>>
>>
>> All those questions have been answered and solved by the example=20
>> implementation I gave.
>> Execptions look natural.
>>
>> The lazy evaluation scope is a bit different from other scopes in the=20
>> sense that it is not nested with other scopes, it is in "parallel". But=
=20
>> lifetime of temporaries within this scope follow classical rules.
>> =20
>>
> If you want more complete answer, here I go:
>
> If an exception is thrown by the lazy expression, the lazy expression cod=
e=20
> destroys the successfully created objects, and lets the flag as it is (so=
=20
> the caller will not try to destroy any of them).
> After that, the exception is forwarded to the callee with classical means=
=20
> and the callee can catch the exception if needed.
>
I don't think this answered the question I asked, so allow me to provide=20
some code:
void foo([]->std::string str)
{
try { auto str2 =3D str(); }
catch(...)
{
}
//bottom of code
}
foo(std::string("foo") + func_that_throws() + std::string("bar"));
OK, the captured expression contains several temporaries.
Let's say that the evaluation order for + for this implementation does=20
things purely left-to-right. So it creates a temporary `string("foo")`. It=
=20
then gets a temporary `string` from `func_that_throws()` and does=20
`operator+` on them, resulting in a prvalue. That prvalue will then=20
manifest a temporary to be added to the temporary `string("bar")`.
Now of course, `func_that_throws` is so named because it throws. So my=20
question is this: given the above evaluation order, which temporaries are=
=20
still alive when you reach that `catch` statement?
The only correct answer I can see is "none of them". And if that's the=20
case, why is it OK for those temporaries to be destroyed if you reach=20
"bottom of code" through the `catch` statement and *not* through=20
non-exception execution?
And if some of those temporaries are alive and some are not... how does=20
that even work? Is there a boolean for each temporary in the captured=20
expression to say if it's alive?
And what if the lazy evaluation doesn't throw, but the callee does:
> The caller will destroy the lazy scope as usual... (this is something I=
=20
> forgot in my implementation, but trivially fixable with a std::scope_exit=
=20
> for instance)
>
>
> Also, you seem to mix scope and storage: the scope of the lazy evaluation=
=20
> is completely and nicely defined: it is the same scope as if it were not=
=20
> lazy.
>
But it's not the same scope. Scope for automatic storage duration objects=
=20
start when they are *constructed*. That happens when the expression is=20
evaluated. And when the block that creates an automatic storage duration=20
object ends, that object will be destroyed (temporaries may be destroyed=20
earlier, but they *never* outlive the block that created them).
Your scoping is breaking those rules. My version doesn't need to.
The storage used depends on the ABI (how the stack frames are handled), but=
=20
> that's completely implementation defined.
>
--=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/3674cb70-8746-42f0-9c56-f05a0ee34ac7%40isocpp.or=
g.
------=_Part_45385_1809606358.1527701978673
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, May 30, 2018 at 1:00:10 PM UTC-4, floria...@=
gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt=
r">Le mercredi 30 mai 2018 18:47:14 UTC+2, <a>floria...@gmail.com</a> a =C3=
=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-le=
ft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br>=
<br>Le mercredi 30 mai 2018 18:42:06 UTC+2, Nicol Bolas a =C3=A9crit=C2=A0:=
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div></div><div>A =
function in C++ is isolated from any non-global state outside of its parame=
ters. That's a basic aspect of how functions work.</div><div><br></div>=
<div>The model you're talking about breaks this. A parameter will start=
manipulating memory outside of that function's scope and outside of th=
e scope of that function's parameters. It will create temporaries to ob=
jects outside of that function's scope. It will begin the lifetime of o=
bjects whose lifetime ends well outside of its own scope. That now makes it=
difficult to reason about the results of that expression.</div><div><br></=
div><div>For example, consider the case where one of the sub-expressions of=
a captured expression throws, and the function that evaluates the expressi=
on catches it, so that the exception doesn't get back to the function t=
hat provided the expression. Well, what happens to the temporaries created =
by the captured expression <i>prior</i> to the throw?</div><div><br></div><=
div>In normal expressions (and in copy-and-paste lazy evaluation), the way =
this works is normal. Any temporaries created are destroyed by stack unwind=
ing. Those temporaries were created in the current scope, so when the scope=
exits, those temporaries are destroyed.</div><div><br></div><div>But with =
your way, temporaries are manifested <i>outside</i> of the scope they'r=
e created in. They are supposed to live beyond that scope. So if you catch =
the exception before the scope leaves... what happens to them? When do they=
get destroyed? What is the right answer?</div><div><br></div><div>If those=
temporaries are not destroyed, then now you have a situation where some of=
the temporaries were successfully created and some were not. How does that=
work when you leave the capturing function? And if they are destroyed... h=
ow does that make sense? You haven't unwound the stack past their scope=
, so there's no reason for them to be destroyed.<br></div></div></block=
quote><div><br></div><div>All those questions have been answered and solved=
by the example implementation I gave.</div><div>Execptions look natural.</=
div><div><br></div><div>The lazy evaluation scope is a bit different from o=
ther scopes in the sense that it is not nested with other scopes, it is in =
"parallel". But lifetime of temporaries within this scope follow =
classical rules.<br></div><div>=C2=A0</div></div></blockquote><div>If you w=
ant more complete answer, here I go:</div><div><br></div><div>If an excepti=
on is thrown by the lazy expression, the lazy expression code destroys the =
successfully created objects, and lets the flag as it is (so the caller wil=
l not try to destroy any of them).</div><div>After that, the exception is f=
orwarded to the callee with classical means and the callee can catch the ex=
ception if needed.</div></div></blockquote><div><br></div><div>I don't =
think this answered the question I asked, so allow me to provide some code:=
</div><div><br></div><div style=3D"background-color: rgb(250, 250, 250); bo=
rder-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; ove=
rflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettyprint">=
<div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-=
by-prettify">void</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> foo</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>([]-></span><span style=3D"color: #000;" class=3D"styled-by-prettify">s=
td</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">string</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> str</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></span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">try</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"=
> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> str2 </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> str</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;" c=
lass=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">catch</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">(...)</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=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 </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 </span><span style=3D"color: #800;" class=3D"styled-by-prettify">//b=
ottom of code</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><br>foo<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">std</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">string</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #080;" cl=
ass=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"style=
d-by-prettify">+</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> func_that_throws</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">()</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">+</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">string</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #=
080;" class=3D"styled-by-prettify">"bar"</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">));</span></div></code></div><div><=
br></div><div>OK, the captured expression contains several temporaries.</di=
v><div><br></div><div>Let's say that the evaluation order for + for thi=
s implementation does things purely left-to-right. So it creates a temporar=
y `string("foo")`. It then gets a temporary `string` from `func_t=
hat_throws()` and does `operator+` on them, resulting in a prvalue. That pr=
value will then manifest a temporary to be added to the temporary `string(&=
quot;bar")`.</div><div><br></div><div>Now of course, `func_that_throws=
` is so named because it throws. So my question is this: given the above ev=
aluation order, which temporaries are still alive when you reach that `catc=
h` statement?<br></div><div><br></div><div>The only correct answer I can se=
e is "none of them". And if that's the case, why is it OK for=
those temporaries to be destroyed if you reach "bottom of code" =
through the `catch` statement and <i>not</i> through non-exception executio=
n?<br></div><div><br></div><div>And if some of those temporaries are alive =
and some are not... how does that even work? Is there a boolean for each te=
mporary in the captured expression to say if it's alive?<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"><di=
v></div><div>And what if the lazy evaluation doesn't throw, but the cal=
lee does:</div><div>The caller will destroy the lazy scope as usual... (thi=
s is something I forgot in my implementation, but trivially fixable with a =
std::scope_exit for instance)<br></div><div><br></div><div><br></div><div>A=
lso, you seem to mix scope and storage: the scope of the lazy evaluation is=
completely and nicely defined: it is the same scope as if it were not lazy=
..<br></div></div></blockquote><div><br></div><div>But it's not the same=
scope. Scope for automatic storage duration objects start when they are <i=
>constructed</i>. That happens when the expression is evaluated. And when t=
he block that creates an automatic storage duration object ends, that objec=
t will be destroyed (temporaries may be destroyed earlier, but they <i>neve=
r</i> outlive the block that created them).</div><div><br></div><div>Your s=
coping is breaking those rules. My version doesn't need to.</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=
></div><div>The storage used depends on the ABI (how the stack frames are h=
andled), but that's completely implementation defined.<br></div></div><=
/blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" 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/3674cb70-8746-42f0-9c56-f05a0ee34ac7%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/3674cb70-8746-42f0-9c56-f05a0ee34ac7=
%40isocpp.org</a>.<br />
------=_Part_45385_1809606358.1527701978673--
------=_Part_45384_473074634.1527701978672--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 30 May 2018 19:00:54 +0100
Raw View
--0000000000004ea095056d7022b7
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Wed, 30 May 2018, 18:00 , <florian.csdt@gmail.com> wrote:
>
>
> Le mercredi 30 mai 2018 18:47:14 UTC+2, floria...@gmail.com a =C3=A9crit =
:
>>
>>
>>
>> Le mercredi 30 mai 2018 18:42:06 UTC+2, Nicol Bolas a =C3=A9crit :
>>>
>>> On Wednesday, May 30, 2018 at 12:04:45 PM UTC-4, mihailn...@gmail.com
>>> wrote:
>>>>
>>>> On Wednesday, May 30, 2018 at 6:35:47 PM UTC+3, Nicol Bolas wrote:
>>>>>
>>>>> On Wednesday, May 30, 2018 at 10:46:39 AM UTC-4, floria...@gmail.com
>>>>> wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>>>
>>>>>>> I agree that that would be a better semantic, but it implies a
>>>>>>>> different ABI to that proposed (in passing) in P0927; rather than =
a single
>>>>>>>> code pointer code whose invocation evaluates the expression, we ne=
ed two
>>>>>>>> code pointers with the second destructing temporaries, or a single=
code
>>>>>>>> pointer with signature T(void* caller_stack, enum class action {
>>>>>>>> evaluate, destruct_temporaries}). The caller would still need to
>>>>>>>> reserve stack space for any temporaries in the lazily evaluated ex=
pression,
>>>>>>>> but would not need to maintain a flag indicating whether temporari=
es had
>>>>>>>> been constructed, as calling the code pointer to perform cleanup w=
ould be
>>>>>>>> the responsibility of the callee.
>>>>>>>>
>>>>>>>
>>>>>>> ABI is essentially irrelevant, because the only way you can have
>>>>>>> lazy expressions work *correctly* is if the function(s) that uses
>>>>>>> them are inlined, relative to the function that provided the expres=
sion.
>>>>>>>
>>>>>>
>>>>>> That's not true, there are many ways to implement this to have the
>>>>>> correct behavior without inlining. Edward's solution is one.
>>>>>>
>>>>> And as I said before, I don't what you call "the *correct* behavior"
>>>>>> is what we want.
>>>>>>
>>>>>>
>>>>>>> The only cross-ABI way to make lazy expressions work is to make the=
m
>>>>>>> an actual function, with the expected C++ semantics. At which point=
....
>>>>>>> they're not lazy expressions anymore. They're just a transparent wa=
y to
>>>>>>> turn an expression into a (lighter-weight) lambda.
>>>>>>>
>>>>>>
>>>>>> Yes, so what? C++ is ABI agnostic, you repeat this often enough. And
>>>>>> now you want to specify language constructions to solve an
>>>>>> implementation/ABI issue?
>>>>>>
>>>>>
>>>>> No, I want to specify lazy expressions so that they're *expressions*,
>>>>> not function calls. So that they work exactly as if you had copy-and-=
pasted
>>>>> the expression at the site of use.
>>>>>
>>>>
>>>> Any particular reason to want them to behave exactly like that? Any
>>>> pointer or examples of why this is required?
>>>>
>>>> To this point I understood layzies are like this (correct me if I am
>>>> wrong)
>>>> void f()
>>>> {
>>>> call(string("hello"));
>>>> }
>>>>
>>>> becomes
>>>>
>>>> void f()
>>>> {
>>>> {
>>>> auto s =3D string("hello");
>>>> call(s);
>>>> }
>>>> }
>>>>
>>>> *However* the auto s =3D string("hello") is executed *not* *before* th=
e
>>>> function call, but *from within* the function call, going back to the
>>>> original context with all the locals visible and so on.
>>>>
>>>
>>>> That model seems to me pretty "natural" and easy to understand.
>>>>
>>>
>>> A function in C++ is isolated from any non-global state outside of its
>>> parameters. That's a basic aspect of how functions work.
>>>
>>> The model you're talking about breaks this. A parameter will start
>>> manipulating memory outside of that function's scope and outside of the
>>> scope of that function's parameters. It will create temporaries to obje=
cts
>>> outside of that function's scope. It will begin the lifetime of objects
>>> whose lifetime ends well outside of its own scope. That now makes it
>>> difficult to reason about the results of that expression.
>>>
>>> For example, consider the case where one of the sub-expressions of a
>>> captured expression throws, and the function that evaluates the express=
ion
>>> catches it, so that the exception doesn't get back to the function that
>>> provided the expression. Well, what happens to the temporaries created =
by
>>> the captured expression *prior* to the throw?
>>>
>>> In normal expressions (and in copy-and-paste lazy evaluation), the way
>>> this works is normal. Any temporaries created are destroyed by stack
>>> unwinding. Those temporaries were created in the current scope, so when=
the
>>> scope exits, those temporaries are destroyed.
>>>
>>> But with your way, temporaries are manifested *outside* of the scope
>>> they're created in. They are supposed to live beyond that scope. So if =
you
>>> catch the exception before the scope leaves... what happens to them? Wh=
en
>>> do they get destroyed? What is the right answer?
>>>
>>> If those temporaries are not destroyed, then now you have a situation
>>> where some of the temporaries were successfully created and some were n=
ot.
>>> How does that work when you leave the capturing function? And if they a=
re
>>> destroyed... how does that make sense? You haven't unwound the stack pa=
st
>>> their scope, so there's no reason for them to be destroyed.
>>>
>>
>> All those questions have been answered and solved by the example
>> implementation I gave.
>> Execptions look natural.
>>
>> The lazy evaluation scope is a bit different from other scopes in the
>> sense that it is not nested with other scopes, it is in "parallel". But
>> lifetime of temporaries within this scope follow classical rules.
>>
>>
> If you want more complete answer, here I go:
>
> If an exception is thrown by the lazy expression, the lazy expression cod=
e
> destroys the successfully created objects, and lets the flag as it is (so
> the caller will not try to destroy any of them).
> After that, the exception is forwarded to the callee with classical means
> and the callee can catch the exception if needed.
>
> And what if the lazy evaluation doesn't throw, but the callee does:
> The caller will destroy the lazy scope as usual... (this is something I
> forgot in my implementation, but trivially fixable with a std::scope_exit
> for instance)
>
Similarly, in the scheme I describe, the EH routine for the lazy expression
where the exception is thrown is invoked first; it cleans up its own
temporaries. The callee's EH routine is next; it invokes the temporary
destruction routines of those lazy expressions that have already been
invoked successfully in the current full-expression, just prior to cleaning
up the respective return values. So destructors are invoked in the correct
order and as appropriate, with no changes needed to the exception handling
system.
> Also, you seem to mix scope and storage: the scope of the lazy evaluation
> is completely and nicely defined: it is the same scope as if it were not
> lazy.
> The storage used depends on the ABI (how the stack frames are handled),
> but that's completely implementation defined.
>
--=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/CAJnLdObBZo1vmE9gRT3zKm28Ko-jCV5VOmFc2-GXtW3Q1Aa=
8sw%40mail.gmail.com.
--0000000000004ea095056d7022b7
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"auto"><div><br><br><div class=3D"gmail_quote"><div dir=3D"ltr">=
On Wed, 30 May 2018, 18:00 , <<a href=3D"mailto:florian.csdt@gmail.com" =
target=3D"_blank" rel=3D"noreferrer">florian.csdt@gmail.com</a>> wrote:<=
br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><br>Le mercred=
i 30 mai 2018 18:47:14 UTC+2, <a href=3D"mailto:floria...@gmail.com" rel=3D=
"noreferrer noreferrer" target=3D"_blank">floria...@gmail.com</a> a =C3=A9c=
rit=C2=A0:<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"><br><br>=
Le mercredi 30 mai 2018 18:42:06 UTC+2, Nicol Bolas a =C3=A9crit=C2=A0:<blo=
ckquote 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">On Wednesday, May 30, =
2018 at 12:04:45 PM UTC-4, <a rel=3D"noreferrer noreferrer">mihailn...@gmai=
l.com</a> 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">On=
Wednesday, May 30, 2018 at 6:35:47 PM UTC+3, Nicol Bolas 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">On Wednesday, May 30, 2018 at=
10:46:39 AM UTC-4, <a rel=3D"noreferrer noreferrer">floria...@gmail.com</a=
> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>=C2=
=A0</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><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></div><=
div>I agree that that would be a better semantic, but it implies a differen=
t ABI to that proposed (in passing) in P0927; rather than a single code poi=
nter code whose invocation evaluates the expression, we need two code point=
ers with the second destructing temporaries, or a single code pointer with =
signature <font face=3D"monospace, monospace">T(void* caller_stack, enum cl=
ass action { evaluate, destruct_temporaries})</font>. The caller would stil=
l need to reserve stack space for any temporaries in the lazily evaluated e=
xpression, but would not need to maintain a flag indicating whether tempora=
ries had been constructed, as calling the code pointer to perform cleanup w=
ould be the responsibility of the callee.</div></div></blockquote><div><br>=
</div><div></div><div>ABI is essentially irrelevant, because the only way y=
ou can have lazy expressions work <i>correctly</i> is if the function(s) th=
at uses them are inlined, relative to the function that provided the expres=
sion.</div></div></blockquote><div><br></div><div>That's not true, ther=
e are many ways to implement this to have the correct behavior without inli=
ning. Edward's solution is one. <br></div></div></blockquote><blockquot=
e 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>And as I said before, I=
don't what you call "the <i>correct</i> behavior" is what we=
want.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D=
"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr"><div></div><div>The only cross-ABI way to make lazy expressi=
ons work is to make them an actual function, with the expected C++ semantic=
s. At which point... they're not lazy expressions anymore. They're =
just a transparent way to turn an expression into a (lighter-weight) lambda=
..</div></div></blockquote><div><br></div><div>Yes, so what? C++ is ABI agno=
stic, you repeat this often enough. And now you want to specify language co=
nstructions to solve an implementation/ABI issue?</div></div></blockquote><=
div><br></div><div>No, I want to specify lazy expressions so that they'=
re <i>expressions</i>, not function calls. So that they work exactly as if =
you had copy-and-pasted the expression at the site of use.</div></div></blo=
ckquote><div><br></div><div>Any particular reason to want them to behave ex=
actly like that? Any pointer or examples of why this is required? =C2=A0</d=
iv><div><br></div><div>To this point I understood layzies are like this (co=
rrect me if I am wrong)</div><div><span style=3D"text-align:left;color:rgb(=
34,34,34);text-transform:none;text-indent:0px;letter-spacing:normal;font-si=
ze:13px;font-style:normal;font-variant:normal;font-weight:400;text-decorati=
on:none;word-spacing:0px;display:inline!important;white-space:normal;float:=
none;background-color:transparent"><font face=3D"courier new,monospace">voi=
d f()</font></span></div><div><font face=3D"courier new,monospace">{</font>=
</div><div><font face=3D"courier new,monospace">=C2=A0 call(string("he=
llo"));</font></div><div><font face=3D"courier new,monospace">}</font>=
</div><div><font face=3D"courier new,monospace"></font><font face=3D"courie=
r new,monospace"></font><br></div><div>becomes</div><div><br></div><div><fo=
nt face=3D"courier new,monospace">void f()</font></div><div><font face=3D"c=
ourier new,monospace">{</font></div><div><font face=3D"courier new,monospac=
e">=C2=A0{</font></div><div><font face=3D"courier new,monospace">=C2=A0 aut=
o s =3D=C2=A0<span style=3D"text-align:left;color:rgb(34,34,34);text-transf=
orm:none;text-indent:0px;letter-spacing:normal;font-size:13px;font-style:no=
rmal;font-variant:normal;font-weight:400;text-decoration:none;word-spacing:=
0px;display:inline!important;white-space:normal;float:none;background-color=
:transparent">string("hello");</span></font></div><div><span styl=
e=3D"text-align:left;color:rgb(34,34,34);text-transform:none;text-indent:0p=
x;letter-spacing:normal;font-size:13px;font-style:normal;font-variant:norma=
l;font-weight:400;text-decoration:none;word-spacing:0px;display:inline!impo=
rtant;white-space:normal;float:none;background-color:transparent"><font fac=
e=3D"courier new,monospace">=C2=A0 call(s);</font></span></div><div><span s=
tyle=3D"text-align:left;color:rgb(34,34,34);text-transform:none;text-indent=
:0px;letter-spacing:normal;font-size:13px;font-style:normal;font-variant:no=
rmal;font-weight:400;text-decoration:none;word-spacing:0px;display:inline!i=
mportant;white-space:normal;float:none;background-color:transparent"><font =
face=3D"courier new,monospace">=C2=A0}</font></span></div><div><span style=
=3D"text-align:left;color:rgb(34,34,34);text-transform:none;text-indent:0px=
;letter-spacing:normal;font-size:13px;font-style:normal;font-variant:normal=
;font-weight:400;text-decoration:none;word-spacing:0px;display:inline!impor=
tant;white-space:normal;float:none;background-color:transparent"><font face=
=3D"courier new,monospace">}</font></span></div><div><span style=3D"text-al=
ign:left;color:rgb(34,34,34);text-transform:none;text-indent:0px;letter-spa=
cing:normal;font-size:13px;font-style:normal;font-variant:normal;font-weigh=
t:400;text-decoration:none;word-spacing:0px;display:inline!important;white-=
space:normal;float:none;background-color:transparent"><font face=3D"arial,s=
ans-serif"></font><font face=3D"courier new,monospace"></font><font face=3D=
"courier new,monospace"></font><br></span></div><div><span style=3D"text-al=
ign:left;color:rgb(34,34,34);text-transform:none;text-indent:0px;letter-spa=
cing:normal;font-size:13px;font-style:normal;font-variant:normal;font-weigh=
t:400;text-decoration:none;word-spacing:0px;display:inline!important;white-=
space:normal;float:none;background-color:transparent"><font face=3D"arial,s=
ans-serif"><i>However</i> the=C2=A0<span style=3D"display:inline!important;=
float:none;background-color:transparent;color:rgb(34,34,34);font-family:cou=
rier new,monospace;font-size:13px;font-style:normal;font-variant:normal;fon=
t-weight:400;letter-spacing:normal;text-align:left;text-decoration:none;tex=
t-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">auto =
s =3D=C2=A0</span><span style=3D"background-color:transparent;border-bottom=
-color:rgb(34,34,34);border-bottom-style:none;border-bottom-width:0px;borde=
r-left-color:rgb(34,34,34);border-left-style:none;border-left-width:0px;bor=
der-right-color:rgb(34,34,34);border-right-style:none;border-right-width:0p=
x;border-top-color:rgb(34,34,34);border-top-style:none;border-top-width:0px=
;color:rgb(34,34,34);display:inline;float:none;font-family:courier new,mono=
space;font-size:13px;font-style:normal;font-variant:normal;font-weight:400;=
letter-spacing:normal;margin-bottom:0px;margin-left:0px;margin-right:0px;ma=
rgin-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-=
top:0px;text-align:left;text-decoration:none;text-indent:0px;text-transform=
:none;white-space:normal;word-spacing:0px"></span><span style=3D"background=
-color:transparent;border-bottom-color:rgb(34,34,34);border-bottom-style:no=
ne;border-bottom-width:0px;border-left-color:rgb(34,34,34);border-left-styl=
e:none;border-left-width:0px;border-right-color:rgb(34,34,34);border-right-=
style:none;border-right-width:0px;border-top-color:rgb(34,34,34);border-top=
-style:none;border-top-width:0px;color:rgb(34,34,34);display:inline;float:n=
one;font-family:courier new,monospace;font-size:13px;font-style:normal;font=
-variant:normal;font-weight:400;letter-spacing:normal;margin-bottom:0px;mar=
gin-left:0px;margin-right:0px;margin-top:0px;padding-bottom:0px;padding-lef=
t:0px;padding-right:0px;padding-top:0px;text-align:left;text-decoration:non=
e;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">=
string("hello") <font face=3D"arial,sans-serif">is executed <i>no=
t</i> <i>before</i> the function call, but <i>from within</i> the function =
call, going back to the original context with all the locals visible and so=
on.</font></span></font></span> <br></div></div></blockquote><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><div><span style=3D"text-align:=
left;color:rgb(34,34,34);text-transform:none;text-indent:0px;letter-spacing=
:normal;font-size:13px;font-style:normal;font-variant:normal;font-weight:40=
0;text-decoration:none;word-spacing:0px;display:inline!important;white-spac=
e:normal;float:none;background-color:transparent"><font face=3D"arial,sans-=
serif"><span style=3D"background-color:transparent;border-bottom-color:rgb(=
34,34,34);border-bottom-style:none;border-bottom-width:0px;border-left-colo=
r:rgb(34,34,34);border-left-style:none;border-left-width:0px;border-right-c=
olor:rgb(34,34,34);border-right-style:none;border-right-width:0px;border-to=
p-color:rgb(34,34,34);border-top-style:none;border-top-width:0px;color:rgb(=
34,34,34);display:inline;float:none;font-family:courier new,monospace;font-=
size:13px;font-style:normal;font-variant:normal;font-weight:400;letter-spac=
ing:normal;margin-bottom:0px;margin-left:0px;margin-right:0px;margin-top:0p=
x;padding-bottom:0px;padding-left:0px;padding-right:0px;padding-top:0px;tex=
t-align:left;text-decoration:none;text-indent:0px;text-transform:none;white=
-space:normal;word-spacing:0px"><font face=3D"arial,sans-serif"><br></font>=
</span></font></span></div><div><span style=3D"text-align:left;color:rgb(34=
,34,34);text-transform:none;text-indent:0px;letter-spacing:normal;font-size=
:13px;font-style:normal;font-variant:normal;font-weight:400;text-decoration=
:none;word-spacing:0px;display:inline!important;white-space:normal;float:no=
ne;background-color:transparent"><font face=3D"arial,sans-serif"><span styl=
e=3D"background-color:transparent;border-bottom-color:rgb(34,34,34);border-=
bottom-style:none;border-bottom-width:0px;border-left-color:rgb(34,34,34);b=
order-left-style:none;border-left-width:0px;border-right-color:rgb(34,34,34=
);border-right-style:none;border-right-width:0px;border-top-color:rgb(34,34=
,34);border-top-style:none;border-top-width:0px;color:rgb(34,34,34);display=
:inline;float:none;font-family:courier new,monospace;font-size:13px;font-st=
yle:normal;font-variant:normal;font-weight:400;letter-spacing:normal;margin=
-bottom:0px;margin-left:0px;margin-right:0px;margin-top:0px;padding-bottom:=
0px;padding-left:0px;padding-right:0px;padding-top:0px;text-align:left;text=
-decoration:none;text-indent:0px;text-transform:none;white-space:normal;wor=
d-spacing:0px"><font face=3D"arial,sans-serif">That model seems to me prett=
y "natural" and easy to understand.</font></span></font></span></=
div></div></blockquote><div><br></div><div>A function in C++ is isolated fr=
om any non-global state outside of its parameters. That's a basic aspec=
t of how functions work.</div><div><br></div><div>The model you're talk=
ing about breaks this. A parameter will start manipulating memory outside o=
f that function's scope and outside of the scope of that function's=
parameters. It will create temporaries to objects outside of that function=
's scope. It will begin the lifetime of objects whose lifetime ends wel=
l outside of its own scope. That now makes it difficult to reason about the=
results of that expression.</div><div><br></div><div>For example, consider=
the case where one of the sub-expressions of a captured expression throws,=
and the function that evaluates the expression catches it, so that the exc=
eption doesn't get back to the function that provided the expression. W=
ell, what happens to the temporaries created by the captured expression <i>=
prior</i> to the throw?</div><div><br></div><div>In normal expressions (and=
in copy-and-paste lazy evaluation), the way this works is normal. Any temp=
oraries created are destroyed by stack unwinding. Those temporaries were cr=
eated in the current scope, so when the scope exits, those temporaries are =
destroyed.</div><div><br></div><div>But with your way, temporaries are mani=
fested <i>outside</i> of the scope they're created in. They are suppose=
d to live beyond that scope. So if you catch the exception before the scope=
leaves... what happens to them? When do they get destroyed? What is the ri=
ght answer?</div><div><br></div><div>If those temporaries are not destroyed=
, then now you have a situation where some of the temporaries were successf=
ully created and some were not. How does that work when you leave the captu=
ring function? And if they are destroyed... how does that make sense? You h=
aven't unwound the stack past their scope, so there's no reason for=
them to be destroyed.<br></div></div></blockquote><div><br></div><div>All =
those questions have been answered and solved by the example implementation=
I gave.</div><div>Execptions look natural.</div><div><br></div><div>The la=
zy evaluation scope is a bit different from other scopes in the sense that =
it is not nested with other scopes, it is in "parallel". But life=
time of temporaries within this scope follow classical rules.<br></div><div=
>=C2=A0</div></div></blockquote><div>If you want more complete answer, here=
I go:</div><div><br></div><div>If an exception is thrown by the lazy expre=
ssion, the lazy expression code destroys the successfully created objects, =
and lets the flag as it is (so the caller will not try to destroy any of th=
em).</div><div>After that, the exception is forwarded to the callee with cl=
assical means and the callee can catch the exception if needed.</div><div><=
br></div><div>And what if the lazy evaluation doesn't throw, but the ca=
llee does:</div><div>The caller will destroy the lazy scope as usual... (th=
is is something I forgot in my implementation, but trivially fixable with a=
std::scope_exit for instance)<br></div><div></div></div></blockquote></div=
></div><div dir=3D"auto"><br></div><div dir=3D"auto">Similarly, in the sche=
me I describe, the EH routine for the lazy expression where the exception i=
s thrown is invoked first; it cleans up its own temporaries. The callee'=
;s EH routine is next; it invokes the temporary destruction routines of tho=
se lazy expressions that have already been invoked successfully in the curr=
ent full-expression, just prior to cleaning up the respective return values=
.. So destructors are invoked in the correct order and as appropriate, with =
no changes needed to the exception handling system.=C2=A0</div><div dir=3D"=
auto"><br></div><div dir=3D"auto"><div class=3D"gmail_quote"><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;p=
adding-left:1ex"><div dir=3D"ltr"><div><br></div><div>Also, you seem to mix=
scope and storage: the scope of the lazy evaluation is completely and nice=
ly defined: it is the same scope as if it were not lazy.<br></div><div>The =
storage used depends on the ABI (how the stack frames are handled), but tha=
t's completely implementation defined.<br></div></div></blockquote></di=
v></div><div dir=3D"auto"><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/CAJnLdObBZo1vmE9gRT3zKm28Ko-jCV5VOmFc=
2-GXtW3Q1Aa8sw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdObBZo1vmE9g=
RT3zKm28Ko-jCV5VOmFc2-GXtW3Q1Aa8sw%40mail.gmail.com</a>.<br />
--0000000000004ea095056d7022b7--
.
Author: Hyman Rosen <hyman.rosen@gmail.com>
Date: Wed, 30 May 2018 14:01:30 -0400
Raw View
--000000000000a1e6e8056d702470
Content-Type: text/plain; charset="UTF-8"
Can't we specify that given void foo([] -> T parm);, a call foo(expr) is
treated as foo([&] -> T { return expr; }), and then let the semantics flow
from that? (With a touch of magic so that foo isn't generic, but that
should be fine for a parameterless lambda returning a specific type, right?)
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAHSYqdbpO97tt8JPT%3DJtk6zaJDzp07NbKWZTnFtGGD5j8vZp6A%40mail.gmail.com.
--000000000000a1e6e8056d702470
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Can't we specify that given <font face=3D"monospace, m=
onospace">void foo([] -> T parm);</font>, a call <font face=3D"monospace=
, monospace">foo(expr)</font> is treated as <font face=3D"monospace, monosp=
ace">foo([&] -> T { return expr; })</font>, and then let the semanti=
cs flow from that?=C2=A0 (With a touch of magic so that <font face=3D"monos=
pace, monospace">foo</font> isn't generic, but that should be fine for =
a parameterless lambda returning a specific type, right?)</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/CAHSYqdbpO97tt8JPT%3DJtk6zaJDzp07NbKW=
ZTnFtGGD5j8vZp6A%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAHSYqdbpO97tt8=
JPT%3DJtk6zaJDzp07NbKWZTnFtGGD5j8vZp6A%40mail.gmail.com</a>.<br />
--000000000000a1e6e8056d702470--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 30 May 2018 19:08:57 +0100
Raw View
--0000000000000d0b95056d703f7c
Content-Type: text/plain; charset="UTF-8"
On Wed, 30 May 2018, 19:01 Hyman Rosen, <hyman.rosen@gmail.com> wrote:
> Can't we specify that given void foo([] -> T parm);, a call foo(expr) is
> treated as foo([&] -> T { return expr; }), and then let the semantics
> flow from that? (With a touch of magic so that foo isn't generic, but
> that should be fine for a parameterless lambda returning a specific type,
> right?)
>
That would be a very bad idea if T is std::string_view and expr is
std::string("foo").
--
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/unsubscribe
> .
> To unsubscribe from this group and all its topics, 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/CAHSYqdbpO97tt8JPT%3DJtk6zaJDzp07NbKWZTnFtGGD5j8vZp6A%40mail.gmail.com
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAHSYqdbpO97tt8JPT%3DJtk6zaJDzp07NbKWZTnFtGGD5j8vZp6A%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>
--
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/CAJnLdOaq%3DjKMeDPrkv8ajUBTg3LXGb50neDmSaPz1e2iARLRJQ%40mail.gmail.com.
--0000000000000d0b95056d703f7c
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"auto"><div><br><br><div class=3D"gmail_quote"><div dir=3D"ltr">=
On Wed, 30 May 2018, 19:01 Hyman Rosen, <<a href=3D"mailto:hyman.rosen@g=
mail.com">hyman.rosen@gmail.com</a>> wrote:<br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div dir=3D"ltr">Can't we specify that given <font face=
=3D"monospace, monospace">void foo([] -> T parm);</font>, a call <font f=
ace=3D"monospace, monospace">foo(expr)</font> is treated as <font face=3D"m=
onospace, monospace">foo([&] -> T { return expr; })</font>, and then=
let the semantics flow from that?=C2=A0 (With a touch of magic so that <fo=
nt face=3D"monospace, monospace">foo</font> isn't generic, but that sho=
uld be fine for a parameterless lambda returning a specific type, right?)</=
div></blockquote></div></div><div dir=3D"auto"><br></div><div dir=3D"auto">=
<br></div><div dir=3D"auto">That would be a very bad idea if T is std::stri=
ng_view and expr is std::string("foo").=C2=A0</div><div dir=3D"au=
to"><br></div><div dir=3D"auto"><div class=3D"gmail_quote"><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pad=
ding-left:1ex">
<p></p>
-- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/unsubscribe" target=3D"_blan=
k" rel=3D"noreferrer">https://groups.google.com/a/isocpp.org/d/topic/std-pr=
oposals/5oUZysJB4HE/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_blank" rel=3D"n=
oreferrer">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank" rel=3D"noreferrer">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/CAHSYqdbpO97tt8JPT%3DJtk6zaJDzp07NbKW=
ZTnFtGGD5j8vZp6A%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r" target=3D"_blank" rel=3D"noreferrer">https://groups.google.com/a/isocpp.=
org/d/msgid/std-proposals/CAHSYqdbpO97tt8JPT%3DJtk6zaJDzp07NbKWZTnFtGGD5j8v=
Zp6A%40mail.gmail.com</a>.<br>
</blockquote></div></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/CAJnLdOaq%3DjKMeDPrkv8ajUBTg3LXGb50ne=
DmSaPz1e2iARLRJQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdOaq%3DjKM=
eDPrkv8ajUBTg3LXGb50neDmSaPz1e2iARLRJQ%40mail.gmail.com</a>.<br />
--0000000000000d0b95056d703f7c--
.
Author: florian.csdt@gmail.com
Date: Wed, 30 May 2018 11:21:57 -0700 (PDT)
Raw View
------=_Part_5167_669372018.1527704517396
Content-Type: multipart/alternative;
boundary="----=_Part_5168_331591032.1527704517396"
------=_Part_5168_331591032.1527704517396
Content-Type: text/plain; charset="UTF-8"
@Hyman: that would imply to many lifetime issues:
void print(std::string_view sv) { std::cout << sv << std::endl; }
void print_lazy([] -> std::string_view sv_expr) { std::cout << sv_expr <<
std::endl; }
template <class F> void print_fun(F&& f) { std::cout << std::forward<F>(f)()
<< std::endl; }
print(std::string("foo")); // This is correct
print_fun([] -> std::string_view { return std::string("foo"); } //
temporary string will be destroyed before being printed
print_lazy(std::string("foo")); // What do we want?
For the lazy one, my point of view is: we want it to be correct, but with
your suggestion, it will be equivalent to print_fun that will not be
correct as the string is destroyed too early.
@Nicol: Edward made a good and quick summary.
So in your example, when the throwing function throws, the lazy expression
destroys the two strings already constructed (with classical exception
handling for example), does not set the magic flag to true, and forward the
exception to the callee (foo in your example).
So at the beginning of the catch, no temporaries are alive.
Then when the callee has finished, the caller will check the flag: it will
still be false as it has not been set to true by the lazy expression, and
will therefore not destroy the temporaries.
After the execution of the lazy expression (but in still in the callee),
either all temporaries are alive (and the caller will need to destroy
them), or none.
Concerning the scope, I agree with you that in the lazy case, the scope
will start after, but it will still be the same (access to the same data,
same behavior regarding exceptions) as the non-lazy expression scope.
The difference is: a lazy expression scope might/will outlive the scope
that triggered its execution, but the rest is exactly the same.
I hope things are clearer now, but if that's not the case, I would be glad
to answer more of your questions.
--
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/4db1ba2f-4ff1-4499-9da0-fda49745089e%40isocpp.org.
------=_Part_5168_331591032.1527704517396
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">@Hyman: that would imply to many lifetime issues:<br><div =
style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, =
187); border-style: solid; border-width: 1px; overflow-wrap: break-word;" c=
lass=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subprettypri=
nt"><span style=3D"color: #008;" class=3D"styled-by-prettify">void</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">print</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">std</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">string_view sv</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"> st=
d</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">cout </span><span=
style=3D"color: #660;" class=3D"styled-by-prettify"><<</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> sv </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><<</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">endl</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">;</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></span><span style=3D"color: #008;" class=3D"styled-by-prettify">void</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> print_lazy<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">([]</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">-></span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">string_view sv_expr</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"> std</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">cou=
t </span><span style=3D"color: #660;" class=3D"styled-by-prettify"><<=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> sv_expr <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify"><<</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">endl</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #00=
0;" 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"><br></span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">template</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">&l=
t;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">class</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> F</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">></span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> print_fun</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">F</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">&&</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> f</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">)</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"> std</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">cout </span><span style=3D"color: =
#660;" class=3D"styled-by-prettify"><<</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">forward</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify"><</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify">F</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">>(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">f</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">)()</span><s=
pan 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"> std</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">endl</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">;</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><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">pr=
int</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">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"col=
or: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #080;=
" 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: #800;" class=3D"=
styled-by-prettify">// This is correct</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br>print_fun</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"style=
d-by-prettify">-></span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> std</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">stri=
ng_view </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">return</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">string</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #080;" cla=
ss=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"style=
d-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">// =
temporary string will be destroyed before being printed</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>print_lazy</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">std</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">string</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #080;" class=3D"style=
d-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: #800;" class=3D"styled-by-pretti=
fy">// What do we want?</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br></span></div></code></div><br>For the lazy one, my point o=
f view is: we want it to be correct, but with your suggestion, it will be e=
quivalent to print_fun that will not be correct as the string is destroyed =
too early.<br><br>@Nicol: Edward made a good and quick summary.<br>So in yo=
ur example, when the throwing function throws, the lazy expression destroys=
the two strings already constructed (with classical exception handling for=
example), does not set the magic flag to true, and forward the exception t=
o the callee (foo in your example).<br>So at the beginning of the catch, no=
temporaries are alive.<br><br>Then when the callee has finished, the calle=
r will check the flag: it will still be false as it has not been set to tru=
e by the lazy expression, and will therefore not destroy the temporaries.<b=
r><br>After the execution of the lazy expression (but in still in the calle=
e), either all temporaries are alive (and the caller will need to destroy t=
hem), or none.<br><br><br>Concerning the scope, I agree with you that in th=
e lazy case, the scope will start after, but it will still be the same (acc=
ess to the same data, same behavior regarding exceptions) as the non-lazy e=
xpression scope.<br>The difference is: a lazy expression scope might/will o=
utlive the scope that triggered its execution, but the rest is exactly the =
same.<br><br>I hope things are clearer now, but if that's not the case,=
I would be glad to answer more of your questions.<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/4db1ba2f-4ff1-4499-9da0-fda49745089e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4db1ba2f-4ff1-4499-9da0-fda49745089e=
%40isocpp.org</a>.<br />
------=_Part_5168_331591032.1527704517396--
------=_Part_5167_669372018.1527704517396--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 30 May 2018 11:53:01 -0700 (PDT)
Raw View
------=_Part_45096_1067749712.1527706381241
Content-Type: multipart/alternative;
boundary="----=_Part_45097_498826454.1527706381241"
------=_Part_45097_498826454.1527706381241
Content-Type: text/plain; charset="UTF-8"
On Wednesday, May 30, 2018 at 2:21:57 PM UTC-4, floria...@gmail.com wrote:
>
> @Nicol: Edward made a good and quick summary.
> So in your example, when the throwing function throws, the lazy expression
> destroys the two strings already constructed (with classical exception
> handling for example), does not set the magic flag to true, and forward the
> exception to the callee (foo in your example).
> So at the beginning of the catch, no temporaries are alive.
>
> Then when the callee has finished, the caller will check the flag: it will
> still be false as it has not been set to true by the lazy expression, and
> will therefore not destroy the temporaries.
>
> After the execution of the lazy expression (but in still in the callee),
> either all temporaries are alive (and the caller will need to destroy
> them), or none.
>
So, why is it OK for those temporaries to be destroyed if there's an
exception, but they must be extended to outside of the evaluator if there
is no exception? That's my point: if it's OK in one case for the
temporaries to no longer exist, then it ought to be OK in general.
If the goal is to make lazy expression evaluation work like non-lazy
evaluation, then this design fails. If an expression throws and it wasn't
lazily captured, the caller is the first one who sees it (since they're the
ones who evaluated it). If it was lazily captured, the function evaluating
the expression can swallow it, such that the caller never sees it.
That is, the same logic you use to say that the code providing the
expression ought to be providing storage for it is the same logic that
could be used to say that the throw ought to originate in the *caller*,
just like it would otherwise appear to. That is, if a lazy expression
throws, the code between the evaluator and the provider of the expression
unrolls immediately, and `catch` statements are only considered from the
site of the one who originally provided the expression.
Concerning the scope, I agree with you that in the lazy case, the scope
> will start after, but it will still be the same (access to the same data,
> same behavior regarding exceptions) as the non-lazy expression scope.
> The difference is: a lazy expression scope might/will outlive the scope
> that triggered its execution, but the rest is exactly the same.
>
Everything is the same... except for the parts where it is different. But
that means it's not the same. This would be the first time that the
creation of an automatic object extends beyond the block that invokes that
creation.
You can't say that isn't new.
I hope things are clearer now, but if that's not the case, I would be glad
> to answer more of your questions.
>
--
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/6279186c-9b97-4b7d-95f5-5edd868c9689%40isocpp.org.
------=_Part_45097_498826454.1527706381241
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, May 30, 2018 at 2:21:57 PM UTC-4, floria...@=
gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt=
r">@Nicol: Edward made a good and quick summary.<br>So in your example, whe=
n the throwing function throws, the lazy expression destroys the two string=
s already constructed (with classical exception handling for example), does=
not set the magic flag to true, and forward the exception to the callee (f=
oo in your example).<br>So at the beginning of the catch, no temporaries ar=
e alive.<br><br>Then when the callee has finished, the caller will check th=
e flag: it will still be false as it has not been set to true by the lazy e=
xpression, and will therefore not destroy the temporaries.<br><br>After the=
execution of the lazy expression (but in still in the callee), either all =
temporaries are alive (and the caller will need to destroy them), or none.<=
br></div></blockquote><div><br></div><div>So, why is it OK for those tempor=
aries to be destroyed if there's an exception, but they must be extende=
d to outside of the evaluator if there is no exception? That's my point=
: if it's OK in one case for the temporaries to no longer exist, then i=
t ought to be OK in general.<br></div><div><br></div><div>If the goal is to=
make lazy expression evaluation work like non-lazy evaluation, then this d=
esign fails. If an expression throws and it wasn't lazily captured, the=
caller is the first one who sees it (since they're the ones who evalua=
ted it). If it was lazily captured, the function evaluating the expression =
can swallow it, such that the caller never sees it.</div><div><br></div><di=
v>That is, the same logic you use to say that the code providing the expres=
sion ought to be providing storage for it is the same logic that could be u=
sed to say that the throw ought to originate in the <i>caller</i>, just lik=
e it would otherwise appear to. That is, if a lazy expression throws, the c=
ode between the evaluator and the provider of the expression unrolls immedi=
ately, and `catch` statements are only considered from the site of the one =
who originally provided the expression.</div><div><br></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Concerning the scope, I agre=
e with you that in the lazy case, the scope will start after, but it will s=
till be the same (access to the same data, same behavior regarding exceptio=
ns) as the non-lazy expression scope.<br>The difference is: a lazy expressi=
on scope might/will outlive the scope that triggered its execution, but the=
rest is exactly the same.<br></div></blockquote><div><br></div><div>Everyt=
hing is the same... except for the parts where it is different. But that me=
ans it's not the same. This would be the first time that the creation o=
f an automatic object extends beyond the block that invokes that creation.<=
/div><div><br></div><div>You can't say that isn't new.<br></div><di=
v><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">I=
hope things are clearer now, but if that's not the case, I would be gl=
ad to answer more of your questions.<br></div></blockquote></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/6279186c-9b97-4b7d-95f5-5edd868c9689%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/6279186c-9b97-4b7d-95f5-5edd868c9689=
%40isocpp.org</a>.<br />
------=_Part_45097_498826454.1527706381241--
------=_Part_45096_1067749712.1527706381241--
.
Author: inkwizytoryankes@gmail.com
Date: Wed, 30 May 2018 12:06:12 -0700 (PDT)
Raw View
------=_Part_45356_1302553658.1527707172182
Content-Type: multipart/alternative;
boundary="----=_Part_45357_1928184968.1527707172183"
------=_Part_45357_1928184968.1527707172183
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Wednesday, May 30, 2018 at 7:39:38 PM UTC+2, Nicol Bolas wrote:
>
> On Wednesday, May 30, 2018 at 1:00:10 PM UTC-4, floria...@gmail.com=20
wrote:
>
> > Le mercredi 30 mai 2018 18:47:14 UTC+2, floria...@gmail.com a=20
=C3=A9crit :
>
>
> I don't think this answered the question I asked, so allow me to=20
provide some code:
>
> void foo([]->std::string str)
> {
> try { auto str2 =3D str(); }
> catch(...)
> {
> }
> //bottom of code
> }
>
> foo(std::string("foo") + func_that_throws() + std::string("bar"));
>
> OK, the captured expression contains several temporaries.
>
> Let's say that the evaluation order for + for this implementation does=
=20
things purely left-to-right. So it creates a temporary `string("foo")`. It=
=20
then gets a temporary `string` from `func_that_throws()` and does=20
`operator+` on them, resulting in a prvalue. That prvalue will then=20
manifest a temporary to be added to the temporary `string("bar")`.
>
> Now of course, `func_that_throws` is so named because it throws. So my=
=20
question is this: given the above evaluation order, which temporaries are=
=20
still alive when you reach that `catch` statement?
>
> The only correct answer I can see is "none of them". And if that's the=
=20
case, why is it OK for those temporaries to be destroyed if you reach=20
"bottom of code" through the `catch` statement and not through=20
non-exception execution?
>
> And if some of those temporaries are alive and some are not... how=20
does that even work? Is there a boolean for each temporary in the captured=
=20
expression to say if it's alive?
IMHO behavior of this two lines (with `z1` and `z2`) should be=20
indistinguishable:
int foo(bool t, []->int a1, []->int a2){ return t ? a1() : a2(); }
auto z1 =3D p ? bar() : baz();
auto z2 =3D foo(p, bar(), baz());
or
bool test([]->bool a1, []->bool a2, []->bool a3) { return a1() && a2() && a=
3
(); }
auto z1 =3D foo() && bar() && baz();
auto z2 =3D test(foo(), bar(), baz());
Overall I think that parameter could be multiple times evaluated but it=20
will return same value every time, storage for it will be from caller and=
=20
caller will store flag that will check if paramere was aready evaluated.
This value is already needed today because if you have `&&` you can create=
=20
temporaries that need be destroyed after this expression.
Exception will leave parameter in uninitialized state and try unwind=20
current function, you can catch this exception and try call it again:
T try_catch([]->T try_, []->T catch_)
{
try
{
return try_();
}
catch(...)
{
return catch_();
}
}
If `try_` throw then from caller perspective `try_` was not call at all. If=
=20
we call any other parameter before then clean up will be responsible of=20
caller.
One parameter can have "block" of temporales guarded by one flag. Exception=
=20
in it will destroy rest that was already created leaving whole block=20
uninitlalized.
T try_again(int i, []->T try_)
{
while(i--)
{
try
{
return try_();
}
catch(...)
{
}
}
return T();
}
We try again to call this param, first fail leave parameter unevaluated,=20
then second will proceed if there was no previous call.
Again in current C++ this behavior need be implemented to support `?:` and=
=20
`&&` we simply need only to expose part of this to programmers.
--=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/016b1cbd-c129-4973-8c40-153f8fb6ec32%40isocpp.or=
g.
------=_Part_45357_1928184968.1527707172183
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, May 30, 2018 at 7:39:38 PM UTC+2, Ni=
col Bolas wrote:<br>><br>>=C2=A0=C2=A0=C2=A0 On Wednesday, May 30, 20=
18 at 1:00:10 PM UTC-4, floria...@gmail.com wrote:<br>><br>> =C2=A0 &=
gt;=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 Le mercredi 30 mai 2018 18:47:14 UTC+2, f=
loria...@gmail.com a =C3=A9crit :<br>><br>><br>>=C2=A0=C2=A0=C2=A0=
I don't think this answered the question I asked, so allow me to provi=
de some code:<br>><br>>=C2=A0=C2=A0=C2=A0 void foo([]->std::string=
str)<br>>=C2=A0=C2=A0=C2=A0 {<br>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try=
{ auto str2 =3D str(); }<br>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 catch(...)<=
br>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 {<br>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 }<br>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 //bottom of code<br>>=C2=A0=
=C2=A0=C2=A0 }<br><div>></div><div> > =C2=A0 foo(std::string("fo=
o") + func_that_throws() + std::string("bar"));</div>><br=
>> =C2=A0 OK, the captured expression contains several temporaries.<br>&=
gt;<br>>=C2=A0=C2=A0=C2=A0
Let's say that the evaluation order for + for this implementation does=
=20
things purely left-to-right. So it creates a temporary `string("foo&qu=
ot;)`.=20
It then gets a temporary `string` from `func_that_throws()` and does=20
`operator+` on them, resulting in a prvalue. That prvalue will then=20
manifest a temporary to be added to the temporary `string("bar")`=
..<br>><br>>=C2=A0=C2=A0=C2=A0
Now of course, `func_that_throws` is so named because it throws. So my=20
question is this: given the above evaluation order, which temporaries=20
are still alive when you reach that `catch` statement?<br>><br>>=C2=
=A0=C2=A0=C2=A0
The only correct answer I can see is "none of them". And if that=
's the=20
case, why is it OK for those temporaries to be destroyed if you reach=20
"bottom of code" through the `catch` statement and not through=20
non-exception execution?<br>><br>>=C2=A0=C2=A0=C2=A0 And if some of t=
hose=20
temporaries are alive and some are not... how does that even work? Is=20
there a boolean for each temporary in the captured expression to say if=20
it's alive?<br><br><br>IMHO behavior of this two lines (with `z1` and `=
z2`) should be indistinguishable:<br><div style=3D"background-color: rgb(25=
0, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; border=
-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><code class=
=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;"=
class=3D"styled-by-prettify">int</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> foo</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">bool</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> t</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: #660;" class=3D"styled-by-prettify">[]-></span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> a1</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">[]-></span><span style=3D"color: #008;" class=3D"styled=
-by-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> a2</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: #008;" class=3D"styled-by-prettify">return</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> t </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">?</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> a1</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"style=
d-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> a2</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 sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> z1 </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> p </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">?</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> bar</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"> baz</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">();</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: =
#008;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> z2 </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-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=
">p</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> bar</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">(),</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> baz</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">());</span></div></code></div>or<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: #008;" class=3D"styled-by-prettify">bool</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> test</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">([]-></span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">bool</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> a1</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">,</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: #008;" class=
=3D"styled-by-prettify">bool</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> a2</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: #008;" class=3D"styled-by-prettify">bool</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> a3</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: #6=
60;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> a1</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">()</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"> a2</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">()</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">&&</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> a3</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">();</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br><br></span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">auto</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
z1 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> foo</span><sp=
an 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"> bar</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"style=
d-by-prettify">&&</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> baz</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">auto=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> z2 </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> test</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</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"> bar</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">(),</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> baz</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">());</span></div></code></div><br>Overall
I think that parameter could be multiple times evaluated but it will=20
return same value every time, storage for it will be from caller and=20
caller will store flag that will check if paramere was aready evaluated.<br=
>This
value is already needed today because if you have `&&` you can=20
create temporaries that need be destroyed after this expression.<br>Excepti=
on
will leave parameter in uninitialized state and try unwind current=20
function, you can catch this exception and try call it again:<br><div style=
=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187);=
border-style: solid; border-width: 1px; overflow-wrap: break-word;" class=
=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint">=
<span style=3D"color: #000;" class=3D"styled-by-prettify">T try_catch</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">([]-></span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">T try_</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">T catch_</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"style=
d-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled=
-by-prettify">try</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">return</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> try_</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">();</span><span style=3D"color: #000;" class=3D"styled-b=
y-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"s=
tyled-by-prettify">catch</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">(...)</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><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;" cla=
ss=3D"styled-by-prettify"> catch_</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">();</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">}</span></div></code></div><br>If
`try_` throw then from caller perspective `try_` was not call at all.=20
If we call any other parameter before then clean up will be responsible=20
of caller.<br>One parameter can have "block" of temporales guarde=
d by=20
one flag. Exception in it will destroy rest that was already created=20
leaving whole block uninitlalized.<br><div style=3D"background-color: rgb(2=
50, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; borde=
r-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><code class=
=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #000;"=
class=3D"styled-by-prettify"><br>T try_again</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">int</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> i</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">T try_</sp=
an><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">{</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">while</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">i</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">--)</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">try</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: #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=
=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">return</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> try_</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: #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">catch</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 =C2=A0 =C2=A0 </span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </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>=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"> T</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">();</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span></div></code></div><br>We try again to call=
this param, first fail leave parameter unevaluated, then second will proce=
ed if there was no previous call.<br><br>Again
in current C++ this behavior need be implemented to support `?:` and=20
`&&` we simply need only to expose part of this to programmers.<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/016b1cbd-c129-4973-8c40-153f8fb6ec32%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/016b1cbd-c129-4973-8c40-153f8fb6ec32=
%40isocpp.org</a>.<br />
------=_Part_45357_1928184968.1527707172183--
------=_Part_45356_1302553658.1527707172182--
.
Author: florian.csdt@gmail.com
Date: Wed, 30 May 2018 12:16:24 -0700 (PDT)
Raw View
------=_Part_45768_1078701130.1527707784802
Content-Type: multipart/alternative;
boundary="----=_Part_45769_264271772.1527707784802"
------=_Part_45769_264271772.1527707784802
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le mercredi 30 mai 2018 20:53:01 UTC+2, Nicol Bolas a =C3=A9crit :
>
> On Wednesday, May 30, 2018 at 2:21:57 PM UTC-4, floria...@gmail.com wrote=
:
>>
>> @Nicol: Edward made a good and quick summary.
>> So in your example, when the throwing function throws, the lazy=20
>> expression destroys the two strings already constructed (with classical=
=20
>> exception handling for example), does not set the magic flag to true, an=
d=20
>> forward the exception to the callee (foo in your example).
>> So at the beginning of the catch, no temporaries are alive.
>>
>> Then when the callee has finished, the caller will check the flag: it=20
>> will still be false as it has not been set to true by the lazy expressio=
n,=20
>> and will therefore not destroy the temporaries.
>>
>> After the execution of the lazy expression (but in still in the callee),=
=20
>> either all temporaries are alive (and the caller will need to destroy=20
>> them), or none.
>>
>
> So, why is it OK for those temporaries to be destroyed if there's an=20
> exception, but they must be extended to outside of the evaluator if there=
=20
> is no exception? That's my point: if it's OK in one case for the=20
> temporaries to no longer exist, then it ought to be OK in general.
>
That's exactly like a non lazy expression: temporaries are destroyed at the=
=20
end of the scope. If there is an exception, the scope ends earlier.
I think I realise what your problem is: the lazy scope can outlive the=20
scope triggering its execution. And yes, that's new.
=20
>
> If the goal is to make lazy expression evaluation work like non-lazy=20
> evaluation, then this design fails. If an expression throws and it wasn't=
=20
> lazily captured, the caller is the first one who sees it (since they're t=
he=20
> ones who evaluated it). If it was lazily captured, the function evaluatin=
g=20
> the expression can swallow it, such that the caller never sees it.
>
True, the exception will not be seen by the callee if the expression is not=
=20
lazy. And if the expression is lazy, the callee can swallow the exception.=
=20
But that would be the case with any proposal allowing some kind of=20
lazy/delayed/deferred expression.
Even your proposal to make it as if it was copy pasted into the callee will=
=20
change the exception handler order. Or with callables.
=20
>
> That is, the same logic you use to say that the code providing the=20
> expression ought to be providing storage for it is the same logic that=20
> could be used to say that the throw ought to originate in the *caller*,=
=20
> just like it would otherwise appear to. That is, if a lazy expression=20
> throws, the code between the evaluator and the provider of the expression=
=20
> unrolls immediately, and `catch` statements are only considered from the=
=20
> site of the one who originally provided the expression.
>
That would be a possibility, but I'm not sure we want that. We would need=
=20
to find some use cases for both way to handle exceptions.
The problem I see with that is: in a function taking a lazy parameter, you=
=20
would not be able to write an exception handler without relying on=20
destructors (or std::scope_exit).
It would not be possible to use a try-catch even if the catch catches=20
anything and forwards the exception.
=20
>
> Concerning the scope, I agree with you that in the lazy case, the scope=
=20
>> will start after, but it will still be the same (access to the same data=
,=20
>> same behavior regarding exceptions) as the non-lazy expression scope.
>> The difference is: a lazy expression scope might/will outlive the scope=
=20
>> that triggered its execution, but the rest is exactly the same.
>>
>
> Everything is the same... except for the parts where it is different. But=
=20
> that means it's not the same. This would be the first time that the=20
> creation of an automatic object extends beyond the block that invokes tha=
t=20
> creation.
>
> You can't say that isn't new.
>
I agree, it's new. but it's not as different as you might think. In the=20
implementation, it is very different, but coneptually (at the language=20
level) it is not that different.
For me, as I already said, the difference is the destruction can outlive=20
the scope where it has been started.
Another way to see it is: the scope start point is delayed and will be=20
triggered by another (inner) scope.
--=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/6b7ba07f-33df-492c-a9fb-24d9c04662af%40isocpp.or=
g.
------=_Part_45769_264271772.1527707784802
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le mercredi 30 mai 2018 20:53:01 UTC+2, Nicol Bola=
s a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">On Wednesday, May 30, 2018 at 2:21:57 PM UTC-4, <a>floria...@gmail=
..com</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-l=
eft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">@Ni=
col: Edward made a good and quick summary.<br>So in your example, when the =
throwing function throws, the lazy expression destroys the two strings alre=
ady constructed (with classical exception handling for example), does not s=
et the magic flag to true, and forward the exception to the callee (foo in =
your example).<br>So at the beginning of the catch, no temporaries are aliv=
e.<br><br>Then when the callee has finished, the caller will check the flag=
: it will still be false as it has not been set to true by the lazy express=
ion, and will therefore not destroy the temporaries.<br><br>After the execu=
tion of the lazy expression (but in still in the callee), either all tempor=
aries are alive (and the caller will need to destroy them), or none.<br></d=
iv></blockquote><div><br></div><div>So, why is it OK for those temporaries =
to be destroyed if there's an exception, but they must be extended to o=
utside of the evaluator if there is no exception? That's my point: if i=
t's OK in one case for the temporaries to no longer exist, then it ough=
t to be OK in general.<br></div></div></blockquote><div><br></div><div>That=
's exactly like a non lazy expression: temporaries are destroyed at the=
end of the scope. If there is an exception, the scope ends earlier.</div><=
div>I think I realise what your problem is: the lazy scope can outlive the =
scope triggering its execution. And yes, that's new.<br></div><div>=C2=
=A0</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=
></div><div><br></div><div>If the goal is to make lazy expression evaluatio=
n work like non-lazy evaluation, then this design fails. If an expression t=
hrows and it wasn't lazily captured, the caller is the first one who se=
es it (since they're the ones who evaluated it). If it was lazily captu=
red, the function evaluating the expression can swallow it, such that the c=
aller never sees it.</div></div></blockquote><div><br></div><div>True, the =
exception will not be seen by the callee if the expression is not lazy. And=
if the expression is lazy, the callee can swallow the exception. But that =
would be the case with any proposal allowing some kind of lazy/delayed/defe=
rred expression.</div><div>Even your proposal to make it as if it was copy =
pasted into the callee will change the exception handler order. Or with cal=
lables.<br></div><div>=C2=A0</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><br></div><div>That is, the same logic you use =
to say that the code providing the expression ought to be providing storage=
for it is the same logic that could be used to say that the throw ought to=
originate in the <i>caller</i>, just like it would otherwise appear to. Th=
at is, if a lazy expression throws, the code between the evaluator and the =
provider of the expression unrolls immediately, and `catch` statements are =
only considered from the site of the one who originally provided the expres=
sion.</div></div></blockquote><div><br></div><div>That would be a possibili=
ty, but I'm not sure we want that. We would need to find some use cases=
for both way to handle exceptions.</div><div>The problem I see with that i=
s: in a function taking a lazy parameter, you would not be able to write an=
exception handler without relying on destructors (or std::scope_exit).</di=
v><div>It would not be possible to use a try-catch even if the catch catche=
s anything and forwards the exception.<br></div><div>=C2=A0</div><blockquot=
e 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><br></div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Concerning the scope, I ag=
ree with you that in the lazy case, the scope will start after, but it will=
still be the same (access to the same data, same behavior regarding except=
ions) as the non-lazy expression scope.<br>The difference is: a lazy expres=
sion scope might/will outlive the scope that triggered its execution, but t=
he rest is exactly the same.<br></div></blockquote><div><br></div><div>Ever=
ything is the same... except for the parts where it is different. But that =
means it's not the same. This would be the first time that the creation=
of an automatic object extends beyond the block that invokes that creation=
..</div><div><br></div><div>You can't say that isn't new.<br></div><=
/div></blockquote><div><br></div><div>I agree, it's new. but it's n=
ot as different as you might think. In the implementation, it is very diffe=
rent, but coneptually (at the language level) it is not that different.</di=
v><div>For me, as I already said, the difference is the destruction can out=
live the scope where it has been started.</div><div>Another way to see it i=
s: the scope start point is delayed and will be triggered by another (inner=
) scope.<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/6b7ba07f-33df-492c-a9fb-24d9c04662af%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/6b7ba07f-33df-492c-a9fb-24d9c04662af=
%40isocpp.org</a>.<br />
------=_Part_45769_264271772.1527707784802--
------=_Part_45768_1078701130.1527707784802--
.
Author: florian.csdt@gmail.com
Date: Wed, 30 May 2018 12:32:42 -0700 (PDT)
Raw View
------=_Part_35530_1491163751.1527708762692
Content-Type: multipart/alternative;
boundary="----=_Part_35531_389224017.1527708762693"
------=_Part_35531_389224017.1527708762693
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le mercredi 30 mai 2018 21:06:12 UTC+2, Marcin Jaczewski a =C3=A9crit :
>
>
>
> On Wednesday, May 30, 2018 at 7:39:38 PM UTC+2, Nicol Bolas wrote:
> >
> > On Wednesday, May 30, 2018 at 1:00:10 PM UTC-4, floria...@gmail.com=
=20
> wrote:
> >
> > > Le mercredi 30 mai 2018 18:47:14 UTC+2, floria...@gmail.com a=
=20
> =C3=A9crit :
> >
> >
> > I don't think this answered the question I asked, so allow me to=20
> provide some code:
> >
> > void foo([]->std::string str)
> > {
> > try { auto str2 =3D str(); }
> > catch(...)
> > {
> > }
> > //bottom of code
> > }
> >
> > foo(std::string("foo") + func_that_throws() + std::string("bar"));
> >
> > OK, the captured expression contains several temporaries.
> >
> > Let's say that the evaluation order for + for this implementation=20
> does things purely left-to-right. So it creates a temporary=20
> `string("foo")`. It then gets a temporary `string` from=20
> `func_that_throws()` and does `operator+` on them, resulting in a prvalue=
..=20
> That prvalue will then manifest a temporary to be added to the temporary=
=20
> `string("bar")`.
> >
> > Now of course, `func_that_throws` is so named because it throws. So=
=20
> my question is this: given the above evaluation order, which temporaries=
=20
> are still alive when you reach that `catch` statement?
> >
> > The only correct answer I can see is "none of them". And if that's=
=20
> the case, why is it OK for those temporaries to be destroyed if you reach=
=20
> "bottom of code" through the `catch` statement and not through=20
> non-exception execution?
> >
> > And if some of those temporaries are alive and some are not... how=
=20
> does that even work? Is there a boolean for each temporary in the capture=
d=20
> expression to say if it's alive?
>
>
> IMHO behavior of this two lines (with `z1` and `z2`) should be=20
> indistinguishable:
> int foo(bool t, []->int a1, []->int a2){ return t ? a1() : a2(); }
>
> auto z1 =3D p ? bar() : baz();
> auto z2 =3D foo(p, bar(), baz());
> or
> bool test([]->bool a1, []->bool a2, []->bool a3) { return a1() && a2() &&=
=20
> a3(); }
>
> auto z1 =3D foo() && bar() && baz();
> auto z2 =3D test(foo(), bar(), baz());
>
> Yes, if those are different, then the feature has failed its purpose.
=20
> Overall I think that parameter could be multiple times evaluated but it=
=20
> will return same value every time, storage for it will be from caller and=
=20
> caller will store flag that will check if paramere was aready evaluated.
>
I don't think it is a good idea to allow multiple evaluations of the=20
expression. If you need to reuse the result, you can store it in a local=20
variable and reuse it as many times as you want.
The problem I see with this automatic local variable stored/cached is: how=
=20
would you enforce RVO to construct the object in-place (one of the biggest=
=20
feature of this proposal).
I would say we should not enforce a single call by checking a flag for=20
instance, but make it undefined behaviour.
This would usually be constructing the object multiple times without=20
properly destroying them.
=20
> This value is already needed today because if you have `&&` you can creat=
e=20
> temporaries that need be destroyed after this expression.
> Exception will leave parameter in uninitialized state and try unwind=20
> current function, you can catch this exception and try call it again:
> T try_catch([]->T try_, []->T catch_)
> {
> try
> {
> return try_();
> }
> catch(...)
> {
> return catch_();
> }
> }
>
> If `try_` throw then from caller perspective `try_` was not call at all.=
=20
> If we call any other parameter before then clean up will be responsible o=
f=20
> caller.
> One parameter can have "block" of temporales guarded by one flag.=20
> Exception in it will destroy rest that was already created leaving whole=
=20
> block uninitlalized.
>
> T try_again(int i, []->T try_)
> {
> while(i--)
> {
> try
> {
> return try_();
> }
> catch(...)
> {
> }
> }
> return T();
> }
>
> We try again to call this param, first fail leave parameter unevaluated,=
=20
> then second will proceed if there was no previous call.
>
> Again in current C++ this behavior need be implemented to support `?:` an=
d=20
> `&&` we simply need only to expose part of this to programmers.
>
--=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/4f469abb-15b1-4b50-9287-727d339f53b9%40isocpp.or=
g.
------=_Part_35531_389224017.1527708762693
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le mercredi 30 mai 2018 21:06:12 UTC+2, Marcin Jac=
zewski a =C3=A9crit=C2=A0:<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"><br><br>On Wednesday, May 30, 2018 at 7:39:38 PM UTC+2, Nicol =
Bolas wrote:<br>><br>>=C2=A0=C2=A0=C2=A0 On Wednesday, May 30, 2018 a=
t 1:00:10 PM UTC-4, <a>floria...@gmail.com</a> wrote:<br>><br>> =C2=
=A0 >=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 Le mercredi 30 mai 2018 18:47:14 UTC=
+2, <a>floria...@gmail.com</a> a =C3=A9crit :<br>><br>><br>>=C2=A0=
=C2=A0=C2=A0 I don't think this answered the question I asked, so allow=
me to provide some code:<br>><br>>=C2=A0=C2=A0=C2=A0 void foo([]->=
;std::string str)<br>>=C2=A0=C2=A0=C2=A0 {<br>>=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0 try { auto str2 =3D str(); }<br>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 catch(...)<br>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 {<br>>=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 }<br>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 //bottom of code=
<br>>=C2=A0=C2=A0=C2=A0 }<br><div>></div><div> > =C2=A0 foo(std::s=
tring("foo") + func_that_throws() + std::string("bar"))=
;</div>><br>> =C2=A0 OK, the captured expression contains several tem=
poraries.<br>><br>>=C2=A0=C2=A0=C2=A0
Let's say that the evaluation order for + for this implementation does=
=20
things purely left-to-right. So it creates a temporary `string("foo&qu=
ot;)`.=20
It then gets a temporary `string` from `func_that_throws()` and does=20
`operator+` on them, resulting in a prvalue. That prvalue will then=20
manifest a temporary to be added to the temporary `string("bar")`=
..<br>><br>>=C2=A0=C2=A0=C2=A0
Now of course, `func_that_throws` is so named because it throws. So my=20
question is this: given the above evaluation order, which temporaries=20
are still alive when you reach that `catch` statement?<br>><br>>=C2=
=A0=C2=A0=C2=A0
The only correct answer I can see is "none of them". And if that=
's the=20
case, why is it OK for those temporaries to be destroyed if you reach=20
"bottom of code" through the `catch` statement and not through=20
non-exception execution?<br>><br>>=C2=A0=C2=A0=C2=A0 And if some of t=
hose=20
temporaries are alive and some are not... how does that even work? Is=20
there a boolean for each temporary in the captured expression to say if=20
it's alive?<br><br><br>IMHO behavior of this two lines (with `z1` and `=
z2`) should be indistinguishable:<br><div style=3D"background-color:rgb(250=
,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px=
"><code><div><span style=3D"color:#008">int</span><span style=3D"color:#000=
"> foo</span><span style=3D"color:#660">(</span><span style=3D"color:#008">=
bool</span><span style=3D"color:#000"> t</span><span style=3D"color:#660">,=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">[]->=
;</span><span style=3D"color:#008">int</span><span style=3D"color:#000"> a1=
</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#660">[]-></span><span style=3D"color:#008">int</=
span><span style=3D"color:#000"> a2</span><span style=3D"color:#660">){</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#008">return</sp=
an><span style=3D"color:#000"> t </span><span style=3D"color:#660">?</span>=
<span style=3D"color:#000"> a1</span><span style=3D"color:#660">()</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span s=
tyle=3D"color:#000"> a2</span><span style=3D"color:#660">();</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br><br></span><span style=3D"color:#008">auto</span><span =
style=3D"color:#000"> z1 </span><span style=3D"color:#660">=3D</span><span =
style=3D"color:#000"> p </span><span style=3D"color:#660">?</span><span sty=
le=3D"color:#000"> bar</span><span style=3D"color:#660">()</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#660">:</span><span style=3D"=
color:#000"> baz</span><span style=3D"color:#660">();</span><span style=3D"=
color:#000"><br></span><span style=3D"color:#008">auto</span><span style=3D=
"color:#000"> z2 </span><span style=3D"color:#660">=3D</span><span style=3D=
"color:#000"> foo</span><span style=3D"color:#660">(</span><span style=3D"c=
olor:#000">p</span><span style=3D"color:#660">,</span><span style=3D"color:=
#000"> bar</span><span style=3D"color:#660">(),</span><span style=3D"color:=
#000"> baz</span><span style=3D"color:#660">());</span></div></code></div>o=
r<br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,1=
87,187);border-style:solid;border-width:1px"><code><div><span style=3D"colo=
r:#008">bool</span><span style=3D"color:#000"> test</span><span style=3D"co=
lor:#660">([]-></span><span style=3D"color:#008">bool</span><span style=
=3D"color:#000"> a1</span><span style=3D"color:#660">,</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">[]-></span><span style=
=3D"color:#008">bool</span><span style=3D"color:#000"> a2</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">[]-></span><span style=3D"color:#008">bool</span><span style=
=3D"color:#000"> a3</span><span style=3D"color:#660">)</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#008">return</span><span style=3D"colo=
r:#000"> a1</span><span style=3D"color:#660">()</span><span style=3D"color:=
#000"> </span><span style=3D"color:#660">&&</span><span style=3D"co=
lor:#000"> a2</span><span style=3D"color:#660">()</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#660">&&</span><span style=3D"=
color:#000"> a3</span><span style=3D"color:#660">();</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660">}</span><span style=3D"color:=
#000"><br><br></span><span style=3D"color:#008">auto</span><span style=3D"c=
olor:#000"> z1 </span><span style=3D"color:#660">=3D</span><span style=3D"c=
olor:#000"> foo</span><span style=3D"color:#660">()</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#660">&&</span><span style=
=3D"color:#000"> bar</span><span style=3D"color:#660">()</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">&&</span><span s=
tyle=3D"color:#000"> baz</span><span style=3D"color:#660">();</span><span s=
tyle=3D"color:#000"><br></span><span style=3D"color:#008">auto</span><span =
style=3D"color:#000"> z2 </span><span style=3D"color:#660">=3D</span><span =
style=3D"color:#000"> test</span><span style=3D"color:#660">(</span><span s=
tyle=3D"color:#000">foo</span><span style=3D"color:#660">(),</span><span st=
yle=3D"color:#000"> bar</span><span style=3D"color:#660">(),</span><span st=
yle=3D"color:#000"> baz</span><span style=3D"color:#660">());</span></div><=
/code></div><br></div></blockquote><div>Yes, if those are different, then t=
he feature has failed its purpose.<br></div><div>=C2=A0</div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px =
#ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Overall
I think that parameter could be multiple times evaluated but it will=20
return same value every time, storage for it will be from caller and=20
caller will store flag that will check if paramere was aready evaluated.<br=
></div></blockquote><div><br></div><div>I don't think it is a good idea=
to allow multiple evaluations of the expression. If you need to reuse the =
result, you can store it in a local variable and reuse it as many times as =
you want.</div><div>The problem I see with this automatic local variable st=
ored/cached is: how would you enforce RVO to construct the object in-place =
(one of the biggest feature of this proposal).</div><div><br></div><div>I w=
ould say we should not enforce a single call by checking a flag for instanc=
e, but make it undefined behaviour.</div><div>This would usually be constru=
cting the object multiple times without properly destroying them.<br></div>=
<div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr">This
value is already needed today because if you have `&&` you can=20
create temporaries that need be destroyed after this expression.<br>Excepti=
on
will leave parameter in uninitialized state and try unwind current=20
function, you can catch this exception and try call it again:<br><div style=
=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-=
style:solid;border-width:1px"><code><div><span style=3D"color:#000">T try_c=
atch</span><span style=3D"color:#660">([]-></span><span style=3D"color:#=
000">T try_</span><span style=3D"color:#660">,</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">[]-></span><span style=3D"color:=
#000">T catch_</span><span style=3D"color:#660">)</span><span style=3D"colo=
r:#000"><br></span><span style=3D"color:#660">{</span><span style=3D"color:=
#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">try</span><span s=
tyle=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">{</=
span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><spa=
n style=3D"color:#008">return</span><span style=3D"color:#000"> try_</span>=
<span style=3D"color:#660">();</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">catch</span><span styl=
e=3D"color:#660">(...)</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 <=
/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:#008">return</span><sp=
an style=3D"color:#000"> catch_</span><span style=3D"color:#660">();</span>=
<span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#6=
60">}</span><span style=3D"color:#000"><br></span><span style=3D"color:#660=
">}</span></div></code></div><br>If
`try_` throw then from caller perspective `try_` was not call at all.=20
If we call any other parameter before then clean up will be responsible=20
of caller.<br>One parameter can have "block" of temporales guarde=
d by=20
one flag. Exception in it will destroy rest that was already created=20
leaving whole block uninitlalized.<br><div style=3D"background-color:rgb(25=
0,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1p=
x"><code><div><span style=3D"color:#000"><br>T try_again</span><span style=
=3D"color:#660">(</span><span style=3D"color:#008">int</span><span style=3D=
"color:#000"> i</span><span style=3D"color:#660">,</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">[]-></span><span style=3D"co=
lor:#000">T try_</span><span style=3D"color:#660">)</span><span style=3D"co=
lor:#000"><br></span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">while</span><sp=
an style=3D"color:#660">(</span><span style=3D"color:#000">i</span><span st=
yle=3D"color:#660">--)</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 <=
/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:#008">try</span><span =
style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"=
color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span styl=
e=3D"color:#000"> try_</span><span style=3D"color:#660">();</span><span sty=
le=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"col=
or:#660">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0=
</span><span style=3D"color:#008">catch</span><span style=3D"color:#660">(=
....)</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </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:#660">}</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span=
><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#=
008">return</span><span style=3D"color:#000"> T</span><span style=3D"color:=
#660">();</span><span style=3D"color:#000"><br></span><span style=3D"color:=
#660">}</span></div></code></div><br>We try again to call this param, first=
fail leave parameter unevaluated, then second will proceed if there was no=
previous call.<br><br>Again
in current C++ this behavior need be implemented to support `?:` and=20
`&&` we simply need only to expose part of this to programmers.<br>=
</div></blockquote></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/4f469abb-15b1-4b50-9287-727d339f53b9%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4f469abb-15b1-4b50-9287-727d339f53b9=
%40isocpp.org</a>.<br />
------=_Part_35531_389224017.1527708762693--
------=_Part_35530_1491163751.1527708762692--
.
Author: inkwizytoryankes@gmail.com
Date: Wed, 30 May 2018 13:13:21 -0700 (PDT)
Raw View
------=_Part_251_38117133.1527711201550
Content-Type: multipart/alternative;
boundary="----=_Part_252_1815982875.1527711201550"
------=_Part_252_1815982875.1527711201550
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Wednesday, May 30, 2018 at 9:32:43 PM UTC+2, floria...@gmail.com wrote:
>
>
>
> Le mercredi 30 mai 2018 21:06:12 UTC+2, Marcin Jaczewski a =C3=A9crit :
>>
>>
>>
>> On Wednesday, May 30, 2018 at 7:39:38 PM UTC+2, Nicol Bolas wrote:
>> >
>> > On Wednesday, May 30, 2018 at 1:00:10 PM UTC-4, floria...@gmail.com=
=20
>> wrote:
>> >
>> > > Le mercredi 30 mai 2018 18:47:14 UTC+2, floria...@gmail.com a=
=20
>> =C3=A9crit :
>> >
>> >
>> > I don't think this answered the question I asked, so allow me to=20
>> provide some code:
>> >
>> > void foo([]->std::string str)
>> > {
>> > try { auto str2 =3D str(); }
>> > catch(...)
>> > {
>> > }
>> > //bottom of code
>> > }
>> >
>> > foo(std::string("foo") + func_that_throws() + std::string("bar"));
>> >
>> > OK, the captured expression contains several temporaries.
>> >
>> > Let's say that the evaluation order for + for this implementation=
=20
>> does things purely left-to-right. So it creates a temporary=20
>> `string("foo")`. It then gets a temporary `string` from=20
>> `func_that_throws()` and does `operator+` on them, resulting in a prvalu=
e.=20
>> That prvalue will then manifest a temporary to be added to the temporary=
=20
>> `string("bar")`.
>> >
>> > Now of course, `func_that_throws` is so named because it throws. So=
=20
>> my question is this: given the above evaluation order, which temporaries=
=20
>> are still alive when you reach that `catch` statement?
>> >
>> > The only correct answer I can see is "none of them". And if that's=
=20
>> the case, why is it OK for those temporaries to be destroyed if you reac=
h=20
>> "bottom of code" through the `catch` statement and not through=20
>> non-exception execution?
>> >
>> > And if some of those temporaries are alive and some are not... how=
=20
>> does that even work? Is there a boolean for each temporary in the captur=
ed=20
>> expression to say if it's alive?
>>
>>
>> IMHO behavior of this two lines (with `z1` and `z2`) should be=20
>> indistinguishable:
>> int foo(bool t, []->int a1, []->int a2){ return t ? a1() : a2(); }
>>
>> auto z1 =3D p ? bar() : baz();
>> auto z2 =3D foo(p, bar(), baz());
>> or
>> bool test([]->bool a1, []->bool a2, []->bool a3) { return a1() && a2() &=
&=20
>> a3(); }
>>
>> auto z1 =3D foo() && bar() && baz();
>> auto z2 =3D test(foo(), bar(), baz());
>>
>> Yes, if those are different, then the feature has failed its purpose.
> =20
>
>> Overall I think that parameter could be multiple times evaluated but it=
=20
>> will return same value every time, storage for it will be from caller an=
d=20
>> caller will store flag that will check if paramere was aready evaluated.
>>
>
> I don't think it is a good idea to allow multiple evaluations of the=20
> expression. If you need to reuse the result, you can store it in a local=
=20
> variable and reuse it as many times as you want.
> The problem I see with this automatic local variable stored/cached is: ho=
w=20
> would you enforce RVO to construct the object in-place (one of the bigges=
t=20
> feature of this proposal).
>
> I would say we should not enforce a single call by checking a flag for=20
> instance, but make it undefined behaviour.
> This would usually be constructing the object multiple times without=20
> properly destroying them.
> =20
>
I use wrong words, when you call `p()` and then you again call `p()` then=
=20
code will be call only once. This will have cost but only one `if`, value=
=20
that store this flag is already need in current C++.
If function get inlined this cost could be removed because in some cases we=
=20
could infer from context what temporaries live. This is probably small cost=
=20
compare to UB.
I think that for `[]->int a` we should have `&a() =3D=3D &a()` this will be=
=20
same temporary variable that is allocated on caller stack.=20
Only problem I see is order in with temporaries will be destroyed, probably=
=20
it will be fixed one not depending on order in with params was call. Adding=
=20
info about order will only increase implementation complexity and cost of=
=20
each call of this parameter. This part I would leave UB.
--=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/70c7e4cd-c1b2-49bd-b831-b07ee3cf3f11%40isocpp.or=
g.
------=_Part_252_1815982875.1527711201550
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, May 30, 2018 at 9:32:43 PM UTC+2, fl=
oria...@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div d=
ir=3D"ltr"><br><br>Le mercredi 30 mai 2018 21:06:12 UTC+2, Marcin Jaczewski=
a =C3=A9crit=C2=A0:<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=
"><br><br>On Wednesday, May 30, 2018 at 7:39:38 PM UTC+2, Nicol Bolas wrote=
:<br>><br>>=C2=A0=C2=A0=C2=A0 On Wednesday, May 30, 2018 at 1:00:10 P=
M UTC-4, <a>floria...@gmail.com</a> wrote:<br>><br>> =C2=A0 >=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0 Le mercredi 30 mai 2018 18:47:14 UTC+2, <a>flor=
ia...@gmail.com</a> a =C3=A9crit :<br>><br>><br>>=C2=A0=C2=A0=C2=
=A0 I don't think this answered the question I asked, so allow me to pr=
ovide some code:<br>><br>>=C2=A0=C2=A0=C2=A0 void foo([]->std::str=
ing str)<br>>=C2=A0=C2=A0=C2=A0 {<br>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =
try { auto str2 =3D str(); }<br>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 catch(..=
..)<br>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 {<br>>=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0 }<br>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 //bottom of code<br>>=C2=
=A0=C2=A0=C2=A0 }<br><div>></div><div> > =C2=A0 foo(std::string("=
;foo") + func_that_throws() + std::string("bar"));</div>>=
<br>> =C2=A0 OK, the captured expression contains several temporaries.<b=
r>><br>>=C2=A0=C2=A0=C2=A0
Let's say that the evaluation order for + for this implementation does=
=20
things purely left-to-right. So it creates a temporary `string("foo&qu=
ot;)`.=20
It then gets a temporary `string` from `func_that_throws()` and does=20
`operator+` on them, resulting in a prvalue. That prvalue will then=20
manifest a temporary to be added to the temporary `string("bar")`=
..<br>><br>>=C2=A0=C2=A0=C2=A0
Now of course, `func_that_throws` is so named because it throws. So my=20
question is this: given the above evaluation order, which temporaries=20
are still alive when you reach that `catch` statement?<br>><br>>=C2=
=A0=C2=A0=C2=A0
The only correct answer I can see is "none of them". And if that=
's the=20
case, why is it OK for those temporaries to be destroyed if you reach=20
"bottom of code" through the `catch` statement and not through=20
non-exception execution?<br>><br>>=C2=A0=C2=A0=C2=A0 And if some of t=
hose=20
temporaries are alive and some are not... how does that even work? Is=20
there a boolean for each temporary in the captured expression to say if=20
it's alive?<br><br><br>IMHO behavior of this two lines (with `z1` and `=
z2`) should be indistinguishable:<br><div style=3D"background-color:rgb(250=
,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px=
"><code><div><span style=3D"color:#008">int</span><span style=3D"color:#000=
"> foo</span><span style=3D"color:#660">(</span><span style=3D"color:#008">=
bool</span><span style=3D"color:#000"> t</span><span style=3D"color:#660">,=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">[]->=
;</span><span style=3D"color:#008">int</span><span style=3D"color:#000"> a1=
</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#660">[]-></span><span style=3D"color:#008">int</=
span><span style=3D"color:#000"> a2</span><span style=3D"color:#660">){</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#008">return</sp=
an><span style=3D"color:#000"> t </span><span style=3D"color:#660">?</span>=
<span style=3D"color:#000"> a1</span><span style=3D"color:#660">()</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span s=
tyle=3D"color:#000"> a2</span><span style=3D"color:#660">();</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br><br></span><span style=3D"color:#008">auto</span><span =
style=3D"color:#000"> z1 </span><span style=3D"color:#660">=3D</span><span =
style=3D"color:#000"> p </span><span style=3D"color:#660">?</span><span sty=
le=3D"color:#000"> bar</span><span style=3D"color:#660">()</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#660">:</span><span style=3D"=
color:#000"> baz</span><span style=3D"color:#660">();</span><span style=3D"=
color:#000"><br></span><span style=3D"color:#008">auto</span><span style=3D=
"color:#000"> z2 </span><span style=3D"color:#660">=3D</span><span style=3D=
"color:#000"> foo</span><span style=3D"color:#660">(</span><span style=3D"c=
olor:#000">p</span><span style=3D"color:#660">,</span><span style=3D"color:=
#000"> bar</span><span style=3D"color:#660">(),</span><span style=3D"color:=
#000"> baz</span><span style=3D"color:#660">());</span></div></code></div>o=
r<br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,1=
87,187);border-style:solid;border-width:1px"><code><div><span style=3D"colo=
r:#008">bool</span><span style=3D"color:#000"> test</span><span style=3D"co=
lor:#660">([]-></span><span style=3D"color:#008">bool</span><span style=
=3D"color:#000"> a1</span><span style=3D"color:#660">,</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">[]-></span><span style=
=3D"color:#008">bool</span><span style=3D"color:#000"> a2</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">[]-></span><span style=3D"color:#008">bool</span><span style=
=3D"color:#000"> a3</span><span style=3D"color:#660">)</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#008">return</span><span style=3D"colo=
r:#000"> a1</span><span style=3D"color:#660">()</span><span style=3D"color:=
#000"> </span><span style=3D"color:#660">&&</span><span style=3D"co=
lor:#000"> a2</span><span style=3D"color:#660">()</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#660">&&</span><span style=3D"=
color:#000"> a3</span><span style=3D"color:#660">();</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660">}</span><span style=3D"color:=
#000"><br><br></span><span style=3D"color:#008">auto</span><span style=3D"c=
olor:#000"> z1 </span><span style=3D"color:#660">=3D</span><span style=3D"c=
olor:#000"> foo</span><span style=3D"color:#660">()</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#660">&&</span><span style=
=3D"color:#000"> bar</span><span style=3D"color:#660">()</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">&&</span><span s=
tyle=3D"color:#000"> baz</span><span style=3D"color:#660">();</span><span s=
tyle=3D"color:#000"><br></span><span style=3D"color:#008">auto</span><span =
style=3D"color:#000"> z2 </span><span style=3D"color:#660">=3D</span><span =
style=3D"color:#000"> test</span><span style=3D"color:#660">(</span><span s=
tyle=3D"color:#000">foo</span><span style=3D"color:#660">(),</span><span st=
yle=3D"color:#000"> bar</span><span style=3D"color:#660">(),</span><span st=
yle=3D"color:#000"> baz</span><span style=3D"color:#660">());</span></div><=
/code></div><br></div></blockquote><div>Yes, if those are different, then t=
he feature has failed its purpose.<br></div><div>=C2=A0</div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #cc=
c solid;padding-left:1ex"><div dir=3D"ltr">Overall
I think that parameter could be multiple times evaluated but it will=20
return same value every time, storage for it will be from caller and=20
caller will store flag that will check if paramere was aready evaluated.<br=
></div></blockquote><div><br></div><div>I don't think it is a good idea=
to allow multiple evaluations of the expression. If you need to reuse the =
result, you can store it in a local variable and reuse it as many times as =
you want.</div><div>The problem I see with this automatic local variable st=
ored/cached is: how would you enforce RVO to construct the object in-place =
(one of the biggest feature of this proposal).</div><div><br></div><div>I w=
ould say we should not enforce a single call by checking a flag for instanc=
e, but make it undefined behaviour.</div><div>This would usually be constru=
cting the object multiple times without properly destroying them.<br></div>=
<div>=C2=A0</div></div></blockquote><div><br></div><div>I use wrong words, =
when you call `p()` and then you again call `p()` then code will be call on=
ly once. This will have cost but only one `if`, value that store this flag =
is already need in current C++.</div><div>If function get inlined this cost=
could be removed because in some cases we could <span data-dobid=3D"hdw">i=
nfer from context what temporaries live. This is probably small cost compar=
e to UB.<br></span></div><div><br></div><div>I think that for `[]->int a=
` we should have `&a() =3D=3D &a()` this will be same temporary var=
iable that is allocated on caller stack. <br></div><div><br></div><div>Only=
problem I see is order in with <span data-dobid=3D"hdw">temporaries </span=
>will be destroyed, probably it will be fixed one not depending on order in=
with params was call. Adding info about order will only increase implement=
ation complexity and cost of each call of this parameter. This part I would=
leave UB.<br></div><div dir=3D"ltr"><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/70c7e4cd-c1b2-49bd-b831-b07ee3cf3f11%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/70c7e4cd-c1b2-49bd-b831-b07ee3cf3f11=
%40isocpp.org</a>.<br />
------=_Part_252_1815982875.1527711201550--
------=_Part_251_38117133.1527711201550--
.
Author: florian.csdt@gmail.com
Date: Wed, 30 May 2018 13:59:26 -0700 (PDT)
Raw View
------=_Part_131_1276315013.1527713966312
Content-Type: multipart/alternative;
boundary="----=_Part_132_1369977418.1527713966313"
------=_Part_132_1369977418.1527713966313
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le mercredi 30 mai 2018 22:13:21 UTC+2, Marcin Jaczewski a =C3=A9crit :
>
>
>
> On Wednesday, May 30, 2018 at 9:32:43 PM UTC+2, floria...@gmail.com wrote=
:
>>
>>
>>
>> Le mercredi 30 mai 2018 21:06:12 UTC+2, Marcin Jaczewski a =C3=A9crit :
>>>
>>>
>>>
>>> On Wednesday, May 30, 2018 at 7:39:38 PM UTC+2, Nicol Bolas wrote:
>>> >
>>> > On Wednesday, May 30, 2018 at 1:00:10 PM UTC-4, floria...@gmail.co=
m=20
>>> wrote:
>>> >
>>> > > Le mercredi 30 mai 2018 18:47:14 UTC+2, floria...@gmail.com=
=20
>>> a =C3=A9crit :
>>> >
>>> >
>>> > I don't think this answered the question I asked, so allow me to=
=20
>>> provide some code:
>>> >
>>> > void foo([]->std::string str)
>>> > {
>>> > try { auto str2 =3D str(); }
>>> > catch(...)
>>> > {
>>> > }
>>> > //bottom of code
>>> > }
>>> >
>>> > foo(std::string("foo") + func_that_throws() + std::string("bar"));
>>> >
>>> > OK, the captured expression contains several temporaries.
>>> >
>>> > Let's say that the evaluation order for + for this implementation=
=20
>>> does things purely left-to-right. So it creates a temporary=20
>>> `string("foo")`. It then gets a temporary `string` from=20
>>> `func_that_throws()` and does `operator+` on them, resulting in a prval=
ue.=20
>>> That prvalue will then manifest a temporary to be added to the temporar=
y=20
>>> `string("bar")`.
>>> >
>>> > Now of course, `func_that_throws` is so named because it throws. S=
o=20
>>> my question is this: given the above evaluation order, which temporarie=
s=20
>>> are still alive when you reach that `catch` statement?
>>> >
>>> > The only correct answer I can see is "none of them". And if that's=
=20
>>> the case, why is it OK for those temporaries to be destroyed if you rea=
ch=20
>>> "bottom of code" through the `catch` statement and not through=20
>>> non-exception execution?
>>> >
>>> > And if some of those temporaries are alive and some are not... how=
=20
>>> does that even work? Is there a boolean for each temporary in the captu=
red=20
>>> expression to say if it's alive?
>>>
>>>
>>> IMHO behavior of this two lines (with `z1` and `z2`) should be=20
>>> indistinguishable:
>>> int foo(bool t, []->int a1, []->int a2){ return t ? a1() : a2(); }
>>>
>>> auto z1 =3D p ? bar() : baz();
>>> auto z2 =3D foo(p, bar(), baz());
>>> or
>>> bool test([]->bool a1, []->bool a2, []->bool a3) { return a1() && a2()=
=20
>>> && a3(); }
>>>
>>> auto z1 =3D foo() && bar() && baz();
>>> auto z2 =3D test(foo(), bar(), baz());
>>>
>>> Yes, if those are different, then the feature has failed its purpose.
>> =20
>>
>>> Overall I think that parameter could be multiple times evaluated but it=
=20
>>> will return same value every time, storage for it will be from caller a=
nd=20
>>> caller will store flag that will check if paramere was aready evaluated=
..
>>>
>>
>> I don't think it is a good idea to allow multiple evaluations of the=20
>> expression. If you need to reuse the result, you can store it in a local=
=20
>> variable and reuse it as many times as you want.
>> The problem I see with this automatic local variable stored/cached is:=
=20
>> how would you enforce RVO to construct the object in-place (one of the=
=20
>> biggest feature of this proposal).
>>
>> I would say we should not enforce a single call by checking a flag for=
=20
>> instance, but make it undefined behaviour.
>> This would usually be constructing the object multiple times without=20
>> properly destroying them.
>> =20
>>
>
> I use wrong words, when you call `p()` and then you again call `p()` then=
=20
> code will be call only once. This will have cost but only one `if`, value=
=20
> that store this flag is already need in current C++.
> If function get inlined this cost could be removed because in some cases=
=20
> we could infer from context what temporaries live. This is probably small=
=20
> cost compare to UB.
>
I understood what you said, and I keep thinking that's not a good idea.
std::array<int, 1000>* create_big([] -> std::array<int, 1000> a) {
return new std::array<int, 1000>(a()); //copy ellision: a() is a prvalue
}
auto *p =3D create_big({1, 2, ..., 1000});
Lazy parameter here allows to defer the creation of the array until the=20
point where its final storage is known, and "RVO" can be applied to ellide=
=20
the copy as the lazy expression "returns" a prvalue.
But now, if you do:
std::array<int, 1000>* create_big([] -> std::array<int, 1000> a) {
std::array<int, 1000> b(a()); // copy ellision
return new std::array<int, 1000>(b); // no copy ellision here, b is not a=
=20
prvalue
}
auto *p =3D create_big({1, 2, ..., 1000});
The copy is not ellided as b is not a prvalue nor can it be converted into=
=20
one.
What you propose is forcing the second scenario, even when the code is=20
actually written like the first.
With this, the lazy "expression" cannot return a prvalue.
And I also don't want the compiler to choose between the two scenarii=20
depending on the number of uses of the lazy expression.
In fact, it will not be possible in general to know statically if the=20
expression will be used several times.
If you say undefined behaviour if used more than once, you can guarantee=20
that the lazy expression "returns" a prvalue and copy ellision will be=20
applied in the first case in every single situation, while still allowing=
=20
people to store it in a local variable and reuse this local variable=20
instead.
As a consequence, you will not be able to use &a() if the parameter is []=
=20
-> int a. But you will be able to do that if it is defined as [] -> const=
=20
int& a.
Also, if all temporaries of the lazy expression are trivial (trivially=20
destructible is enough), you could even save the flag telling it has=20
already been executed, and skip proper destruction of the temporaries. This=
=20
will be a big gain if the construction of the returned object can throw,=20
for instance.
This point is possible only if you don't define multiple evaluations of the=
=20
lazy expression.
> I think that for `[]->int a` we should have `&a() =3D=3D &a()` this will =
be=20
> same temporary variable that is allocated on caller stack.=20
>
if the lazy exporession "returns" a prvalue, you will not be able to call=
=20
&a() at all.
=20
>
> Only problem I see is order in with temporaries will be destroyed,=20
> probably it will be fixed one not depending on order in with params was=
=20
> call. Adding info about order will only increase implementation complexit=
y=20
> and cost of each call of this parameter. This part I would leave UB.
>
>
Actually, this part is not a problem and can be fully defined: if the lazy=
=20
expression throws the constructed temporaries will be destroyed in reverse=
=20
order, and then exception is forwarded to the callee.
If there are other lazy parameters, either they have not been executed=20
already and no object needs to be destroyed, or they have been successfully=
=20
executed and their temporaries will be destroyed by the caller (not the=20
calle) in reverse order (that is known by the caller) per lazy parameter.
The destruction order for different lazy parameter could be unspecified. I=
=20
don't see any reason we should try to force an order between completely=20
unrelated objects.
--=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/8e4a6908-d7a6-4896-8820-79de09f5b07c%40isocpp.or=
g.
------=_Part_132_1369977418.1527713966313
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le mercredi 30 mai 2018 22:13:21 UTC+2, Marcin Jac=
zewski a =C3=A9crit=C2=A0:<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"><br><br>On Wednesday, May 30, 2018 at 9:32:43 PM UTC+2, <a>flo=
ria...@gmail.com</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margi=
n:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><br><br>Le mercredi 30 mai 2018 21:06:12 UTC+2, Marcin Jaczewski a=
=C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin:0;margi=
n-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
<br><br>On Wednesday, May 30, 2018 at 7:39:38 PM UTC+2, Nicol Bolas wrote:<=
br>><br>>=C2=A0=C2=A0=C2=A0 On Wednesday, May 30, 2018 at 1:00:10 PM =
UTC-4, <a>floria...@gmail.com</a> wrote:<br>><br>> =C2=A0 >=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0 Le mercredi 30 mai 2018 18:47:14 UTC+2, <a>floria.=
...@gmail.com</a> a =C3=A9crit :<br>><br>><br>>=C2=A0=C2=A0=C2=A0 I=
don't think this answered the question I asked, so allow me to provide=
some code:<br>><br>>=C2=A0=C2=A0=C2=A0 void foo([]->std::string s=
tr)<br>>=C2=A0=C2=A0=C2=A0 {<br>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try {=
auto str2 =3D str(); }<br>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 catch(...)<br=
>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 {<br>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
}<br>>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 //bottom of code<br>>=C2=A0=C2=
=A0=C2=A0 }<br><div>></div><div> > =C2=A0 foo(std::string("foo&q=
uot;) + func_that_throws() + std::string("bar"));</div>><br>&g=
t; =C2=A0 OK, the captured expression contains several temporaries.<br>>=
<br>>=C2=A0=C2=A0=C2=A0
Let's say that the evaluation order for + for this implementation does=
=20
things purely left-to-right. So it creates a temporary `string("foo&qu=
ot;)`.=20
It then gets a temporary `string` from `func_that_throws()` and does=20
`operator+` on them, resulting in a prvalue. That prvalue will then=20
manifest a temporary to be added to the temporary `string("bar")`=
..<br>><br>>=C2=A0=C2=A0=C2=A0
Now of course, `func_that_throws` is so named because it throws. So my=20
question is this: given the above evaluation order, which temporaries=20
are still alive when you reach that `catch` statement?<br>><br>>=C2=
=A0=C2=A0=C2=A0
The only correct answer I can see is "none of them". And if that=
's the=20
case, why is it OK for those temporaries to be destroyed if you reach=20
"bottom of code" through the `catch` statement and not through=20
non-exception execution?<br>><br>>=C2=A0=C2=A0=C2=A0 And if some of t=
hose=20
temporaries are alive and some are not... how does that even work? Is=20
there a boolean for each temporary in the captured expression to say if=20
it's alive?<br><br><br>IMHO behavior of this two lines (with `z1` and `=
z2`) should be indistinguishable:<br><div style=3D"background-color:rgb(250=
,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px=
"><code><div><span style=3D"color:#008">int</span><span style=3D"color:#000=
"> foo</span><span style=3D"color:#660">(</span><span style=3D"color:#008">=
bool</span><span style=3D"color:#000"> t</span><span style=3D"color:#660">,=
</span><span style=3D"color:#000"> </span><span style=3D"color:#660">[]->=
;</span><span style=3D"color:#008">int</span><span style=3D"color:#000"> a1=
</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#660">[]-></span><span style=3D"color:#008">int</=
span><span style=3D"color:#000"> a2</span><span style=3D"color:#660">){</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#008">return</sp=
an><span style=3D"color:#000"> t </span><span style=3D"color:#660">?</span>=
<span style=3D"color:#000"> a1</span><span style=3D"color:#660">()</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span s=
tyle=3D"color:#000"> a2</span><span style=3D"color:#660">();</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br><br></span><span style=3D"color:#008">auto</span><span =
style=3D"color:#000"> z1 </span><span style=3D"color:#660">=3D</span><span =
style=3D"color:#000"> p </span><span style=3D"color:#660">?</span><span sty=
le=3D"color:#000"> bar</span><span style=3D"color:#660">()</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#660">:</span><span style=3D"=
color:#000"> baz</span><span style=3D"color:#660">();</span><span style=3D"=
color:#000"><br></span><span style=3D"color:#008">auto</span><span style=3D=
"color:#000"> z2 </span><span style=3D"color:#660">=3D</span><span style=3D=
"color:#000"> foo</span><span style=3D"color:#660">(</span><span style=3D"c=
olor:#000">p</span><span style=3D"color:#660">,</span><span style=3D"color:=
#000"> bar</span><span style=3D"color:#660">(),</span><span style=3D"color:=
#000"> baz</span><span style=3D"color:#660">());</span></div></code></div>o=
r<br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,1=
87,187);border-style:solid;border-width:1px"><code><div><span style=3D"colo=
r:#008">bool</span><span style=3D"color:#000"> test</span><span style=3D"co=
lor:#660">([]-></span><span style=3D"color:#008">bool</span><span style=
=3D"color:#000"> a1</span><span style=3D"color:#660">,</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">[]-></span><span style=
=3D"color:#008">bool</span><span style=3D"color:#000"> a2</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">[]-></span><span style=3D"color:#008">bool</span><span style=
=3D"color:#000"> a3</span><span style=3D"color:#660">)</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#008">return</span><span style=3D"colo=
r:#000"> a1</span><span style=3D"color:#660">()</span><span style=3D"color:=
#000"> </span><span style=3D"color:#660">&&</span><span style=3D"co=
lor:#000"> a2</span><span style=3D"color:#660">()</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#660">&&</span><span style=3D"=
color:#000"> a3</span><span style=3D"color:#660">();</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660">}</span><span style=3D"color:=
#000"><br><br></span><span style=3D"color:#008">auto</span><span style=3D"c=
olor:#000"> z1 </span><span style=3D"color:#660">=3D</span><span style=3D"c=
olor:#000"> foo</span><span style=3D"color:#660">()</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#660">&&</span><span style=
=3D"color:#000"> bar</span><span style=3D"color:#660">()</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">&&</span><span s=
tyle=3D"color:#000"> baz</span><span style=3D"color:#660">();</span><span s=
tyle=3D"color:#000"><br></span><span style=3D"color:#008">auto</span><span =
style=3D"color:#000"> z2 </span><span style=3D"color:#660">=3D</span><span =
style=3D"color:#000"> test</span><span style=3D"color:#660">(</span><span s=
tyle=3D"color:#000">foo</span><span style=3D"color:#660">(),</span><span st=
yle=3D"color:#000"> bar</span><span style=3D"color:#660">(),</span><span st=
yle=3D"color:#000"> baz</span><span style=3D"color:#660">());</span></div><=
/code></div><br></div></blockquote><div>Yes, if those are different, then t=
he feature has failed its purpose.<br></div><div>=C2=A0</div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #cc=
c solid;padding-left:1ex"><div dir=3D"ltr">Overall
I think that parameter could be multiple times evaluated but it will=20
return same value every time, storage for it will be from caller and=20
caller will store flag that will check if paramere was aready evaluated.<br=
></div></blockquote><div><br></div><div>I don't think it is a good idea=
to allow multiple evaluations of the expression. If you need to reuse the =
result, you can store it in a local variable and reuse it as many times as =
you want.</div><div>The problem I see with this automatic local variable st=
ored/cached is: how would you enforce RVO to construct the object in-place =
(one of the biggest feature of this proposal).</div><div><br></div><div>I w=
ould say we should not enforce a single call by checking a flag for instanc=
e, but make it undefined behaviour.</div><div>This would usually be constru=
cting the object multiple times without properly destroying them.<br></div>=
<div>=C2=A0</div></div></blockquote><div><br></div><div>I use wrong words, =
when you call `p()` and then you again call `p()` then code will be call on=
ly once. This will have cost but only one `if`, value that store this flag =
is already need in current C++.</div><div>If function get inlined this cost=
could be removed because in some cases we could <span>infer from context w=
hat temporaries live. This is probably small cost compare to UB.<br></span>=
</div></div></blockquote><div><br></div><div>I understood what you said, an=
d I keep thinking that's not a good idea.<code></code></div><div><div s=
tyle=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 1=
87); border-style: solid; border-width: 1px; overflow-wrap: break-word;" cl=
ass=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subprettyprin=
t"><span style=3D"color: #000;" class=3D"styled-by-prettify">std</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">array</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: =
#008;" class=3D"styled-by-prettify">int</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"styled-by=
-prettify">1000</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">>*</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
create_big</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>([]</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">-></span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">array</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #008;"=
class=3D"styled-by-prettify">int</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: #066;" class=3D"styled-by-pret=
tify">1000</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
></span><span style=3D"color: #000;" class=3D"styled-by-prettify"> a</sp=
an><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: #0=
00;" class=3D"styled-by-prettify"><br>=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: #008;" class=
=3D"styled-by-prettify">new</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> std</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">array</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&l=
t;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #066;" class=3D"styled-by-prettify">1000</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">>(</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"st=
yled-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-p=
rettify">//copy ellision: a() is a prvalue</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br><br></span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
*</span><span style=3D"color: #000;" class=3D"styled-by-prettify">p </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> create_big</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">({</span><span style=3D=
"color: #066;" class=3D"styled-by-prettify">1</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"sty=
led-by-prettify">2</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">,</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 st=
yle=3D"color: #066;" class=3D"styled-by-prettify">1000</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>Lazy par=
ameter here allows to defer the creation of the array until the point where=
its final storage is known, and "RVO" can be applied to ellide t=
he copy as the lazy expression "returns" a prvalue.</div><div><br=
></div><div>But now, if you do:<code></code></div><div><div style=3D"backgr=
ound-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-st=
yle: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyp=
rint"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #000;" class=3D"styled-by-prettify">std</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">array</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify"><</span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">int</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">1000=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">>*</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> create_big</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">([]</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">-></span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify">array</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify"><</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">int</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"styled-by-prettify">1000</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">></span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> a</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"colo=
r: #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 std</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">array</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify"><</span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">int</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #066;" class=3D"styled-by-prettify">1000</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">></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;" cl=
ass=3D"styled-by-prettify">a</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">());</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettif=
y">// copy ellision</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">return</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">new=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">array</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">int</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"styl=
ed-by-prettify">1000</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">>(</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"> </span><spa=
n style=3D"color: #800;" class=3D"styled-by-prettify">// no copy ellision h=
ere, b is not a prvalue</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">auto=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">*</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">p </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> create_big</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">({</span><span style=3D"color: #066;" clas=
s=3D"styled-by-prettify">1</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">2<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</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"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066=
;" class=3D"styled-by-prettify">1000</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">});</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br></span></div></code></div></div><div>The copy is not=
ellided as b is not a prvalue nor can it be converted into one.</div><div>=
What you propose is forcing the second scenario, even when the code is actu=
ally written like the first.</div><div>With this, the lazy "expression=
" cannot return a prvalue.<br></div><div><br></div><div>And I also don=
't want the compiler to choose between the two scenarii depending on th=
e number of uses of the lazy expression.</div><div>In fact, it will not be =
possible in general to know statically if the expression will be used sever=
al times.</div><div><br></div><div>If you say undefined behaviour if used m=
ore than once, you can guarantee that the lazy expression "returns&quo=
t; a prvalue and copy ellision will be applied in the first case in every s=
ingle situation, while still allowing people to store it in a local variabl=
e and reuse this local variable instead.<br></div><div>As a consequence, yo=
u will not be able to use <span style=3D"font-family: courier new, monospac=
e;">&a()</span> if the parameter is <span style=3D"font-family: courier=
new, monospace;">[] -> int a</span>. But you will be able to do that if=
it is defined as <span style=3D"font-family: courier new, monospace;">[] -=
> const int& a</span>.</div><div><br></div><div>Also, if all tempora=
ries of the lazy expression are trivial (trivially destructible is enough),=
you could even save the flag telling it has already been executed, and ski=
p proper destruction of the temporaries. This will be a big gain if the con=
struction of the returned object can throw, for instance.</div><div>This po=
int is possible only if you don't define multiple evaluations of the la=
zy expression.<br></div><div><br></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div dir=3D"ltr"><div><span></span></div><div><br></div><div>I thi=
nk that for `[]->int a` we should have `&a() =3D=3D &a()` this w=
ill be same temporary variable that is allocated on caller stack. <br></div=
></div></blockquote><div><br></div><div>if the lazy exporession "retur=
ns" a prvalue, you will not be able to call <span style=3D"font-family=
: courier new, monospace;">&a()</span> at all.<br></div><div>=C2=A0</di=
v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div>=
<div><br></div><div>Only problem I see is order in with <span>temporaries <=
/span>will be destroyed, probably it will be fixed one not depending on ord=
er in with params was call. Adding info about order will only increase impl=
ementation complexity and cost of each call of this parameter. This part I =
would leave UB.<br></div><div dir=3D"ltr"><br></div></div></blockquote><div=
><br></div><div>Actually, this part is not a problem and can be fully defin=
ed: if the lazy expression throws the constructed temporaries will be destr=
oyed in reverse order, and then exception is forwarded to the callee.</div>=
<div>If there are other lazy parameters, either they have not been executed=
already and no object needs to be destroyed, or they have been successfull=
y executed and their temporaries will be destroyed by the caller (not the c=
alle) in reverse order (that is known by the caller) per lazy parameter.</d=
iv><div><br></div><div>The destruction order for different lazy parameter c=
ould be unspecified. I don't see any reason we should try to force an o=
rder between completely unrelated objects.<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/8e4a6908-d7a6-4896-8820-79de09f5b07c%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/8e4a6908-d7a6-4896-8820-79de09f5b07c=
%40isocpp.org</a>.<br />
------=_Part_132_1369977418.1527713966313--
------=_Part_131_1276315013.1527713966312--
.
Author: inkwizytoryankes@gmail.com
Date: Wed, 30 May 2018 15:20:07 -0700 (PDT)
Raw View
------=_Part_567_672727723.1527718807532
Content-Type: multipart/alternative;
boundary="----=_Part_568_150259340.1527718807533"
------=_Part_568_150259340.1527718807533
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Wednesday, May 30, 2018 at 10:59:26 PM UTC+2, floria...@gmail.com wrote:
>
>
>
> Le mercredi 30 mai 2018 22:13:21 UTC+2, Marcin Jaczewski a =C3=A9crit :
>>
>>
>>
>> On Wednesday, May 30, 2018 at 9:32:43 PM UTC+2, floria...@gmail.com=20
>> wrote:
>>>
>>>
>>>
>>> Le mercredi 30 mai 2018 21:06:12 UTC+2, Marcin Jaczewski a =C3=A9crit :
>>>>
>>>>
>>>>
>>>> IMHO behavior of this two lines (with `z1` and `z2`) should be=20
>>>> indistinguishable:
>>>> int foo(bool t, []->int a1, []->int a2){ return t ? a1() : a2(); }
>>>>
>>>> auto z1 =3D p ? bar() : baz();
>>>> auto z2 =3D foo(p, bar(), baz());
>>>> or
>>>> bool test([]->bool a1, []->bool a2, []->bool a3) { return a1() && a2()=
=20
>>>> && a3(); }
>>>>
>>>> auto z1 =3D foo() && bar() && baz();
>>>> auto z2 =3D test(foo(), bar(), baz());
>>>>
>>>> Yes, if those are different, then the feature has failed its purpose.
>>> =20
>>>
>>>> Overall I think that parameter could be multiple times evaluated but i=
t=20
>>>> will return same value every time, storage for it will be from caller =
and=20
>>>> caller will store flag that will check if paramere was aready evaluate=
d.
>>>>
>>>
>>> I don't think it is a good idea to allow multiple evaluations of the=20
>>> expression. If you need to reuse the result, you can store it in a loca=
l=20
>>> variable and reuse it as many times as you want.
>>> The problem I see with this automatic local variable stored/cached is:=
=20
>>> how would you enforce RVO to construct the object in-place (one of the=
=20
>>> biggest feature of this proposal).
>>>
>>> I would say we should not enforce a single call by checking a flag for=
=20
>>> instance, but make it undefined behaviour.
>>> This would usually be constructing the object multiple times without=20
>>> properly destroying them.
>>> =20
>>>
>>
>> I use wrong words, when you call `p()` and then you again call `p()` the=
n=20
>> code will be call only once. This will have cost but only one `if`, valu=
e=20
>> that store this flag is already need in current C++.
>> If function get inlined this cost could be removed because in some cases=
=20
>> we could infer from context what temporaries live. This is probably=20
>> small cost compare to UB.
>>
>
> I understood what you said, and I keep thinking that's not a good idea.
> std::array<int, 1000>* create_big([] -> std::array<int, 1000> a) {
> return new std::array<int, 1000>(a()); //copy ellision: a() is a prvalu=
e
> }
>
> auto *p =3D create_big({1, 2, ..., 1000});
> Lazy parameter here allows to defer the creation of the array until the=
=20
> point where its final storage is known, and "RVO" can be applied to ellid=
e=20
> the copy as the lazy expression "returns" a prvalue.
>
> But now, if you do:
> std::array<int, 1000>* create_big([] -> std::array<int, 1000> a) {
> std::array<int, 1000> b(a()); // copy ellision
> return new std::array<int, 1000>(b); // no copy ellision here, b is not=
=20
> a prvalue
> }
>
> auto *p =3D create_big({1, 2, ..., 1000});
> The copy is not ellided as b is not a prvalue nor can it be converted int=
o=20
> one.
> What you propose is forcing the second scenario, even when the code is=20
> actually written like the first.
> With this, the lazy "expression" cannot return a prvalue.
>
> And I also don't want the compiler to choose between the two scenarii=20
> depending on the number of uses of the lazy expression.
> In fact, it will not be possible in general to know statically if the=20
> expression will be used several times.
>
> =20
Good point. Then to have best performance we will need have UB. With this=
=20
for simplicity my "retry" feature should be scraped too because it to close=
=20
to UB situation even if in itself could be easy implemented.
Rule will be simple: parameter can be only called onece or less.
If UB is not desired then exception could be thrown as alternative solution=
=20
for repeated calls.
--=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/cfac6d36-d1dc-4e71-805c-8f78eebd1275%40isocpp.or=
g.
------=_Part_568_150259340.1527718807533
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, May 30, 2018 at 10:59:26 PM UTC+2, f=
loria...@gmail.com 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"><br><br>Le mercredi 30 mai 2018 22:13:21 UTC+2, Marcin Jaczewsk=
i a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin:0;ma=
rgin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"lt=
r"><br><br>On Wednesday, May 30, 2018 at 9:32:43 PM UTC+2, <a>floria...@gma=
il.com</a> 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"><=
br><br>Le mercredi 30 mai 2018 21:06:12 UTC+2, Marcin Jaczewski a =C3=A9cri=
t=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><br>IM=
HO behavior of this two lines (with `z1` and `z2`) should be indistinguisha=
ble:<br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(18=
7,187,187);border-style:solid;border-width:1px"><code><div><span style=3D"c=
olor:#008">int</span><span style=3D"color:#000"> foo</span><span style=3D"c=
olor:#660">(</span><span style=3D"color:#008">bool</span><span style=3D"col=
or:#000"> t</span><span style=3D"color:#660">,</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">[]-></span><span style=3D"color:=
#008">int</span><span style=3D"color:#000"> a1</span><span style=3D"color:#=
660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
[]-></span><span style=3D"color:#008">int</span><span style=3D"color:#00=
0"> a2</span><span style=3D"color:#660">){</span><span style=3D"color:#000"=
> </span><span style=3D"color:#008">return</span><span style=3D"color:#000"=
> t </span><span style=3D"color:#660">?</span><span style=3D"color:#000"> a=
1</span><span style=3D"color:#660">()</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">:</span><span style=3D"color:#000"> a2</span=
><span style=3D"color:#660">();</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#660">}</span><span style=3D"color:#000"><br><br></span>=
<span style=3D"color:#008">auto</span><span style=3D"color:#000"> z1 </span=
><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> p </span>=
<span style=3D"color:#660">?</span><span style=3D"color:#000"> bar</span><s=
pan style=3D"color:#660">()</span><span style=3D"color:#000"> </span><span =
style=3D"color:#660">:</span><span style=3D"color:#000"> baz</span><span st=
yle=3D"color:#660">();</span><span style=3D"color:#000"><br></span><span st=
yle=3D"color:#008">auto</span><span style=3D"color:#000"> z2 </span><span s=
tyle=3D"color:#660">=3D</span><span style=3D"color:#000"> foo</span><span s=
tyle=3D"color:#660">(</span><span style=3D"color:#000">p</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> bar</span><span style=
=3D"color:#660">(),</span><span style=3D"color:#000"> baz</span><span style=
=3D"color:#660">());</span></div></code></div>or<br><div style=3D"backgroun=
d-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;b=
order-width:1px"><code><div><span style=3D"color:#008">bool</span><span sty=
le=3D"color:#000"> test</span><span style=3D"color:#660">([]-></span><sp=
an style=3D"color:#008">bool</span><span style=3D"color:#000"> a1</span><sp=
an style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#660">[]-></span><span style=3D"color:#008">bool</span><spa=
n style=3D"color:#000"> a2</span><span style=3D"color:#660">,</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#660">[]-></span><span =
style=3D"color:#008">bool</span><span style=3D"color:#000"> a3</span><span =
style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#008">return</span><span style=3D"color:#000"> a1</span><span style=3D=
"color:#660">()</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#660">&&</span><span style=3D"color:#000"> a2</span><span style=
=3D"color:#660">()</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">&&</span><span style=3D"color:#000"> a3</span><span sty=
le=3D"color:#660">();</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">}</span><span style=3D"color:#000"><br><br></span><span sty=
le=3D"color:#008">auto</span><span style=3D"color:#000"> z1 </span><span st=
yle=3D"color:#660">=3D</span><span style=3D"color:#000"> foo</span><span st=
yle=3D"color:#660">()</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">&&</span><span style=3D"color:#000"> bar</span><spa=
n style=3D"color:#660">()</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#660">&&</span><span style=3D"color:#000"> baz</span><=
span style=3D"color:#660">();</span><span style=3D"color:#000"><br></span><=
span style=3D"color:#008">auto</span><span style=3D"color:#000"> z2 </span>=
<span style=3D"color:#660">=3D</span><span style=3D"color:#000"> test</span=
><span style=3D"color:#660">(</span><span style=3D"color:#000">foo</span><s=
pan style=3D"color:#660">(),</span><span style=3D"color:#000"> bar</span><s=
pan style=3D"color:#660">(),</span><span style=3D"color:#000"> baz</span><s=
pan style=3D"color:#660">());</span></div></code></div><br></div></blockquo=
te><div>Yes, if those are different, then the feature has failed its purpos=
e.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div d=
ir=3D"ltr">Overall
I think that parameter could be multiple times evaluated but it will=20
return same value every time, storage for it will be from caller and=20
caller will store flag that will check if paramere was aready evaluated.<br=
></div></blockquote><div><br></div><div>I don't think it is a good idea=
to allow multiple evaluations of the expression. If you need to reuse the =
result, you can store it in a local variable and reuse it as many times as =
you want.</div><div>The problem I see with this automatic local variable st=
ored/cached is: how would you enforce RVO to construct the object in-place =
(one of the biggest feature of this proposal).</div><div><br></div><div>I w=
ould say we should not enforce a single call by checking a flag for instanc=
e, but make it undefined behaviour.</div><div>This would usually be constru=
cting the object multiple times without properly destroying them.<br></div>=
<div>=C2=A0</div></div></blockquote><div><br></div><div>I use wrong words, =
when you call `p()` and then you again call `p()` then code will be call on=
ly once. This will have cost but only one `if`, value that store this flag =
is already need in current C++.</div><div>If function get inlined this cost=
could be removed because in some cases we could <span>infer from context w=
hat temporaries live. This is probably small cost compare to UB.<br></span>=
</div></div></blockquote><div><br></div><div>I understood what you said, an=
d I keep thinking that's not a good idea.<code></code></div><div><div s=
tyle=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bor=
der-style:solid;border-width:1px"><code><div><span style=3D"color:#000">std=
</span><span style=3D"color:#660">::</span><span style=3D"color:#000">array=
</span><span style=3D"color:#660"><</span><span style=3D"color:#008">int=
</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#066">1000</span><span style=3D"color:#660">>*</s=
pan><span style=3D"color:#000"> create_big</span><span style=3D"color:#660"=
>([]</span><span style=3D"color:#000"> </span><span style=3D"color:#660">-&=
gt;</span><span style=3D"color:#000"> std</span><span style=3D"color:#660">=
::</span><span style=3D"color:#000">array</span><span style=3D"color:#660">=
<</span><span style=3D"color:#008">int</span><span style=3D"color:#660">=
,</span><span style=3D"color:#000"> </span><span style=3D"color:#066">1000<=
/span><span style=3D"color:#660">></span><span style=3D"color:#000"> a</=
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 </=
span><span style=3D"color:#008">return</span><span style=3D"color:#000"> </=
span><span style=3D"color:#008">new</span><span style=3D"color:#000"> std</=
span><span style=3D"color:#660">::</span><span style=3D"color:#000">array</=
span><span style=3D"color:#660"><</span><span style=3D"color:#008">int</=
span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#066">1000</span><span style=3D"color:#660">>(</spa=
n><span style=3D"color:#000">a</span><span style=3D"color:#660">());</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#800">//copy ellisi=
on: a() is a prvalue</span><span style=3D"color:#000"><br></span><span styl=
e=3D"color:#660">}</span><span style=3D"color:#000"><br><br></span><span st=
yle=3D"color:#008">auto</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">*</span><span style=3D"color:#000">p </span><span style=3D=
"color:#660">=3D</span><span style=3D"color:#000"> create_big</span><span s=
tyle=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"c=
olor:#066">2</span><span style=3D"color:#660">,</span><span style=3D"color:=
#000"> </span><span style=3D"color:#660">...,</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#066">1000</span><span style=3D"color:#660=
">});</span><span style=3D"color:#000"><br></span></div></code></div>Lazy p=
arameter here allows to defer the creation of the array until the point whe=
re its final storage is known, and "RVO" can be applied to ellide=
the copy as the lazy expression "returns" a prvalue.</div><div><=
br></div><div>But now, if you do:<code></code></div><div><div style=3D"back=
ground-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:so=
lid;border-width:1px"><code><div><span style=3D"color:#000">std</span><span=
style=3D"color:#660">::</span><span style=3D"color:#000">array</span><span=
style=3D"color:#660"><</span><span style=3D"color:#008">int</span><span=
style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#066">1000</span><span style=3D"color:#660">>*</span><span st=
yle=3D"color:#000"> create_big</span><span style=3D"color:#660">([]</span><=
span style=3D"color:#000"> </span><span style=3D"color:#660">-></span><s=
pan style=3D"color:#000"> std</span><span style=3D"color:#660">::</span><sp=
an style=3D"color:#000">array</span><span style=3D"color:#660"><</span><=
span style=3D"color:#008">int</span><span style=3D"color:#660">,</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#066">1000</span><span =
style=3D"color:#660">></span><span style=3D"color:#000"> a</span><span s=
tyle=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 std</span><sp=
an style=3D"color:#660">::</span><span style=3D"color:#000">array</span><sp=
an style=3D"color:#660"><</span><span style=3D"color:#008">int</span><sp=
an style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#066">1000</span><span style=3D"color:#660">></span><span s=
tyle=3D"color:#000"> b</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">a</span><span style=3D"color:#660">());</span><span style=
=3D"color:#000"> </span><span style=3D"color:#800">// copy ellision</span><=
span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">retu=
rn</span><span style=3D"color:#000"> </span><span style=3D"color:#008">new<=
/span><span style=3D"color:#000"> std</span><span style=3D"color:#660">::</=
span><span style=3D"color:#000">array</span><span style=3D"color:#660"><=
</span><span style=3D"color:#008">int</span><span style=3D"color:#660">,</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#066">1000</spa=
n><span style=3D"color:#660">>(</span><span style=3D"color:#000">b</span=
><span style=3D"color:#660">);</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#800">// no copy ellision here, b is not a prvalue</span>=
<span style=3D"color:#000"><br></span><span style=3D"color:#660">}</span><s=
pan style=3D"color:#000"><br><br></span><span style=3D"color:#008">auto</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#660">*</span><s=
pan style=3D"color:#000">p </span><span style=3D"color:#660">=3D</span><spa=
n style=3D"color:#000"> create_big</span><span style=3D"color:#660">({</spa=
n><span style=3D"color:#066">1</span><span style=3D"color:#660">,</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#066">2</span><span st=
yle=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">...,</span><span style=3D"color:#000"> </span><span style=
=3D"color:#066">1000</span><span style=3D"color:#660">});</span><span style=
=3D"color:#000"><br></span></div></code></div></div><div>The copy is not el=
lided as b is not a prvalue nor can it be converted into one.</div><div>Wha=
t you propose is forcing the second scenario, even when the code is actuall=
y written like the first.</div><div>With this, the lazy "expression&qu=
ot; cannot return a prvalue.<br></div><div><br></div><div>And I also don=
9;t want the compiler to choose between the two scenarii depending on the n=
umber of uses of the lazy expression.</div><div>In fact, it will not be pos=
sible in general to know statically if the expression will be used several =
times.</div><div><br></div></div></blockquote><div>=C2=A0</div><div>Good po=
int. Then to have best performance we will need have UB. With this for simp=
licity my "retry" feature should be scraped too because it to clo=
se to UB situation even if in itself could be easy implemented.</div><div>R=
ule will be simple: parameter can be only called onece or less.</div><div>I=
f UB is not desired then exception could be thrown as alternative solution =
for repeated calls.<br></div><div><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/cfac6d36-d1dc-4e71-805c-8f78eebd1275%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/cfac6d36-d1dc-4e71-805c-8f78eebd1275=
%40isocpp.org</a>.<br />
------=_Part_568_150259340.1527718807533--
------=_Part_567_672727723.1527718807532--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 30 May 2018 23:37:03 +0100
Raw View
--000000000000d93430056d73fd5c
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Wed, 30 May 2018, 20:16 , <florian.csdt@gmail.com> wrote:
>
>
> Le mercredi 30 mai 2018 20:53:01 UTC+2, Nicol Bolas a =C3=A9crit :
>>
>> On Wednesday, May 30, 2018 at 2:21:57 PM UTC-4, floria...@gmail.com
>> wrote:
>>>
>>> @Nicol: Edward made a good and quick summary.
>>> So in your example, when the throwing function throws, the lazy
>>> expression destroys the two strings already constructed (with classical
>>> exception handling for example), does not set the magic flag to true, a=
nd
>>> forward the exception to the callee (foo in your example).
>>> So at the beginning of the catch, no temporaries are alive.
>>>
>>> Then when the callee has finished, the caller will check the flag: it
>>> will still be false as it has not been set to true by the lazy expressi=
on,
>>> and will therefore not destroy the temporaries.
>>>
>>> After the execution of the lazy expression (but in still in the callee)=
,
>>> either all temporaries are alive (and the caller will need to destroy
>>> them), or none.
>>>
>>
>> So, why is it OK for those temporaries to be destroyed if there's an
>> exception, but they must be extended to outside of the evaluator if ther=
e
>> is no exception? That's my point: if it's OK in one case for the
>> temporaries to no longer exist, then it ought to be OK in general.
>>
>
> That's exactly like a non lazy expression: temporaries are destroyed at
> the end of the scope. If there is an exception, the scope ends earlier.
> I think I realise what your problem is: the lazy scope can outlive the
> scope triggering its execution. And yes, that's new.
>
>
>>
>> If the goal is to make lazy expression evaluation work like non-lazy
>> evaluation, then this design fails. If an expression throws and it wasn'=
t
>> lazily captured, the caller is the first one who sees it (since they're =
the
>> ones who evaluated it). If it was lazily captured, the function evaluati=
ng
>> the expression can swallow it, such that the caller never sees it.
>>
>
> True, the exception will not be seen by the callee if the expression is
> not lazy. And if the expression is lazy, the callee can swallow the
> exception. But that would be the case with any proposal allowing some kin=
d
> of lazy/delayed/deferred expression.
> Even your proposal to make it as if it was copy pasted into the callee
> will change the exception handler order. Or with callables.
>
>
>>
>> That is, the same logic you use to say that the code providing the
>> expression ought to be providing storage for it is the same logic that
>> could be used to say that the throw ought to originate in the *caller*,
>> just like it would otherwise appear to. That is, if a lazy expression
>> throws, the code between the evaluator and the provider of the expressio=
n
>> unrolls immediately, and `catch` statements are only considered from the
>> site of the one who originally provided the expression.
>>
>
> That would be a possibility, but I'm not sure we want that. We would need
> to find some use cases for both way to handle exceptions.
> The problem I see with that is: in a function taking a lazy parameter, yo=
u
> would not be able to write an exception handler without relying on
> destructors (or std::scope_exit).
> It would not be possible to use a try-catch even if the catch catches
> anything and forwards the exception.
>
>
>>
>> Concerning the scope, I agree with you that in the lazy case, the scope
>>> will start after, but it will still be the same (access to the same dat=
a,
>>> same behavior regarding exceptions) as the non-lazy expression scope.
>>> The difference is: a lazy expression scope might/will outlive the scope
>>> that triggered its execution, but the rest is exactly the same.
>>>
>>
>> Everything is the same... except for the parts where it is different. Bu=
t
>> that means it's not the same. This would be the first time that the
>> creation of an automatic object extends beyond the block that invokes th=
at
>> creation.
>>
>> You can't say that isn't new.
>>
>
> I agree, it's new. but it's not as different as you might think. In the
> implementation, it is very different, but coneptually (at the language
> level) it is not that different.
> For me, as I already said, the difference is the destruction can outlive
> the scope where it has been started.
> Another way to see it is: the scope start point is delayed and will be
> triggered by another (inner) scope.
>
And with the coroutines TS we will have far more complicated overlapping
scopes allocating stack space for themselves. At least here the stack
requirement of the innermost scope is known allowing it to use fixed space
allocated by the outermost scope.
You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/=
unsubscribe
> .
> To unsubscribe from this group and all its topics, 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/6b7ba07f-33d=
f-492c-a9fb-24d9c04662af%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6b7ba07f-33=
df-492c-a9fb-24d9c04662af%40isocpp.org?utm_medium=3Demail&utm_source=3Dfoot=
er>
> .
>
--=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/CAJnLdOacc%2B%2B6VtodQH-2bgJxTOt9e3MC5hm8uz-gSZe=
weYRe-A%40mail.gmail.com.
--000000000000d93430056d73fd5c
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"auto"><div><br><br><div class=3D"gmail_quote"><div dir=3D"ltr">=
On Wed, 30 May 2018, 20:16 , <<a href=3D"mailto:florian.csdt@gmail.com">=
florian.csdt@gmail.com</a>> wrote:<br></div><blockquote class=3D"gmail_q=
uote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1e=
x"><div dir=3D"ltr"><br><br>Le mercredi 30 mai 2018 20:53:01 UTC+2, Nicol B=
olas a =C3=A9crit=C2=A0:<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">On Wednesday, May 30, 2018 at 2:21:57 PM UTC-4, <a rel=3D"noreferrer"=
>floria...@gmail.com</a> wrote:<blockquote class=3D"gmail_quote" style=3D"m=
argin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div=
dir=3D"ltr">@Nicol: Edward made a good and quick summary.<br>So in your ex=
ample, when the throwing function throws, the lazy expression destroys the =
two strings already constructed (with classical exception handling for exam=
ple), does not set the magic flag to true, and forward the exception to the=
callee (foo in your example).<br>So at the beginning of the catch, no temp=
oraries are alive.<br><br>Then when the callee has finished, the caller wil=
l check the flag: it will still be false as it has not been set to true by =
the lazy expression, and will therefore not destroy the temporaries.<br><br=
>After the execution of the lazy expression (but in still in the callee), e=
ither all temporaries are alive (and the caller will need to destroy them),=
or none.<br></div></blockquote><div><br></div><div>So, why is it OK for th=
ose temporaries to be destroyed if there's an exception, but they must =
be extended to outside of the evaluator if there is no exception? That'=
s my point: if it's OK in one case for the temporaries to no longer exi=
st, then it ought to be OK in general.<br></div></div></blockquote><div><br=
></div><div>That's exactly like a non lazy expression: temporaries are =
destroyed at the end of the scope. If there is an exception, the scope ends=
earlier.</div><div>I think I realise what your problem is: the lazy scope =
can outlive the scope triggering its execution. And yes, that's new.<br=
></div><div>=C2=A0</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></div><div><br></div><div>If the goal is to make lazy expression=
evaluation work like non-lazy evaluation, then this design fails. If an ex=
pression throws and it wasn't lazily captured, the caller is the first =
one who sees it (since they're the ones who evaluated it). If it was la=
zily captured, the function evaluating the expression can swallow it, such =
that the caller never sees it.</div></div></blockquote><div><br></div><div>=
True, the exception will not be seen by the callee if the expression is not=
lazy. And if the expression is lazy, the callee can swallow the exception.=
But that would be the case with any proposal allowing some kind of lazy/de=
layed/deferred expression.</div><div>Even your proposal to make it as if it=
was copy pasted into the callee will change the exception handler order. O=
r with callables.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quot=
e" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-l=
eft:1ex"><div dir=3D"ltr"><div><br></div><div>That is, the same logic you u=
se to say that the code providing the expression ought to be providing stor=
age for it is the same logic that could be used to say that the throw ought=
to originate in the <i>caller</i>, just like it would otherwise appear to.=
That is, if a lazy expression throws, the code between the evaluator and t=
he provider of the expression unrolls immediately, and `catch` statements a=
re only considered from the site of the one who originally provided the exp=
ression.</div></div></blockquote><div><br></div><div>That would be a possib=
ility, but I'm not sure we want that. We would need to find some use ca=
ses for both way to handle exceptions.</div><div>The problem I see with tha=
t is: in a function taking a lazy parameter, you would not be able to write=
an exception handler without relying on destructors (or std::scope_exit).<=
/div><div>It would not be possible to use a try-catch even if the catch cat=
ches anything and forwards the exception.<br></div><div>=C2=A0</div><blockq=
uote 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><br></div><blockquot=
e class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px=
#ccc solid;padding-left:1ex"><div dir=3D"ltr">Concerning the scope, I agre=
e with you that in the lazy case, the scope will start after, but it will s=
till be the same (access to the same data, same behavior regarding exceptio=
ns) as the non-lazy expression scope.<br>The difference is: a lazy expressi=
on scope might/will outlive the scope that triggered its execution, but the=
rest is exactly the same.<br></div></blockquote><div><br></div><div>Everyt=
hing is the same... except for the parts where it is different. But that me=
ans it's not the same. This would be the first time that the creation o=
f an automatic object extends beyond the block that invokes that creation.<=
/div><div><br></div><div>You can't say that isn't new.<br></div></d=
iv></blockquote><div><br></div><div>I agree, it's new. but it's not=
as different as you might think. In the implementation, it is very differe=
nt, but coneptually (at the language level) it is not that different.</div>=
<div>For me, as I already said, the difference is the destruction can outli=
ve the scope where it has been started.</div><div>Another way to see it is:=
the scope start point is delayed and will be triggered by another (inner) =
scope.</div></div></blockquote></div></div><div dir=3D"auto"><br></div><div=
dir=3D"auto"><br></div><div dir=3D"auto">And with the coroutines TS we wil=
l have far more complicated overlapping scopes allocating stack space for t=
hemselves. At least here the stack requirement of the innermost scope is kn=
own allowing it to use fixed space allocated by the outermost scope.=C2=A0<=
/div><div dir=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gmail_quot=
e"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left=
:1px #ccc solid;padding-left:1ex">
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/unsubscribe" target=3D"_blan=
k" rel=3D"noreferrer">https://groups.google.com/a/isocpp.org/d/topic/std-pr=
oposals/5oUZysJB4HE/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_blank" rel=3D"n=
oreferrer">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank" rel=3D"noreferrer">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/6b7ba07f-33df-492c-a9fb-24d9c04662af%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank" =
rel=3D"noreferrer">https://groups.google.com/a/isocpp.org/d/msgid/std-propo=
sals/6b7ba07f-33df-492c-a9fb-24d9c04662af%40isocpp.org</a>.<br>
</blockquote></div></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/CAJnLdOacc%2B%2B6VtodQH-2bgJxTOt9e3MC=
5hm8uz-gSZeweYRe-A%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdOacc%2B=
%2B6VtodQH-2bgJxTOt9e3MC5hm8uz-gSZeweYRe-A%40mail.gmail.com</a>.<br />
--000000000000d93430056d73fd5c--
.
Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Fri, 1 Jun 2018 15:52:34 -0700 (PDT)
Raw View
------=_Part_13567_1852832150.1527893554555
Content-Type: multipart/alternative;
boundary="----=_Part_13568_1019737665.1527893554556"
------=_Part_13568_1019737665.1527893554556
Content-Type: text/plain; charset="UTF-8"
Considering forwarding of lazy parameters to functions that may or may not
use them it becomes very hard to use them if they can only be evaluated
once, or the code must make copies just in case, which defeats the purpose
of the feature. I don't think that avoiding a copy during initialization is
a motivating purpose which should be allowed to rule the definition,
instead we should focus on being able to mimic the shortcut operators and
operator? and the classical logging scenario. Here is a nasty example:
bool andand([]->bool lhs, []->bool rhs)
{
Log("Performing andand on", lhs, " and ", rhs); // Variadic log with
lazy parameters only evaluated if logging is enabled.
return lhs() && rhs(); // This is UB if logging is enabled!
}
Apart from showing the problems with evaluate once principle this example
rasies a couple of syntactical issues:
1) How do we declare a variadic template with lazy parameters?
2) Is is logical to forward-by-lazy by not using postfix(). If so, how many
of us will add the () by mistake when calling Log, accidentally (but
silently) evaluating the lazy parameter and forwarding the resulting value
as a (very simple) lazy expression to Log?
3) Could it be considered to use postfix [] (empty bracket) to "derefer" a
lazy parameter to make it stand out more from function application?
Personally I still think that you should not have to annotate the use of a
lazy parameter in the called function, just as the value/reference
distinction this is something that the function author will have close to
the top of her head when writing the code. This would nullify the 2) issue
above. Maybe it could be complemented by a template function std::eager()
which makes sure evaluation is done even if forwarding to a function that
may take a lazy parameter. I don't have an example where this would be
important though, it seems a bit backwards.
I think the best would be to view this as a new kind of reference, possibly
using the | token to signify it. That is, it works like a reference, except
that before the first use it is evaluated (using the flag to check this).
As for other references there is no indicating at the usage site, as other
(lvalue) references it is transparently forwarded to subordinate functions
(for example Log in my example). The issue of how to write a template
function has an obvious answer, and, I daresay, there should be no syntax
issues as we have the example of using the & character which as an operator
is parallel to | to indicate a type of reference already.
// Variadic Log with lazy parameters only evaluated if logging is enabled.
template<typename T, typename... Ts> Log(T| head, Ts| tail)
{
if (log_enabled) {
cout << head;
Log(tail...);
}
}
bool andand(bool| lhs, bool| rhs)
{
Log("Performing andand on", lhs, " and ", rhs);
return lhs && rhs;
}
Looking at the big-array-copy scenario, I understand this as a case where a
non-inlined function gets called and you want to redirect the constructor
call of the lazy thunk (creating the by value "return" value) to do its
construction directly in the receiving variable, presuming that, as the
variable type is "big" the ABI will have the caller of the lazy thunk
provide an address to construct the value in. The lazy thunk can use
different constructors at different call sites which is nice in combination
with not having to see the callee source code. This has significant
performance advantage in the case that the value is large and does not have
a lightweight move possibility. Apart from std::array all standard
containers have cheap moves so the usefulness is further reduced compared
to a regular by value parameter which is moved into the destination except
for objects with large C or std arrays. Again: Is this functionality really
so important that it warrants hijacking the original feature at the cost of
making it less useful for its original purpose?
--
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/984d7434-303d-4808-b054-8b116f19e838%40isocpp.org.
------=_Part_13568_1019737665.1527893554556
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Considering forwarding of lazy parameters to functions tha=
t may or may not use them it becomes very hard to use them if they can only=
be evaluated once, or the code must make copies just in case, which defeat=
s the purpose of the feature. I don't think that avoiding a copy during=
initialization is a motivating purpose which should be allowed to rule the=
definition, instead we should focus on being able to mimic the shortcut op=
erators and operator? and the classical logging scenario. Here is a nasty e=
xample:<div><br></div><div class=3D"prettyprint" style=3D"background-color:=
rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid;=
border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><di=
v class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-=
prettify">bool</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> andand</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>([]-></span><span style=3D"color: #008;" class=3D"styled-by-prettify">b=
ool</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> lhs</s=
pan><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"co=
lor: #008;" class=3D"styled-by-prettify">bool</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> rhs</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">{</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #606;" class=3D"styled-=
by-prettify">Log</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">(</span><span style=3D"color: #080;" class=3D"styled-by-prettify">&qu=
ot;Performing andand on"</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> lhs</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: #080;" class=3D"styled-by-prettify">" and &qu=
ot;</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> rhs</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> =C2=A0 </span><span style=
=3D"color: #800;" class=3D"styled-by-prettify">// Variadic log with lazy pa=
rameters only evaluated if logging is enabled.</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"col=
or: #000;" class=3D"styled-by-prettify"> lhs</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">&&</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> rhs</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">();</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> =C2=A0 =C2=A0</span><span style=3D"color: #800;" class=3D"styled-by-pr=
ettify">// This is UB if logging is enabled!</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br><br></span></div></code></div><div><br><br></div><di=
v>Apart from showing the problems with evaluate once principle this example=
rasies a couple of syntactical issues:</div><div><br></div><div>1) How do =
we declare a variadic template with lazy parameters?</div><div>2) Is is log=
ical to forward-by-lazy by not using postfix(). If so, how many of us will =
add the () by mistake when calling Log, accidentally (but silently) evaluat=
ing the lazy parameter and forwarding the resulting value as a (very simple=
) lazy expression to Log?</div><div>3) Could it be considered to use postfi=
x [] (empty bracket) to "derefer" a lazy parameter to make it sta=
nd out more from function application?</div><div><br></div><div>Personally =
I still think that you should not have to annotate the use of a lazy parame=
ter in the called function, just as the value/reference distinction this is=
something that the function author will have close to the top of her head =
when writing the code. This would nullify the 2) issue above. Maybe it coul=
d be complemented by a template function std::eager() which makes sure eval=
uation is done even if forwarding to a function that may take a lazy parame=
ter. I don't have an example where this would be important though, it s=
eems a bit backwards.</div><div><br></div><div>I think the best would be to=
view this as a new kind of reference, possibly using the | token to signif=
y it. That is, it works like a reference, except that before the first use =
it is evaluated (using the flag to check this). As for other references the=
re is no indicating at the usage site, as other (lvalue) references it is t=
ransparently forwarded to subordinate functions (for example Log in my exam=
ple). The issue of how to write a template function has an obvious answer, =
and, I daresay, there should be no syntax issues as we have the example of =
using the & character which as an operator is parallel to | to indicate=
a type of reference already.</div><div><br></div><div class=3D"prettyprint=
" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187=
, 187); border-style: solid; border-width: 1px; word-wrap: break-word;"><co=
de class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color=
: #800;" class=3D"styled-by-prettify">// Variadic Log with lazy parameters =
only evaluated if logging is enabled.</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">template</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify"><</span><span style=3D"color: #008;" class=3D"styled-=
by-prettify">typename</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> T</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: #008;" class=3D"styled-by-prettify">typename</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">...</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #606;" class=3D"styled-by-prettify">Ts</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">></span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"s=
tyled-by-prettify">Log</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">|</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> head</span><sp=
an 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=
: #606;" class=3D"styled-by-prettify">Ts</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">|</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> tail</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><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: #008;" class=3D"styled-by-prettify"=
>if</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">log_enabled</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #66=
0;" 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 cout </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify"><<</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> head</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-by-prettify">Log</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">tail</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></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">bool</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> andand</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">bool</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">|</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> lhs</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: #008;" =
class=3D"styled-by-prettify">bool</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">|</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> rhs</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</spa=
n><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">Log</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span=
style=3D"color: #080;" class=3D"styled-by-prettify">"Performing andan=
d on"</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> lhs</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #080;" class=3D"styled-by-prettify">" and "</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> rhs</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">return</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> lhs </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">&&</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> rhs</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
br></span></div></code></div><div><div><br></div><div>Looking at the big-ar=
ray-copy scenario, I understand this as a case where a non-inlined function=
gets called and you want to redirect the constructor call of the lazy thun=
k (creating the by value "return" value) to do its construction d=
irectly in the receiving variable, presuming that, as the variable type is =
"big" the ABI will have the caller of the lazy thunk provide an a=
ddress to construct the value in. The lazy thunk can use different construc=
tors at different call sites which is nice in combination with not having t=
o see the callee source code. This has significant performance advantage in=
the case that the value is large and does not have a lightweight move poss=
ibility. Apart from std::array all standard containers have cheap moves=C2=
=A0 so the usefulness is further reduced compared to a regular by value par=
ameter which is moved into the destination except for objects with large C =
or std arrays. Again: Is this functionality really so important that it war=
rants hijacking the original feature at the cost of making it less useful f=
or its original purpose?</div></div><div><br></div><div><br></div><div><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/984d7434-303d-4808-b054-8b116f19e838%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/984d7434-303d-4808-b054-8b116f19e838=
%40isocpp.org</a>.<br />
------=_Part_13568_1019737665.1527893554556--
------=_Part_13567_1852832150.1527893554555--
.
Author: inkwizytoryankes@gmail.com
Date: Fri, 1 Jun 2018 16:47:46 -0700 (PDT)
Raw View
------=_Part_13779_2125879210.1527896867041
Content-Type: multipart/alternative;
boundary="----=_Part_13780_1771436293.1527896867042"
------=_Part_13780_1771436293.1527896867042
Content-Type: text/plain; charset="UTF-8"
On Saturday, June 2, 2018 at 12:52:34 AM UTC+2, Bengt Gustafsson wrote:
>
> Considering forwarding of lazy parameters to functions that may or may not
> use them it becomes very hard to use them if they can only be evaluated
> once, or the code must make copies just in case, which defeats the purpose
> of the feature. I don't think that avoiding a copy during initialization is
> a motivating purpose which should be allowed to rule the definition,
> instead we should focus on being able to mimic the shortcut operators and
> operator? and the classical logging scenario. Here is a nasty example:
>
> bool andand([]->bool lhs, []->bool rhs)
> {
> Log("Performing andand on", lhs, " and ", rhs); // Variadic log
> with lazy parameters only evaluated if logging is enabled.
> return lhs() && rhs(); // This is UB if logging is enabled!
> }
>
>
>
> Apart from showing the problems with evaluate once principle this example
> rasies a couple of syntactical issues:
>
> 1) How do we declare a variadic template with lazy parameters?
> 2) Is is logical to forward-by-lazy by not using postfix(). If so, how
> many of us will add the () by mistake when calling Log, accidentally (but
> silently) evaluating the lazy parameter and forwarding the resulting value
> as a (very simple) lazy expression to Log?
> 3) Could it be considered to use postfix [] (empty bracket) to "derefer" a
> lazy parameter to make it stand out more from function application?
>
> Personally I still think that you should not have to annotate the use of a
> lazy parameter in the called function, just as the value/reference
> distinction this is something that the function author will have close to
> the top of her head when writing the code. This would nullify the 2) issue
> above. Maybe it could be complemented by a template function std::eager()
> which makes sure evaluation is done even if forwarding to a function that
> may take a lazy parameter. I don't have an example where this would be
> important though, it seems a bit backwards.
>
> I think the best would be to view this as a new kind of reference,
> possibly using the | token to signify it. That is, it works like a
> reference, except that before the first use it is evaluated (using the flag
> to check this). As for other references there is no indicating at the usage
> site, as other (lvalue) references it is transparently forwarded to
> subordinate functions (for example Log in my example). The issue of how to
> write a template function has an obvious answer, and, I daresay, there
> should be no syntax issues as we have the example of using the & character
> which as an operator is parallel to | to indicate a type of reference
> already.
>
> // Variadic Log with lazy parameters only evaluated if logging is enabled.
> template<typename T, typename... Ts> Log(T| head, Ts| tail)
> {
> if (log_enabled) {
> cout << head;
> Log(tail...);
> }
> }
> bool andand(bool| lhs, bool| rhs)
> {
> Log("Performing andand on", lhs, " and ", rhs);
> return lhs && rhs;
> }
>
>
> Looking at the big-array-copy scenario, I understand this as a case where
> a non-inlined function gets called and you want to redirect the constructor
> call of the lazy thunk (creating the by value "return" value) to do its
> construction directly in the receiving variable, presuming that, as the
> variable type is "big" the ABI will have the caller of the lazy thunk
> provide an address to construct the value in. The lazy thunk can use
> different constructors at different call sites which is nice in combination
> with not having to see the callee source code. This has significant
> performance advantage in the case that the value is large and does not have
> a lightweight move possibility. Apart from std::array all standard
> containers have cheap moves so the usefulness is further reduced compared
> to a regular by value parameter which is moved into the destination except
> for objects with large C or std arrays. Again: Is this functionality really
> so important that it warrants hijacking the original feature at the cost of
> making it less useful for its original purpose?
>
>
Florian show examples where allowing multiple usage of lazy parameters
cause suboptimal code.
Only way I see to avoid performance degradation and UB is ban multiple
usage of parameter in "dumb" code paths:
void foo(bool t, []->int a, []->int b, []->int c)
{
if (t)
{
a();
}
else
{
a(); //ok
}
if (t)
{
b();
}
if (!t) //compiler is dumb and do not try figure out that this path
can't be taken
{
b(); //error!
}
do
{
c(); //error again, even if this can be call only once.
}
while(false);
}
Something like this is done by C# compiler when checking is variable
unassigned or `out` parameters. Because this is new feature that never
existed in language before we can be lot of more restrictive than normal.
This need be done on "dumb" level because is impossible to check it in
general case.
Another thing is that lazy parameters should not leak from function body if
you want pass them to another function you need evaluate them first.
With this two requirements we could even drop `()` from syntax because lazy
parameter symbol can only appear once in function body (with small
exception for completely separate code paths).
As bonus, with `co_await` and `co_wait` we will have another limitation
that you can use parameters before first `co_` operation.
--
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/7df1b92d-bc1f-4f5c-ab2c-7fa5a3713e6a%40isocpp.org.
------=_Part_13780_1771436293.1527896867042
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Saturday, June 2, 2018 at 12:52:34 AM UTC+2, Be=
ngt Gustafsson wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">Considering forwarding of lazy parameters to functions that may or=
may not use them it becomes very hard to use them if they can only be eval=
uated once, or the code must make copies just in case, which defeats the pu=
rpose of the feature. I don't think that avoiding a copy during initial=
ization is a motivating purpose which should be allowed to rule the definit=
ion, instead we should focus on being able to mimic the shortcut operators =
and operator? and the classical logging scenario. Here is a nasty example:<=
div><br></div><div style=3D"background-color:rgb(250,250,250);border-color:=
rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break-word">=
<code><div><span style=3D"color:#008">bool</span><span style=3D"color:#000"=
> andand</span><span style=3D"color:#660">([]-></span><span style=3D"col=
or:#008">bool</span><span style=3D"color:#000"> lhs</span><span style=3D"co=
lor:#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660">[]-></span><span style=3D"color:#008">bool</span><span style=3D"col=
or:#000"> rhs</span><span style=3D"color:#660">)</span><span style=3D"color=
:#000"><br></span><span style=3D"color:#660">{</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#606">Log</span><span st=
yle=3D"color:#660">(</span><span style=3D"color:#080">"Performing anda=
nd on"</span><span style=3D"color:#660">,</span><span style=3D"color:#=
000"> lhs</span><span style=3D"color:#660">,</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#080">" and "</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> rhs</span><span style=
=3D"color:#660">);</span><span style=3D"color:#000"> =C2=A0 </span><span st=
yle=3D"color:#800">// Variadic log with lazy parameters only evaluated if l=
ogging is enabled.</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </spa=
n><span style=3D"color:#008">return</span><span style=3D"color:#000"> lhs</=
span><span style=3D"color:#660">()</span><span style=3D"color:#000"> </span=
><span style=3D"color:#660">&&</span><span style=3D"color:#000"> rh=
s</span><span style=3D"color:#660">();</span><span style=3D"color:#000"> =
=C2=A0 =C2=A0</span><span style=3D"color:#800">// This is UB if logging is =
enabled!</span><span style=3D"color:#000"><br></span><span style=3D"color:#=
660">}</span><span style=3D"color:#000"><br><br></span></div></code></div><=
div><br><br></div><div>Apart from showing the problems with evaluate once p=
rinciple this example rasies a couple of syntactical issues:</div><div><br>=
</div><div>1) How do we declare a variadic template with lazy parameters?</=
div><div>2) Is is logical to forward-by-lazy by not using postfix(). If so,=
how many of us will add the () by mistake when calling Log, accidentally (=
but silently) evaluating the lazy parameter and forwarding the resulting va=
lue as a (very simple) lazy expression to Log?</div><div>3) Could it be con=
sidered to use postfix [] (empty bracket) to "derefer" a lazy par=
ameter to make it stand out more from function application?</div><div><br><=
/div><div>Personally I still think that you should not have to annotate the=
use of a lazy parameter in the called function, just as the value/referenc=
e distinction this is something that the function author will have close to=
the top of her head when writing the code. This would nullify the 2) issue=
above. Maybe it could be complemented by a template function std::eager() =
which makes sure evaluation is done even if forwarding to a function that m=
ay take a lazy parameter. I don't have an example where this would be i=
mportant though, it seems a bit backwards.</div><div><br></div><div>I think=
the best would be to view this as a new kind of reference, possibly using =
the | token to signify it. That is, it works like a reference, except that =
before the first use it is evaluated (using the flag to check this). As for=
other references there is no indicating at the usage site, as other (lvalu=
e) references it is transparently forwarded to subordinate functions (for e=
xample Log in my example). The issue of how to write a template function ha=
s an obvious answer, and, I daresay, there should be no syntax issues as we=
have the example of using the & character which as an operator is para=
llel to | to indicate a type of reference already.</div><div><br></div><div=
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);b=
order-style:solid;border-width:1px;word-wrap:break-word"><code><div><span s=
tyle=3D"color:#800">// Variadic Log with lazy parameters only evaluated if =
logging is enabled.</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#008">template</span><span style=3D"color:#660"><</span><span =
style=3D"color:#008">typename</span><span style=3D"color:#000"> T</span><sp=
an style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#008">typename</span><span style=3D"color:#660">...</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#606">Ts</span><span st=
yle=3D"color:#660">></span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#606">Log</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">T</span><span style=3D"color:#660">|</span><span style=3D"c=
olor:#000"> head</span><span style=3D"color:#660">,</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#606">Ts</span><span style=3D"color:=
#660">|</span><span style=3D"color:#000"> tail</span><span style=3D"color:#=
660">)</span><span style=3D"color:#000"><br></span><span style=3D"color:#66=
0">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=
=3D"color:#008">if</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">(</span><span style=3D"color:#000">log_enabled</span><span styl=
e=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 =C2=A0 =C2=
=A0 cout </span><span style=3D"color:#660"><<</span><span style=3D"co=
lor:#000"> head</span><span style=3D"color:#660">;</span><span style=3D"col=
or:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#606">=
Log</span><span style=3D"color:#660">(</span><span style=3D"color:#000">tai=
l</span><span style=3D"color:#660">...);</span><span style=3D"color:#000"><=
br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"c=
olor:#000"><br></span><span style=3D"color:#660">}</span><span style=3D"col=
or:#000"><br></span><span style=3D"color:#008">bool</span><span style=3D"co=
lor:#000"> andand</span><span style=3D"color:#660">(</span><span style=3D"c=
olor:#008">bool</span><span style=3D"color:#660">|</span><span style=3D"col=
or:#000"> lhs</span><span style=3D"color:#660">,</span><span style=3D"color=
:#000"> </span><span style=3D"color:#008">bool</span><span style=3D"color:#=
660">|</span><span style=3D"color:#000"> rhs</span><span style=3D"color:#66=
0">)</span><span style=3D"color:#000"><br></span><span style=3D"color:#660"=
>{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D=
"color:#606">Log</span><span style=3D"color:#660">(</span><span style=3D"co=
lor:#080">"Performing andand on"</span><span style=3D"color:#660"=
>,</span><span style=3D"color:#000"> lhs</span><span style=3D"color:#660">,=
</span><span style=3D"color:#000"> </span><span style=3D"color:#080">"=
and "</span><span style=3D"color:#660">,</span><span style=3D"color:#=
000"> rhs</span><span style=3D"color:#660">);</span><span style=3D"color:#0=
00"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span =
style=3D"color:#000"> lhs </span><span style=3D"color:#660">&&</spa=
n><span style=3D"color:#000"> rhs</span><span style=3D"color:#660">;</span>=
<span style=3D"color:#000"><br></span><span style=3D"color:#660">}</span><s=
pan style=3D"color:#000"><br><br></span></div></code></div><div><div><br></=
div><div>Looking at the big-array-copy scenario, I understand this as a cas=
e where a non-inlined function gets called and you want to redirect the con=
structor call of the lazy thunk (creating the by value "return" v=
alue) to do its construction directly in the receiving variable, presuming =
that, as the variable type is "big" the ABI will have the caller =
of the lazy thunk provide an address to construct the value in. The lazy th=
unk can use different constructors at different call sites which is nice in=
combination with not having to see the callee source code. This has signif=
icant performance advantage in the case that the value is large and does no=
t have a lightweight move possibility. Apart from std::array all standard c=
ontainers have cheap moves=C2=A0 so the usefulness is further reduced compa=
red to a regular by value parameter which is moved into the destination exc=
ept for objects with large C or std arrays. Again: Is this functionality re=
ally so important that it warrants hijacking the original feature at the co=
st of making it less useful for its original purpose?</div></div><div><br><=
/div></div></blockquote><div>=C2=A0</div><div>Florian show examples where a=
llowing multiple usage of lazy parameters cause suboptimal code.</div><div>=
Only way I see to avoid performance degradation and UB is ban multiple usag=
e of parameter in "dumb" code paths:</div><div><div style=3D"back=
ground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-=
style: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"prett=
yprint"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">void</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: #008;" c=
lass=3D"styled-by-prettify">bool</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> t</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">[]=
-></span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> a</span><sp=
an 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: #=
008;" class=3D"styled-by-prettify">int</span><span style=3D"color: #000;" c=
lass=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"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">[]-></span><span style=3D"color: #008;" class=3D"styled-by-prettify">i=
nt</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> c</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span st=
yle=3D"color: #000;" class=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>=C2=A0 =C2=A0</span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">if</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"styl=
ed-by-prettify">t</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r>=C2=A0 =C2=A0</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 =C2=A0 a</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">();</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br>=C2=A0 =C2=A0</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: #008;" class=3D"styled-by-=
prettify">else</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><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 =C2=A0 a</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">();</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify=
">//ok</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"color: #008;" class=3D"styled-by-prettif=
y">if</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">t</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #0=
00;" 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"><br>=C2=A0 =C2=A0 =C2=A0 b</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">();</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">if</span><span style=3D"colo=
r: #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">t</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">//c=
ompiler is dumb and do not try figure out that this path can't be taken=
</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 =C2=A0 b</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #800;" class=3D"styled-by-prettify">//error!</s=
pan><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">}</s=
pan><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">do</=
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">{</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 =C2=A0 c</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #800;" class=3D"styled-by-prettify">//error aga=
in, even if this can be call only once.</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;" cl=
ass=3D"styled-by-prettify"><br>=C2=A0 =C2=A0</span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">while</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">false</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=
</span></div></code></div></div><div><br></div><div>Something like this is =
done by C# compiler when checking is variable unassigned or `out` parameter=
s. Because this is new feature that never existed in language before we can=
be lot of more restrictive than normal.</div><div>This need be done on &qu=
ot;dumb" level because is impossible to check it in general case.</div=
><div><br></div><div>Another thing is that lazy parameters should not leak =
from function body if you want pass them to another function you need evalu=
ate them first.</div><div><br></div><div>With this two requirements we coul=
d even drop `()` from syntax because lazy parameter symbol can only appear =
once in function body (with small exception for completely separate code pa=
ths).</div><div><br></div><div>As bonus, with `co_await` and `co_wait` we w=
ill have another limitation that you can use parameters before first `co_` =
operation.<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/7df1b92d-bc1f-4f5c-ab2c-7fa5a3713e6a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/7df1b92d-bc1f-4f5c-ab2c-7fa5a3713e6a=
%40isocpp.org</a>.<br />
------=_Part_13780_1771436293.1527896867042--
------=_Part_13779_2125879210.1527896867041--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 1 Jun 2018 21:21:10 -0700 (PDT)
Raw View
------=_Part_5385_143849733.1527913270477
Content-Type: multipart/alternative;
boundary="----=_Part_5386_907755676.1527913270477"
------=_Part_5386_907755676.1527913270477
Content-Type: text/plain; charset="UTF-8"
On Friday, June 1, 2018 at 6:52:34 PM UTC-4, Bengt Gustafsson wrote:
>
> Considering forwarding of lazy parameters to functions that may or may not
> use them it becomes very hard to use them if they can only be evaluated
> once, or the code must make copies just in case, which defeats the purpose
> of the feature.
>
I disagree. We encounter this scenario in other forms. A function which
takes a parameter by rvalue reference may move from it... or it may not.
Can you use the object afterwards? And if so, how? The same goes for
forwarding parameters with `std::forward`. You're not *supposed* to use
them later; you don't know what state they're in or if they've been moved
from or not.
This is just one more case of where you need to be careful.
--
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/eba03eca-3bfe-4063-8e2f-a5a8975a9232%40isocpp.org.
------=_Part_5386_907755676.1527913270477
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 1, 2018 at 6:52:34 PM UTC-4, Bengt Gustafs=
son 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">Con=
sidering forwarding of lazy parameters to functions that may or may not use=
them it becomes very hard to use them if they can only be evaluated once, =
or the code must make copies just in case, which defeats the purpose of the=
feature.</div></blockquote><div><br></div><div>I disagree. We encounter th=
is scenario in other forms. A function which takes a parameter by rvalue re=
ference may move from it... or it may not. Can you use the object afterward=
s? And if so, how? The same goes for forwarding parameters with `std::forwa=
rd`. You're not <i>supposed</i> to use them later; you don't know w=
hat state they're in or if they've been moved from or not.</div><di=
v><br></div><div>This is just one more case of where you need to be careful=
..</div><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/eba03eca-3bfe-4063-8e2f-a5a8975a9232%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/eba03eca-3bfe-4063-8e2f-a5a8975a9232=
%40isocpp.org</a>.<br />
------=_Part_5386_907755676.1527913270477--
------=_Part_5385_143849733.1527913270477--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Sat, 2 Jun 2018 14:16:46 +0100
Raw View
--00000000000003b0f6056da936cb
Content-Type: text/plain; charset="UTF-8"
On Fri, 1 Jun 2018, 23:52 Bengt Gustafsson, <bengt.gustafsson@beamways.com>
wrote:
> Considering forwarding of lazy parameters to functions that may or may not
> use them it becomes very hard to use them if they can only be evaluated
> once, or the code must make copies just in case, which defeats the purpose
> of the feature. I don't think that avoiding a copy during initialization is
> a motivating purpose which should be allowed to rule the definition,
> instead we should focus on being able to mimic the shortcut operators and
> operator? and the classical logging scenario. Here is a nasty example:
>
> bool andand([]->bool lhs, []->bool rhs)
> {
> Log("Performing andand on", lhs, " and ", rhs); // Variadic log
> with lazy parameters only evaluated if logging is enabled.
> return lhs() && rhs(); // This is UB if logging is enabled!
> }
>
>
>
> Apart from showing the problems with evaluate once principle this example
> rasies a couple of syntactical issues:
>
> 1) How do we declare a variadic template with lazy parameters?
> 2) Is is logical to forward-by-lazy by not using postfix(). If so, how
> many of us will add the () by mistake when calling Log, accidentally (but
> silently) evaluating the lazy parameter and forwarding the resulting value
> as a (very simple) lazy expression to Log?
>
No, adding the parentheses continues to defer evaluation. The syntactic
function call expression is a subexpression of the initializer passed to
Log, so its evaluation is delayed. Inventing a special forwarding operation
is unnecessary (although the compiler might need to identify such to
generate optimal code).
I'm not sure that the identifier without postfix parentheses has any
semantics.
3) Could it be considered to use postfix [] (empty bracket) to "derefer" a
> lazy parameter to make it stand out more from function application?
>
> Personally I still think that you should not have to annotate the use of a
> lazy parameter in the called function, just as the value/reference
> distinction this is something that the function author will have close to
> the top of her head when writing the code. This would nullify the 2) issue
> above. Maybe it could be complemented by a template function std::eager()
> which makes sure evaluation is done even if forwarding to a function that
> may take a lazy parameter. I don't have an example where this would be
> important though, it seems a bit backwards.
>
That wouldn't accomplish anything; the call to std::eager would itself be
delayed.
> I think the best would be to view this as a new kind of reference,
> possibly using the | token to signify it. That is, it works like a
> reference, except that before the first use it is evaluated (using the flag
> to check this). As for other references there is no indicating at the usage
> site, as other (lvalue) references it is transparently forwarded to
> subordinate functions (for example Log in my example). The issue of how to
> write a template function has an obvious answer, and, I daresay, there
> should be no syntax issues as we have the example of using the & character
> which as an operator is parallel to | to indicate a type of reference
> already.
>
> // Variadic Log with lazy parameters only evaluated if logging is enabled.
> template<typename T, typename... Ts> Log(T| head, Ts| tail)
> {
> if (log_enabled) {
> cout << head;
> Log(tail...);
> }
> }
> bool andand(bool| lhs, bool| rhs)
> {
> Log("Performing andand on", lhs, " and ", rhs);
> return lhs && rhs;
> }
>
>
> Looking at the big-array-copy scenario, I understand this as a case where
> a non-inlined function gets called and you want to redirect the constructor
> call of the lazy thunk (creating the by value "return" value) to do its
> construction directly in the receiving variable, presuming that, as the
> variable type is "big" the ABI will have the caller of the lazy thunk
> provide an address to construct the value in. The lazy thunk can use
> different constructors at different call sites which is nice in combination
> with not having to see the callee source code. This has significant
> performance advantage in the case that the value is large and does not have
> a lightweight move possibility. Apart from std::array all standard
> containers have cheap moves so the usefulness is further reduced compared
> to a regular by value parameter which is moved into the destination except
> for objects with large C or std arrays. Again: Is this functionality really
> so important that it warrants hijacking the original feature at the cost of
> making it less useful for its original purpose?
>
It's not just types with expensive move; there are also types with deleted
move and copy constructors. Given that guaranteed RVO enabled use of these
types recently, it would be a shame if they were not to work with this new
feature.
>
>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/unsubscribe
> .
> To unsubscribe from this group and all its topics, 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/984d7434-303d-4808-b054-8b116f19e838%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/984d7434-303d-4808-b054-8b116f19e838%40isocpp.org?utm_medium=email&utm_source=footer>
> .
>
--
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/CAJnLdOYYUpidmwTo82%2BxVms2byRf0im8P1zL3953EBa2nBie9Q%40mail.gmail.com.
--00000000000003b0f6056da936cb
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"auto"><div><br><br><div class=3D"gmail_quote"><div dir=3D"ltr">=
On Fri, 1 Jun 2018, 23:52 Bengt Gustafsson, <<a href=3D"mailto:bengt.gus=
tafsson@beamways.com">bengt.gustafsson@beamways.com</a>> wrote:<br></div=
><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Considering forwarding of =
lazy parameters to functions that may or may not use them it becomes very h=
ard to use them if they can only be evaluated once, or the code must make c=
opies just in case, which defeats the purpose of the feature. I don't t=
hink that avoiding a copy during initialization is a motivating purpose whi=
ch should be allowed to rule the definition, instead we should focus on bei=
ng able to mimic the shortcut operators and operator? and the classical log=
ging scenario. Here is a nasty example:<div><br></div><div class=3D"m_59329=
479607999503prettyprint" style=3D"background-color:rgb(250,250,250);border-=
color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break-=
word"><code class=3D"m_59329479607999503prettyprint"><div class=3D"m_593294=
79607999503subprettyprint"><span style=3D"color:#008" class=3D"m_5932947960=
7999503styled-by-prettify">bool</span><span style=3D"color:#000" class=3D"m=
_59329479607999503styled-by-prettify"> andand</span><span style=3D"color:#6=
60" class=3D"m_59329479607999503styled-by-prettify">([]-></span><span st=
yle=3D"color:#008" class=3D"m_59329479607999503styled-by-prettify">bool</sp=
an><span style=3D"color:#000" class=3D"m_59329479607999503styled-by-prettif=
y"> lhs</span><span style=3D"color:#660" class=3D"m_59329479607999503styled=
-by-prettify">,</span><span style=3D"color:#000" class=3D"m_593294796079995=
03styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_5932947=
9607999503styled-by-prettify">[]-></span><span style=3D"color:#008" clas=
s=3D"m_59329479607999503styled-by-prettify">bool</span><span style=3D"color=
:#000" class=3D"m_59329479607999503styled-by-prettify"> rhs</span><span sty=
le=3D"color:#660" class=3D"m_59329479607999503styled-by-prettify">)</span><=
span style=3D"color:#000" class=3D"m_59329479607999503styled-by-prettify"><=
br></span><span style=3D"color:#660" class=3D"m_59329479607999503styled-by-=
prettify">{</span><span style=3D"color:#000" class=3D"m_59329479607999503st=
yled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#606" class=
=3D"m_59329479607999503styled-by-prettify">Log</span><span style=3D"color:#=
660" class=3D"m_59329479607999503styled-by-prettify">(</span><span style=3D=
"color:#080" class=3D"m_59329479607999503styled-by-prettify">"Performi=
ng andand on"</span><span style=3D"color:#660" class=3D"m_593294796079=
99503styled-by-prettify">,</span><span style=3D"color:#000" class=3D"m_5932=
9479607999503styled-by-prettify"> lhs</span><span style=3D"color:#660" clas=
s=3D"m_59329479607999503styled-by-prettify">,</span><span style=3D"color:#0=
00" class=3D"m_59329479607999503styled-by-prettify"> </span><span style=3D"=
color:#080" class=3D"m_59329479607999503styled-by-prettify">" and &quo=
t;</span><span style=3D"color:#660" class=3D"m_59329479607999503styled-by-p=
rettify">,</span><span style=3D"color:#000" class=3D"m_59329479607999503sty=
led-by-prettify"> rhs</span><span style=3D"color:#660" class=3D"m_593294796=
07999503styled-by-prettify">);</span><span style=3D"color:#000" class=3D"m_=
59329479607999503styled-by-prettify"> =C2=A0 </span><span style=3D"color:#8=
00" class=3D"m_59329479607999503styled-by-prettify">// Variadic log with la=
zy parameters only evaluated if logging is enabled.</span><span style=3D"co=
lor:#000" class=3D"m_59329479607999503styled-by-prettify"><br>=C2=A0 =C2=A0=
</span><span style=3D"color:#008" class=3D"m_59329479607999503styled-by-pr=
ettify">return</span><span style=3D"color:#000" class=3D"m_5932947960799950=
3styled-by-prettify"> lhs</span><span style=3D"color:#660" class=3D"m_59329=
479607999503styled-by-prettify">()</span><span style=3D"color:#000" class=
=3D"m_59329479607999503styled-by-prettify"> </span><span style=3D"color:#66=
0" class=3D"m_59329479607999503styled-by-prettify">&&</span><span s=
tyle=3D"color:#000" class=3D"m_59329479607999503styled-by-prettify"> rhs</s=
pan><span style=3D"color:#660" class=3D"m_59329479607999503styled-by-pretti=
fy">();</span><span style=3D"color:#000" class=3D"m_59329479607999503styled=
-by-prettify"> =C2=A0 =C2=A0</span><span style=3D"color:#800" class=3D"m_59=
329479607999503styled-by-prettify">// This is UB if logging is enabled!</sp=
an><span style=3D"color:#000" class=3D"m_59329479607999503styled-by-prettif=
y"><br></span><span style=3D"color:#660" class=3D"m_59329479607999503styled=
-by-prettify">}</span><span style=3D"color:#000" class=3D"m_593294796079995=
03styled-by-prettify"><br><br></span></div></code></div><div><br><br></div>=
<div>Apart from showing the problems with evaluate once principle this exam=
ple rasies a couple of syntactical issues:</div><div><br></div><div>1) How =
do we declare a variadic template with lazy parameters?</div><div>2) Is is =
logical to forward-by-lazy by not using postfix(). If so, how many of us wi=
ll add the () by mistake when calling Log, accidentally (but silently) eval=
uating the lazy parameter and forwarding the resulting value as a (very sim=
ple) lazy expression to Log?</div></div></blockquote></div></div><div dir=
=3D"auto"><br></div><div dir=3D"auto">No, adding the parentheses continues =
to defer evaluation. The syntactic function call expression is a subexpress=
ion of the initializer passed to Log, so its evaluation is delayed. Inventi=
ng a special forwarding operation is unnecessary (although the compiler mig=
ht need to identify such to generate optimal code).=C2=A0</div><div dir=3D"=
auto"><br></div><div dir=3D"auto">I'm not sure that the identifier with=
out postfix parentheses has any semantics.=C2=A0</div><div dir=3D"auto"><br=
></div><div dir=3D"auto"><div class=3D"gmail_quote"><blockquote class=3D"gm=
ail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr"><div>3) Could it be considered to use postfix [] (=
empty bracket) to "derefer" a lazy parameter to make it stand out=
more from function application?</div><div><br></div><div>Personally I stil=
l think that you should not have to annotate the use of a lazy parameter in=
the called function, just as the value/reference distinction this is somet=
hing that the function author will have close to the top of her head when w=
riting the code. This would nullify the 2) issue above. Maybe it could be c=
omplemented by a template function std::eager() which makes sure evaluation=
is done even if forwarding to a function that may take a lazy parameter. I=
don't have an example where this would be important though, it seems a=
bit backwards.</div><div></div></div></blockquote></div></div><div dir=3D"=
auto"><br></div><div dir=3D"auto">That wouldn't accomplish anything; th=
e call to std::eager would itself be delayed.=C2=A0</div><div dir=3D"auto">=
<br></div><div dir=3D"auto"><div class=3D"gmail_quote"><blockquote class=3D=
"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding=
-left:1ex"><div dir=3D"ltr"><div><br></div><div>I think the best would be t=
o view this as a new kind of reference, possibly using the | token to signi=
fy it. That is, it works like a reference, except that before the first use=
it is evaluated (using the flag to check this). As for other references th=
ere is no indicating at the usage site, as other (lvalue) references it is =
transparently forwarded to subordinate functions (for example Log in my exa=
mple). The issue of how to write a template function has an obvious answer,=
and, I daresay, there should be no syntax issues as we have the example of=
using the & character which as an operator is parallel to | to indicat=
e a type of reference already.</div><div><br></div><div class=3D"m_59329479=
607999503prettyprint" style=3D"background-color:rgb(250,250,250);border-col=
or:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break-wor=
d"><code class=3D"m_59329479607999503prettyprint"><div class=3D"m_593294796=
07999503subprettyprint"><span style=3D"color:#800" class=3D"m_5932947960799=
9503styled-by-prettify">// Variadic Log with lazy parameters only evaluated=
if logging is enabled.</span><span style=3D"color:#000" class=3D"m_5932947=
9607999503styled-by-prettify"><br></span><span style=3D"color:#008" class=
=3D"m_59329479607999503styled-by-prettify">template</span><span style=3D"co=
lor:#660" class=3D"m_59329479607999503styled-by-prettify"><</span><span =
style=3D"color:#008" class=3D"m_59329479607999503styled-by-prettify">typena=
me</span><span style=3D"color:#000" class=3D"m_59329479607999503styled-by-p=
rettify"> T</span><span style=3D"color:#660" class=3D"m_59329479607999503st=
yled-by-prettify">,</span><span style=3D"color:#000" class=3D"m_59329479607=
999503styled-by-prettify"> </span><span style=3D"color:#008" class=3D"m_593=
29479607999503styled-by-prettify">typename</span><span style=3D"color:#660"=
class=3D"m_59329479607999503styled-by-prettify">...</span><span style=3D"c=
olor:#000" class=3D"m_59329479607999503styled-by-prettify"> </span><span st=
yle=3D"color:#606" class=3D"m_59329479607999503styled-by-prettify">Ts</span=
><span style=3D"color:#660" class=3D"m_59329479607999503styled-by-prettify"=
>></span><span style=3D"color:#000" class=3D"m_59329479607999503styled-b=
y-prettify"> </span><span style=3D"color:#606" class=3D"m_59329479607999503=
styled-by-prettify">Log</span><span style=3D"color:#660" class=3D"m_5932947=
9607999503styled-by-prettify">(</span><span style=3D"color:#000" class=3D"m=
_59329479607999503styled-by-prettify">T</span><span style=3D"color:#660" cl=
ass=3D"m_59329479607999503styled-by-prettify">|</span><span style=3D"color:=
#000" class=3D"m_59329479607999503styled-by-prettify"> head</span><span sty=
le=3D"color:#660" class=3D"m_59329479607999503styled-by-prettify">,</span><=
span style=3D"color:#000" class=3D"m_59329479607999503styled-by-prettify"> =
</span><span style=3D"color:#606" class=3D"m_59329479607999503styled-by-pre=
ttify">Ts</span><span style=3D"color:#660" class=3D"m_59329479607999503styl=
ed-by-prettify">|</span><span style=3D"color:#000" class=3D"m_5932947960799=
9503styled-by-prettify"> tail</span><span style=3D"color:#660" class=3D"m_5=
9329479607999503styled-by-prettify">)</span><span style=3D"color:#000" clas=
s=3D"m_59329479607999503styled-by-prettify"><br></span><span style=3D"color=
:#660" class=3D"m_59329479607999503styled-by-prettify">{</span><span style=
=3D"color:#000" class=3D"m_59329479607999503styled-by-prettify"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#008" class=3D"m_59329479607999503styled=
-by-prettify">if</span><span style=3D"color:#000" class=3D"m_59329479607999=
503styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_593294=
79607999503styled-by-prettify">(</span><span style=3D"color:#000" class=3D"=
m_59329479607999503styled-by-prettify">log_enabled</span><span style=3D"col=
or:#660" class=3D"m_59329479607999503styled-by-prettify">)</span><span styl=
e=3D"color:#000" class=3D"m_59329479607999503styled-by-prettify"> </span><s=
pan style=3D"color:#660" class=3D"m_59329479607999503styled-by-prettify">{<=
/span><span style=3D"color:#000" class=3D"m_59329479607999503styled-by-pret=
tify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 cout </span><span style=3D"color:#660=
" class=3D"m_59329479607999503styled-by-prettify"><<</span><span styl=
e=3D"color:#000" class=3D"m_59329479607999503styled-by-prettify"> head</spa=
n><span style=3D"color:#660" class=3D"m_59329479607999503styled-by-prettify=
">;</span><span style=3D"color:#000" class=3D"m_59329479607999503styled-by-=
prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#606"=
class=3D"m_59329479607999503styled-by-prettify">Log</span><span style=3D"c=
olor:#660" class=3D"m_59329479607999503styled-by-prettify">(</span><span st=
yle=3D"color:#000" class=3D"m_59329479607999503styled-by-prettify">tail</sp=
an><span style=3D"color:#660" class=3D"m_59329479607999503styled-by-prettif=
y">...);</span><span style=3D"color:#000" class=3D"m_59329479607999503style=
d-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660" class=3D=
"m_59329479607999503styled-by-prettify">}</span><span style=3D"color:#000" =
class=3D"m_59329479607999503styled-by-prettify"><br></span><span style=3D"c=
olor:#660" class=3D"m_59329479607999503styled-by-prettify">}</span><span st=
yle=3D"color:#000" class=3D"m_59329479607999503styled-by-prettify"><br></sp=
an><span style=3D"color:#008" class=3D"m_59329479607999503styled-by-prettif=
y">bool</span><span style=3D"color:#000" class=3D"m_59329479607999503styled=
-by-prettify"> andand</span><span style=3D"color:#660" class=3D"m_593294796=
07999503styled-by-prettify">(</span><span style=3D"color:#008" class=3D"m_5=
9329479607999503styled-by-prettify">bool</span><span style=3D"color:#660" c=
lass=3D"m_59329479607999503styled-by-prettify">|</span><span style=3D"color=
:#000" class=3D"m_59329479607999503styled-by-prettify"> lhs</span><span sty=
le=3D"color:#660" class=3D"m_59329479607999503styled-by-prettify">,</span><=
span style=3D"color:#000" class=3D"m_59329479607999503styled-by-prettify"> =
</span><span style=3D"color:#008" class=3D"m_59329479607999503styled-by-pre=
ttify">bool</span><span style=3D"color:#660" class=3D"m_59329479607999503st=
yled-by-prettify">|</span><span style=3D"color:#000" class=3D"m_59329479607=
999503styled-by-prettify"> rhs</span><span style=3D"color:#660" class=3D"m_=
59329479607999503styled-by-prettify">)</span><span style=3D"color:#000" cla=
ss=3D"m_59329479607999503styled-by-prettify"><br></span><span style=3D"colo=
r:#660" class=3D"m_59329479607999503styled-by-prettify">{</span><span style=
=3D"color:#000" class=3D"m_59329479607999503styled-by-prettify"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#606" class=3D"m_59329479607999503styled=
-by-prettify">Log</span><span style=3D"color:#660" class=3D"m_5932947960799=
9503styled-by-prettify">(</span><span style=3D"color:#080" class=3D"m_59329=
479607999503styled-by-prettify">"Performing andand on"</span><spa=
n style=3D"color:#660" class=3D"m_59329479607999503styled-by-prettify">,</s=
pan><span style=3D"color:#000" class=3D"m_59329479607999503styled-by-pretti=
fy"> lhs</span><span style=3D"color:#660" class=3D"m_59329479607999503style=
d-by-prettify">,</span><span style=3D"color:#000" class=3D"m_59329479607999=
503styled-by-prettify"> </span><span style=3D"color:#080" class=3D"m_593294=
79607999503styled-by-prettify">" and "</span><span style=3D"color=
:#660" class=3D"m_59329479607999503styled-by-prettify">,</span><span style=
=3D"color:#000" class=3D"m_59329479607999503styled-by-prettify"> rhs</span>=
<span style=3D"color:#660" class=3D"m_59329479607999503styled-by-prettify">=
);</span><span style=3D"color:#000" class=3D"m_59329479607999503styled-by-p=
rettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008" class=3D"m_593=
29479607999503styled-by-prettify">return</span><span style=3D"color:#000" c=
lass=3D"m_59329479607999503styled-by-prettify"> lhs </span><span style=3D"c=
olor:#660" class=3D"m_59329479607999503styled-by-prettify">&&</span=
><span style=3D"color:#000" class=3D"m_59329479607999503styled-by-prettify"=
> rhs</span><span style=3D"color:#660" class=3D"m_59329479607999503styled-b=
y-prettify">;</span><span style=3D"color:#000" class=3D"m_59329479607999503=
styled-by-prettify"><br></span><span style=3D"color:#660" class=3D"m_593294=
79607999503styled-by-prettify">}</span><span style=3D"color:#000" class=3D"=
m_59329479607999503styled-by-prettify"><br><br></span></div></code></div><d=
iv><div><br></div><div>Looking at the big-array-copy scenario, I understand=
this as a case where a non-inlined function gets called and you want to re=
direct the constructor call of the lazy thunk (creating the by value "=
return" value) to do its construction directly in the receiving variab=
le, presuming that, as the variable type is "big" the ABI will ha=
ve the caller of the lazy thunk provide an address to construct the value i=
n. The lazy thunk can use different constructors at different call sites wh=
ich is nice in combination with not having to see the callee source code. T=
his has significant performance advantage in the case that the value is lar=
ge and does not have a lightweight move possibility. Apart from std::array =
all standard containers have cheap moves=C2=A0 so the usefulness is further=
reduced compared to a regular by value parameter which is moved into the d=
estination except for objects with large C or std arrays. Again: Is this fu=
nctionality really so important that it warrants hijacking the original fea=
ture at the cost of making it less useful for its original purpose?</div></=
div><div></div></div></blockquote></div></div><div dir=3D"auto"><br></div><=
div dir=3D"auto">It's not just types with expensive move; there are als=
o types with deleted move and copy constructors. Given that guaranteed RVO =
enabled use of these types recently, it would be a shame if they were not t=
o work with this new feature.=C2=A0</div><div dir=3D"auto"><br></div><div d=
ir=3D"auto"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div =
dir=3D"ltr"><div><br></div><div><br></div><div><br></div></div>
<p></p>
-- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/unsubscribe" target=3D"_blan=
k" rel=3D"noreferrer">https://groups.google.com/a/isocpp.org/d/topic/std-pr=
oposals/5oUZysJB4HE/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_blank" rel=3D"n=
oreferrer">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank" rel=3D"noreferrer">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/984d7434-303d-4808-b054-8b116f19e838%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank" =
rel=3D"noreferrer">https://groups.google.com/a/isocpp.org/d/msgid/std-propo=
sals/984d7434-303d-4808-b054-8b116f19e838%40isocpp.org</a>.<br>
</blockquote></div></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/CAJnLdOYYUpidmwTo82%2BxVms2byRf0im8P1=
zL3953EBa2nBie9Q%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdOYYUpidmw=
To82%2BxVms2byRf0im8P1zL3953EBa2nBie9Q%40mail.gmail.com</a>.<br />
--00000000000003b0f6056da936cb--
.
Author: florian.csdt@gmail.com
Date: Sat, 2 Jun 2018 09:20:31 -0700 (PDT)
Raw View
------=_Part_18131_119932819.1527956431525
Content-Type: multipart/alternative;
boundary="----=_Part_18132_1366291150.1527956431526"
------=_Part_18132_1366291150.1527956431526
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
I know other people already have answered your questions, but I would like=
=20
to give my point of view.
Le samedi 2 juin 2018 00:52:34 UTC+2, Bengt Gustafsson a =C3=A9crit :
>
> Considering forwarding of lazy parameters to functions that may or may no=
t=20
> use them it becomes very hard to use them if they can only be evaluated=
=20
> once, or the code must make copies just in case, which defeats the purpos=
e=20
> of the feature. I don't think that avoiding a copy during initialization =
is=20
> a motivating purpose which should be allowed to rule the definition,=20
> instead we should focus on being able to mimic the shortcut operators and=
=20
> operator? and the classical logging scenario. Here is a nasty example:
>
> bool andand([]->bool lhs, []->bool rhs)
> {
> Log("Performing andand on", lhs, " and ", rhs); // Variadic log=20
> with lazy parameters only evaluated if logging is enabled.
> return lhs() && rhs(); // This is UB if logging is enabled!
> }
>
>
>
If you really want something like that you could imagine doing the=20
following:
bool andand([] -> bool lhs_lazy, [] -> bool rhs_lazy) {
std::optional<bool> lhs_v, rhs_v;
auto lhs =3D [&] () -> bool { if (!lhs_v) { lhs_v =3D lhs_lazy(); } retur=
n=20
lhs_v.value(); };
auto rhs =3D [&] () -> bool { if (!rhs_v) { rhs_v =3D rhs_lazy(); } retur=
n=20
rhs_v.value(); };
=20
Log("Performing andand on", lhs(), " and ", rhs());
return lhs() && rhs();
}
This would allow the kind of behavior you want (parameters will be=20
evaluated only if they are needed), while keeping lazy arguments returning=
=20
pr-values.
We would need to standardize lambda captures relating to lazy parameters,=
=20
but it would be worth it.
However, if you allow multiple evaluation of the expression: either you=20
will not be able to return a pr-value (with caching), or you will have=20
problems with overlapping lifetime of the same objects...
So you can implement what you want with what I propose, but I cannot=20
implement what I want with what you propose.
=20
>
> Apart from showing the problems with evaluate once principle this example=
=20
> rasies a couple of syntactical issues:
>
> 1) How do we declare a variadic template with lazy parameters?
>
Is there any problem with this?
template <class... Args>
void Log([] -> Args... args);
=20
> 2) Is is logical to forward-by-lazy by not using postfix(). If so, how=20
> many of us will add the () by mistake when calling Log, accidentally (but=
=20
> silently) evaluating the lazy parameter and forwarding the resulting valu=
e=20
> as a (very simple) lazy expression to Log?
>
Lazy parameter forwarding is just an optimization a compiler would be able=
=20
to do. But there is no reason it should be in the language: if Log takes=20
lazy parameters, when you "evaluate" a lazy parameter to forward to Log,=20
you will create a new lazy expression that will evaluate the first lazy=20
expression when it will be evaluated.
With or without a proper lazy parameter forwarding, the behaviour of the=20
program will be *exactly* the same.
=20
> 3) Could it be considered to use postfix [] (empty bracket) to "derefer" =
a=20
> lazy parameter to make it stand out more from function application?
>
I have no opinion on what syntax should be used to "evaluate" a lazy=20
expression. For now the majority seems to prefer postfix ().
=20
>
> Personally I still think that you should not have to annotate the use of =
a=20
> lazy parameter in the called function, just as the value/reference=20
> distinction this is something that the function author will have close to=
=20
> the top of her head when writing the code. This would nullify the 2) issu=
e=20
> above. Maybe it could be complemented by a template function std::eager()=
=20
> which makes sure evaluation is done even if forwarding to a function that=
=20
> may take a lazy parameter. I don't have an example where this would be=20
> important though, it seems a bit backwards.
>
If you want an expression to be executed even when passed as a lazy=20
parameter, just create a local variable constructed from your expression,=
=20
and pass this variable as the lazy parameter.
bool foo() {
bool lhs =3D bar(0); // this expression evaluation is forced here
return lhs && bar(1); // the evaluation of bar(1) might not happen
}
=20
>
> I think the best would be to view this as a new kind of reference,=20
> possibly using the | token to signify it. That is, it works like a=20
> reference, except that before the first use it is evaluated (using the fl=
ag=20
> to check this). As for other references there is no indicating at the usa=
ge=20
> site, as other (lvalue) references it is transparently forwarded to=20
> subordinate functions (for example Log in my example). The issue of how t=
o=20
> write a template function has an obvious answer, and, I daresay, there=20
> should be no syntax issues as we have the example of using the & characte=
r=20
> which as an operator is parallel to | to indicate a type of reference=20
> already.
>
> // Variadic Log with lazy parameters only evaluated if logging is enabled=
..
> template<typename T, typename... Ts> Log(T| head, Ts| tail)
> {
> if (log_enabled) {
> cout << head;
> Log(tail...);
> }
> }
> bool andand(bool| lhs, bool| rhs)
> {
> Log("Performing andand on", lhs, " and ", rhs);
> return lhs && rhs;
> }
>
>
>
I fail to see how this new syntax is better. The proposed syntax [] -> has=
=20
a comprehensive meaning once you have seen a lambda. But this is a weak=20
argument, I have to admit.
=20
> Looking at the big-array-copy scenario, I understand this as a case where=
=20
> a non-inlined function gets called and you want to redirect the construct=
or=20
> call of the lazy thunk (creating the by value "return" value) to do its=
=20
> construction directly in the receiving variable, presuming that, as the=
=20
> variable type is "big" the ABI will have the caller of the lazy thunk=20
> provide an address to construct the value in. The lazy thunk can use=20
> different constructors at different call sites which is nice in combinati=
on=20
> with not having to see the callee source code. This has significant=20
> performance advantage in the case that the value is large and does not ha=
ve=20
> a lightweight move possibility. Apart from std::array all standard=20
> containers have cheap moves so the usefulness is further reduced compare=
d=20
> to a regular by value parameter which is moved into the destination excep=
t=20
> for objects with large C or std arrays. Again: Is this functionality real=
ly=20
> so important that it warrants hijacking the original feature at the cost =
of=20
> making it less useful for its original purpose?
>
>
As Edward said, this is not only about big objects with inefficient moves,=
=20
but also types that are neither copyable nor moveable: for instance=20
std::atomic or std::mutex.
Also, I have the feeling that lazy parameters would be an efficient way to=
=20
create complex objects without relying on emplace fonctions and=20
std::piecewise_construct.
I asked before if my feeling on this subject was shared, but the discussion=
=20
drifted away.
--=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/cc20625c-804f-4ad2-8c38-ce443e7314ec%40isocpp.or=
g.
------=_Part_18132_1366291150.1527956431526
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I know other people already have answered your questions, =
but I would like to give my point of view.<br><br>Le samedi 2 juin 2018 00:=
52:34 UTC+2, Bengt Gustafsson a =C3=A9crit=C2=A0:<blockquote class=3D"gmail=
_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;p=
adding-left: 1ex;"><div dir=3D"ltr">Considering forwarding of lazy paramete=
rs to functions that may or may not use them it becomes very hard to use th=
em if they can only be evaluated once, or the code must make copies just in=
case, which defeats the purpose of the feature. I don't think that avo=
iding a copy during initialization is a motivating purpose which should be =
allowed to rule the definition, instead we should focus on being able to mi=
mic the shortcut operators and operator? and the classical logging scenario=
.. Here is a nasty example:<div><br></div><div style=3D"background-color:rgb=
(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-width=
:1px;word-wrap:break-word"><code><div><span style=3D"color:#008">bool</span=
><span style=3D"color:#000"> andand</span><span style=3D"color:#660">([]-&g=
t;</span><span style=3D"color:#008">bool</span><span style=3D"color:#000"> =
lhs</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </=
span><span style=3D"color:#660">[]-></span><span style=3D"color:#008">bo=
ol</span><span style=3D"color:#000"> rhs</span><span style=3D"color:#660">)=
</span><span style=3D"color:#000"><br></span><span style=3D"color:#660">{</=
span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"col=
or:#606">Log</span><span style=3D"color:#660">(</span><span style=3D"color:=
#080">"Performing andand on"</span><span style=3D"color:#660">,</=
span><span style=3D"color:#000"> lhs</span><span style=3D"color:#660">,</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#080">" and=
"</span><span style=3D"color:#660">,</span><span style=3D"color:#000"=
> rhs</span><span style=3D"color:#660">);</span><span style=3D"color:#000">=
=C2=A0 </span><span style=3D"color:#800">// Variadic log with lazy paramet=
ers only evaluated if logging is enabled.</span><span style=3D"color:#000">=
<br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span styl=
e=3D"color:#000"> lhs</span><span style=3D"color:#660">()</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">&&</span><span s=
tyle=3D"color:#000"> rhs</span><span style=3D"color:#660">();</span><span s=
tyle=3D"color:#000"> =C2=A0 =C2=A0</span><span style=3D"color:#800">// This=
is UB if logging is enabled!</span><span style=3D"color:#000"><br></span><=
span style=3D"color:#660">}</span><span style=3D"color:#000"><br><br></span=
></div></code></div><div><br></div></div></blockquote><div><br></div><div>I=
f you really want something like that you could imagine doing the following=
:</div><div><div style=3D"background-color: rgb(250, 250, 250); border-colo=
r: rgb(187, 187, 187); border-style: solid; border-width: 1px; overflow-wra=
p: break-word;" class=3D"prettyprint"><code class=3D"prettyprint"><div clas=
s=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">bool</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> a=
ndand</span><span style=3D"color: #660;" class=3D"styled-by-prettify">([]</=
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 sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">bool</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> lhs_lazy</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: #660;" class=3D"style=
d-by-prettify">[]</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">-&=
gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">bool</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> rhs_lazy</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: #6=
60;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br>=C2=A0 std</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">optional</span><span style=3D"color: #080;" class=3D"s=
tyled-by-prettify"><bool></span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> lhs_v</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> rhs_v</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">;</span><code class=3D"prettyprint"><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> lhs </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">[&=
amp;]</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><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"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;"=
class=3D"styled-by-prettify">bool</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">if<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">(!</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">lhs_v</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #00=
0;" 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"> lhs_v </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> lhs_lazy</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> lhs_v</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify">value</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">();</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></span></code><code class=3D"prettyprint"><span style=3D"color: #000;"=
class=3D"styled-by-prettify">=C2=A0 </span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> rhs </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </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><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"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">bool</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
if</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">rhs_v</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"> rhs_v </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> rhs_lazy</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: #660;" class=3D"styled-by-prettify">}</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> rhs_v</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify">value</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"style=
d-by-prettify">};</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br></span></code><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify">=C2=A0 </span><br><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><code><span style=3D"color:#606">=C2=A0 Log</span><span style=3D"c=
olor:#660">(</span><span style=3D"color:#080">"Performing andand on&qu=
ot;</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> lh=
s</span><span style=3D"color:#660">(),</span><span style=3D"color:#000"> </=
span><span style=3D"color:#080">" and "</span><span style=3D"colo=
r:#660">,</span><span style=3D"color:#000"> rhs</span><span style=3D"color:=
#660">());</span></code><br>=C2=A0 return lhs() && rhs();<br></span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></code><=
/div></div><div><br></div><div>This would allow the kind of behavior you wa=
nt (parameters will be evaluated only if they are needed), while keeping la=
zy arguments returning pr-values.</div><div>We would need to standardize la=
mbda captures relating to lazy parameters, but it would be worth it.</div><=
div><br></div><div>However, if you allow multiple evaluation of the express=
ion: either you will not be able to return a pr-value (with caching), or yo=
u will have problems with overlapping lifetime of the same objects...</div>=
<div>So you can implement what you want with what I propose, but I cannot i=
mplement what I want with what you propose.<br></div><div>=C2=A0</div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><di=
v>Apart from showing the problems with evaluate once principle this example=
rasies a couple of syntactical issues:</div><div><br></div><div>1) How do =
we declare a variadic template with lazy parameters?</div></div></blockquot=
e><div><br></div><div>Is there any problem with this?</div><div><div style=
=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187);=
border-style: solid; border-width: 1px; overflow-wrap: break-word;" class=
=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint">=
<span style=3D"color: #606;" class=3D"styled-by-prettify">template <clas=
s... Args><br>void Log([] -> Args... args);</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify"></span></div></code></div><br></div>=
<div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div>2) Is is logical to forward-by-lazy by not using postfix(). If so,=
how many of us will add the () by mistake when calling Log, accidentally (=
but silently) evaluating the lazy parameter and forwarding the resulting va=
lue as a (very simple) lazy expression to Log?</div></div></blockquote><div=
>Lazy parameter forwarding is just an optimization a compiler would be able=
to do. But there is no reason it should be in the language: if Log takes l=
azy parameters, when you "evaluate" a lazy parameter to forward t=
o Log, you will create a new lazy expression that will evaluate the first l=
azy expression when it will be evaluated.</div><div>With or without a prope=
r lazy parameter forwarding, the behaviour of the program will be <i>exactl=
y</i> the same.<br></div><div><br></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div>3) Could it be considered=
to use postfix [] (empty bracket) to "derefer" a lazy parameter =
to make it stand out more from function application?</div></div></blockquot=
e><div><br></div><div>I have no opinion on what syntax should be used to &q=
uot;evaluate" a lazy expression. For now the majority seems to prefer =
postfix ().<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;"><div dir=3D"ltr"><div><br></div><div>Personally I still think that =
you should not have to annotate the use of a lazy parameter in the called f=
unction, just as the value/reference distinction this is something that the=
function author will have close to the top of her head when writing the co=
de. This would nullify the 2) issue above. Maybe it could be complemented b=
y a template function std::eager() which makes sure evaluation is done even=
if forwarding to a function that may take a lazy parameter. I don't ha=
ve an example where this would be important though, it seems a bit backward=
s.</div></div></blockquote><div><br></div><div>If you want an expression to=
be executed even when passed as a lazy parameter, just create a local vari=
able constructed from your expression, and pass this variable as the lazy p=
arameter.</div><div><div style=3D"background-color: rgb(250, 250, 250); bor=
der-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; over=
flow-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettyprint"><=
div class=3D"subprettyprint"><span style=3D"color: #606;" class=3D"styled-b=
y-prettify">bool foo() {<br>=C2=A0 bool lhs =3D bar(0); // this expression =
evaluation is forced here<br>=C2=A0 return lhs && bar(1); // the ev=
aluation of bar(1) might not happen<br>}</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify"></span></div></code></div><br><br></div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
div><br></div><div>I think the best would be to view this as a new kind of =
reference, possibly using the | token to signify it. That is, it works like=
a reference, except that before the first use it is evaluated (using the f=
lag to check this). As for other references there is no indicating at the u=
sage site, as other (lvalue) references it is transparently forwarded to su=
bordinate functions (for example Log in my example). The issue of how to wr=
ite a template function has an obvious answer, and, I daresay, there should=
be no syntax issues as we have the example of using the & character wh=
ich as an operator is parallel to | to indicate a type of reference already=
..</div><div><br></div><div style=3D"background-color:rgb(250,250,250);borde=
r-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:brea=
k-word"><code><div><span style=3D"color:#800">// Variadic Log with lazy par=
ameters only evaluated if logging is enabled.</span><span style=3D"color:#0=
00"><br></span><span style=3D"color:#008">template</span><span style=3D"col=
or:#660"><</span><span style=3D"color:#008">typename</span><span style=
=3D"color:#000"> T</span><span style=3D"color:#660">,</span><span style=3D"=
color:#000"> </span><span style=3D"color:#008">typename</span><span style=
=3D"color:#660">...</span><span style=3D"color:#000"> </span><span style=3D=
"color:#606">Ts</span><span style=3D"color:#660">></span><span style=3D"=
color:#000"> </span><span style=3D"color:#606">Log</span><span style=3D"col=
or:#660">(</span><span style=3D"color:#000">T</span><span style=3D"color:#6=
60">|</span><span style=3D"color:#000"> head</span><span style=3D"color:#66=
0">,</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Ts=
</span><span style=3D"color:#660">|</span><span style=3D"color:#000"> tail<=
/span><span style=3D"color:#660">)</span><span style=3D"color:#000"><br></s=
pan><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color:#008">if</span><span style=3D"color:=
#000"> </span><span style=3D"color:#660">(</span><span style=3D"color:#000"=
>log_enabled</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 =C2=A0 =C2=A0 cout </span><span style=3D"color:#660"><=
;<</span><span style=3D"color:#000"> head</span><span style=3D"color:#66=
0">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </spa=
n><span style=3D"color:#606">Log</span><span style=3D"color:#660">(</span><=
span style=3D"color:#000">tail</span><span style=3D"color:#660">...);</span=
><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#=
660">}</span><span style=3D"color:#000"><br></span><span style=3D"color:#66=
0">}</span><span style=3D"color:#000"><br></span><span style=3D"color:#008"=
>bool</span><span style=3D"color:#000"> andand</span><span style=3D"color:#=
660">(</span><span style=3D"color:#008">bool</span><span style=3D"color:#66=
0">|</span><span style=3D"color:#000"> lhs</span><span style=3D"color:#660"=
>,</span><span style=3D"color:#000"> </span><span style=3D"color:#008">bool=
</span><span style=3D"color:#660">|</span><span style=3D"color:#000"> rhs</=
span><span style=3D"color:#660">)</span><span style=3D"color:#000"><br></sp=
an><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0=
=C2=A0 </span><span style=3D"color:#606">Log</span><span style=3D"color:#6=
60">(</span><span style=3D"color:#080">"Performing andand on"</sp=
an><span style=3D"color:#660">,</span><span style=3D"color:#000"> lhs</span=
><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#080">" and "</span><span style=3D"color:#660">,=
</span><span style=3D"color:#000"> rhs</span><span style=3D"color:#660">);<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"co=
lor:#008">return</span><span style=3D"color:#000"> lhs </span><span style=
=3D"color:#660">&&</span><span style=3D"color:#000"> rhs</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"><br></span><span =
style=3D"color:#660">}</span><span style=3D"color:#000"><br><br></span></di=
v></code></div><div><div><br></div></div></div></blockquote><div><br></div>=
<div>I fail to see how this new syntax is better. The proposed syntax [] -&=
gt; has a comprehensive meaning once you have seen a lambda. But this is a =
weak argument, I have to admit.<br></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div></div><div>Looking a=
t the big-array-copy scenario, I understand this as a case where a non-inli=
ned function gets called and you want to redirect the constructor call of t=
he lazy thunk (creating the by value "return" value) to do its co=
nstruction directly in the receiving variable, presuming that, as the varia=
ble type is "big" the ABI will have the caller of the lazy thunk =
provide an address to construct the value in. The lazy thunk can use differ=
ent constructors at different call sites which is nice in combination with =
not having to see the callee source code. This has significant performance =
advantage in the case that the value is large and does not have a lightweig=
ht move possibility. Apart from std::array all standard containers have che=
ap moves=C2=A0 so the usefulness is further reduced compared to a regular b=
y value parameter which is moved into the destination except for objects wi=
th large C or std arrays. Again: Is this functionality really so important =
that it warrants hijacking the original feature at the cost of making it le=
ss useful for its original purpose?</div></div><div><br></div></div></block=
quote><div><br></div><div>As Edward said, this is not only about big object=
s with inefficient moves, but also types that are neither copyable nor move=
able: for instance std::atomic or std::mutex.</div><div>Also, I have the fe=
eling that lazy parameters would be an efficient way to create complex obje=
cts without relying on emplace fonctions and std::piecewise_construct.</div=
><div>I asked before if my feeling on this subject was shared, but the disc=
ussion drifted away.<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/cc20625c-804f-4ad2-8c38-ce443e7314ec%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/cc20625c-804f-4ad2-8c38-ce443e7314ec=
%40isocpp.org</a>.<br />
------=_Part_18132_1366291150.1527956431526--
------=_Part_18131_119932819.1527956431525--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Sun, 3 Jun 2018 08:55:01 +0100
Raw View
--00000000000034a4a7056db8237e
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Sat, 2 Jun 2018, 17:20 , <florian.csdt@gmail.com> wrote:
> I know other people already have answered your questions, but I would lik=
e
> to give my point of view.
>
> Le samedi 2 juin 2018 00:52:34 UTC+2, Bengt Gustafsson a =C3=A9crit :
>>
>> Considering forwarding of lazy parameters to functions that may or may
>> not use them it becomes very hard to use them if they can only be evalua=
ted
>> once, or the code must make copies just in case, which defeats the purpo=
se
>> of the feature. I don't think that avoiding a copy during initialization=
is
>> a motivating purpose which should be allowed to rule the definition,
>> instead we should focus on being able to mimic the shortcut operators an=
d
>> operator? and the classical logging scenario. Here is a nasty example:
>>
>> bool andand([]->bool lhs, []->bool rhs)
>> {
>> Log("Performing andand on", lhs, " and ", rhs); // Variadic log
>> with lazy parameters only evaluated if logging is enabled.
>> return lhs() && rhs(); // This is UB if logging is enabled!
>> }
>>
>>
>>
> If you really want something like that you could imagine doing the
> following:
> bool andand([] -> bool lhs_lazy, [] -> bool rhs_lazy) {
> std::optional<bool> lhs_v, rhs_v;
> auto lhs =3D [&] () -> bool { if (!lhs_v) { lhs_v =3D lhs_lazy(); } ret=
urn
> lhs_v.value(); };
> auto rhs =3D [&] () -> bool { if (!rhs_v) { rhs_v =3D rhs_lazy(); } ret=
urn
> rhs_v.value(); };
>
> Log("Performing andand on", lhs(), " and ", rhs());
> return lhs() && rhs();
> }
>
> This would allow the kind of behavior you want (parameters will be
> evaluated only if they are needed), while keeping lazy arguments returnin=
g
> pr-values.
> We would need to standardize lambda captures relating to lazy parameters,
> but it would be worth it.
>
> However, if you allow multiple evaluation of the expression: either you
> will not be able to return a pr-value (with caching), or you will have
> problems with overlapping lifetime of the same objects...
> So you can implement what you want with what I propose, but I cannot
> implement what I want with what you propose.
>
>
It should be possible to implement multiple evaluation without caching by
storing lifetime extended temporaries in a conventionally located stack
frame and then not restoring (or only partially restoring) the stack
pointer on return from evaluation. This should be technically possible on
any platform where alloca is implementable.
The stack would look like: (growing downwards)
caller
callee
lazy1a temporaries
lazy2 temporaries
lazy1b temporaries
inner function
Here lazy1 is evaluated twice within the same expression, giving two sets
of temporaries. The temporaries would be destructed and their stack space
reclaimed at the end of the full-expression in the callee. Note that the
stack space used is bounded by the size of the expression in the callee.
This would have the advantage that scope, lifetime and stack location would
be more conventionally correlated, and may be technically easier to
implement than storing temporaries within the stack frame of the caller.
>> Apart from showing the problems with evaluate once principle this exampl=
e
>> rasies a couple of syntactical issues:
>>
>> 1) How do we declare a variadic template with lazy parameters?
>>
>
> Is there any problem with this?
> template <class... Args>
> void Log([] -> Args... args);
>
>
>
>> 2) Is is logical to forward-by-lazy by not using postfix(). If so, how
>> many of us will add the () by mistake when calling Log, accidentally (bu=
t
>> silently) evaluating the lazy parameter and forwarding the resulting val=
ue
>> as a (very simple) lazy expression to Log?
>>
> Lazy parameter forwarding is just an optimization a compiler would be abl=
e
> to do. But there is no reason it should be in the language: if Log takes
> lazy parameters, when you "evaluate" a lazy parameter to forward to Log,
> you will create a new lazy expression that will evaluate the first lazy
> expression when it will be evaluated.
> With or without a proper lazy parameter forwarding, the behaviour of the
> program will be *exactly* the same.
>
>
>
>> 3) Could it be considered to use postfix [] (empty bracket) to "derefer"
>> a lazy parameter to make it stand out more from function application?
>>
>
> I have no opinion on what syntax should be used to "evaluate" a lazy
> expression. For now the majority seems to prefer postfix ().
>
>
>>
>> Personally I still think that you should not have to annotate the use of
>> a lazy parameter in the called function, just as the value/reference
>> distinction this is something that the function author will have close t=
o
>> the top of her head when writing the code. This would nullify the 2) iss=
ue
>> above. Maybe it could be complemented by a template function std::eager(=
)
>> which makes sure evaluation is done even if forwarding to a function tha=
t
>> may take a lazy parameter. I don't have an example where this would be
>> important though, it seems a bit backwards.
>>
>
> If you want an expression to be executed even when passed as a lazy
> parameter, just create a local variable constructed from your expression,
> and pass this variable as the lazy parameter.
> bool foo() {
> bool lhs =3D bar(0); // this expression evaluation is forced here
> return lhs && bar(1); // the evaluation of bar(1) might not happen
> }
>
>
>
>
>>
>> I think the best would be to view this as a new kind of reference,
>> possibly using the | token to signify it. That is, it works like a
>> reference, except that before the first use it is evaluated (using the f=
lag
>> to check this). As for other references there is no indicating at the us=
age
>> site, as other (lvalue) references it is transparently forwarded to
>> subordinate functions (for example Log in my example). The issue of how =
to
>> write a template function has an obvious answer, and, I daresay, there
>> should be no syntax issues as we have the example of using the & charact=
er
>> which as an operator is parallel to | to indicate a type of reference
>> already.
>>
>> // Variadic Log with lazy parameters only evaluated if logging is enable=
d.
>> template<typename T, typename... Ts> Log(T| head, Ts| tail)
>> {
>> if (log_enabled) {
>> cout << head;
>> Log(tail...);
>> }
>> }
>> bool andand(bool| lhs, bool| rhs)
>> {
>> Log("Performing andand on", lhs, " and ", rhs);
>> return lhs && rhs;
>> }
>>
>>
>>
> I fail to see how this new syntax is better. The proposed syntax [] -> ha=
s
> a comprehensive meaning once you have seen a lambda. But this is a weak
> argument, I have to admit.
>
>
>> Looking at the big-array-copy scenario, I understand this as a case wher=
e
>> a non-inlined function gets called and you want to redirect the construc=
tor
>> call of the lazy thunk (creating the by value "return" value) to do its
>> construction directly in the receiving variable, presuming that, as the
>> variable type is "big" the ABI will have the caller of the lazy thunk
>> provide an address to construct the value in. The lazy thunk can use
>> different constructors at different call sites which is nice in combinat=
ion
>> with not having to see the callee source code. This has significant
>> performance advantage in the case that the value is large and does not h=
ave
>> a lightweight move possibility. Apart from std::array all standard
>> containers have cheap moves so the usefulness is further reduced compar=
ed
>> to a regular by value parameter which is moved into the destination exce=
pt
>> for objects with large C or std arrays. Again: Is this functionality rea=
lly
>> so important that it warrants hijacking the original feature at the cost=
of
>> making it less useful for its original purpose?
>>
>>
> As Edward said, this is not only about big objects with inefficient moves=
,
> but also types that are neither copyable nor moveable: for instance
> std::atomic or std::mutex.
> Also, I have the feeling that lazy parameters would be an efficient way t=
o
> create complex objects without relying on emplace fonctions and
> std::piecewise_construct.
> I asked before if my feeling on this subject was shared, but the
> discussion drifted away.
>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/=
unsubscribe
> .
> To unsubscribe from this group and all its topics, 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/cc20625c-804=
f-4ad2-8c38-ce443e7314ec%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/cc20625c-80=
4f-4ad2-8c38-ce443e7314ec%40isocpp.org?utm_medium=3Demail&utm_source=3Dfoot=
er>
> .
>
--=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/CAJnLdObwz9LJQGtquyGFsGSQawuLWH9kbAQQZjS9LKrTVxY=
iNQ%40mail.gmail.com.
--00000000000034a4a7056db8237e
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"auto"><div><br><br><div class=3D"gmail_quote"><div dir=3D"ltr">=
On Sat, 2 Jun 2018, 17:20 , <<a href=3D"mailto:florian.csdt@gmail.com">f=
lorian.csdt@gmail.com</a>> wrote:<br></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr">I know other people already have answered your questions=
, but I would like to give my point of view.<br><br>Le samedi 2 juin 2018 0=
0:52:34 UTC+2, Bengt Gustafsson a =C3=A9crit=C2=A0:<blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr">Considering forwarding of lazy parameters =
to functions that may or may not use them it becomes very hard to use them =
if they can only be evaluated once, or the code must make copies just in ca=
se, which defeats the purpose of the feature. I don't think that avoidi=
ng a copy during initialization is a motivating purpose which should be all=
owed to rule the definition, instead we should focus on being able to mimic=
the shortcut operators and operator? and the classical logging scenario. H=
ere is a nasty example:<div><br></div><div style=3D"background-color:rgb(25=
0,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1p=
x;word-wrap:break-word"><code><div><span style=3D"color:#008">bool</span><s=
pan style=3D"color:#000"> andand</span><span style=3D"color:#660">([]-><=
/span><span style=3D"color:#008">bool</span><span style=3D"color:#000"> lhs=
</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#660">[]-></span><span style=3D"color:#008">bool<=
/span><span style=3D"color:#000"> rhs</span><span style=3D"color:#660">)</s=
pan><span style=3D"color:#000"><br></span><span style=3D"color:#660">{</spa=
n><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:=
#606">Log</span><span style=3D"color:#660">(</span><span style=3D"color:#08=
0">"Performing andand on"</span><span style=3D"color:#660">,</spa=
n><span style=3D"color:#000"> lhs</span><span style=3D"color:#660">,</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#080">" and &q=
uot;</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> r=
hs</span><span style=3D"color:#660">);</span><span style=3D"color:#000"> =
=C2=A0 </span><span style=3D"color:#800">// Variadic log with lazy paramete=
rs only evaluated if logging is enabled.</span><span style=3D"color:#000"><=
br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span style=
=3D"color:#000"> lhs</span><span style=3D"color:#660">()</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">&&</span><span s=
tyle=3D"color:#000"> rhs</span><span style=3D"color:#660">();</span><span s=
tyle=3D"color:#000"> =C2=A0 =C2=A0</span><span style=3D"color:#800">// This=
is UB if logging is enabled!</span><span style=3D"color:#000"><br></span><=
span style=3D"color:#660">}</span><span style=3D"color:#000"><br><br></span=
></div></code></div><div><br></div></div></blockquote><div><br></div><div>I=
f you really want something like that you could imagine doing the following=
:</div><div><div style=3D"background-color:rgb(250,250,250);border-color:rg=
b(187,187,187);border-style:solid;border-width:1px" class=3D"m_-29657603705=
62034332prettyprint"><code class=3D"m_-2965760370562034332prettyprint"><div=
class=3D"m_-2965760370562034332subprettyprint"><span style=3D"color:#008" =
class=3D"m_-2965760370562034332styled-by-prettify">bool</span><span style=
=3D"color:#000" class=3D"m_-2965760370562034332styled-by-prettify"> andand<=
/span><span style=3D"color:#660" class=3D"m_-2965760370562034332styled-by-p=
rettify">([]</span><span style=3D"color:#000" class=3D"m_-29657603705620343=
32styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_-296576=
0370562034332styled-by-prettify">-></span><span style=3D"color:#000" cla=
ss=3D"m_-2965760370562034332styled-by-prettify"> </span><span style=3D"colo=
r:#008" class=3D"m_-2965760370562034332styled-by-prettify">bool</span><span=
style=3D"color:#000" class=3D"m_-2965760370562034332styled-by-prettify"> l=
hs_lazy</span><span style=3D"color:#660" class=3D"m_-2965760370562034332sty=
led-by-prettify">,</span><span style=3D"color:#000" class=3D"m_-29657603705=
62034332styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_-=
2965760370562034332styled-by-prettify">[]</span><span style=3D"color:#000" =
class=3D"m_-2965760370562034332styled-by-prettify"> </span><span style=3D"c=
olor:#660" class=3D"m_-2965760370562034332styled-by-prettify">-></span><=
span style=3D"color:#000" class=3D"m_-2965760370562034332styled-by-prettify=
"> </span><span style=3D"color:#008" class=3D"m_-2965760370562034332styled-=
by-prettify">bool</span><span style=3D"color:#000" class=3D"m_-296576037056=
2034332styled-by-prettify"> rhs_lazy</span><span style=3D"color:#660" class=
=3D"m_-2965760370562034332styled-by-prettify">)</span><span style=3D"color:=
#000" class=3D"m_-2965760370562034332styled-by-prettify"> </span><span styl=
e=3D"color:#660" class=3D"m_-2965760370562034332styled-by-prettify">{</span=
><span style=3D"color:#000" class=3D"m_-2965760370562034332styled-by-pretti=
fy"><br>=C2=A0 std</span><span style=3D"color:#660" class=3D"m_-29657603705=
62034332styled-by-prettify">::</span><span style=3D"color:#000" class=3D"m_=
-2965760370562034332styled-by-prettify">optional</span><span style=3D"color=
:#080" class=3D"m_-2965760370562034332styled-by-prettify"><bool></spa=
n><span style=3D"color:#000" class=3D"m_-2965760370562034332styled-by-prett=
ify"> lhs_v</span><span style=3D"color:#660" class=3D"m_-296576037056203433=
2styled-by-prettify">,</span><span style=3D"color:#000" class=3D"m_-2965760=
370562034332styled-by-prettify"> rhs_v</span><span style=3D"color:#660" cla=
ss=3D"m_-2965760370562034332styled-by-prettify">;</span><code class=3D"m_-2=
965760370562034332prettyprint"><span style=3D"color:#000" class=3D"m_-29657=
60370562034332styled-by-prettify"><br>=C2=A0 </span><span style=3D"color:#0=
08" class=3D"m_-2965760370562034332styled-by-prettify">auto</span><span sty=
le=3D"color:#000" class=3D"m_-2965760370562034332styled-by-prettify"> lhs <=
/span><span style=3D"color:#660" class=3D"m_-2965760370562034332styled-by-p=
rettify">=3D</span><span style=3D"color:#000" class=3D"m_-29657603705620343=
32styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_-296576=
0370562034332styled-by-prettify">[&]</span><span style=3D"color:#000" c=
lass=3D"m_-2965760370562034332styled-by-prettify"> </span><span style=3D"co=
lor:#660" class=3D"m_-2965760370562034332styled-by-prettify">()</span><span=
style=3D"color:#000" class=3D"m_-2965760370562034332styled-by-prettify"> <=
/span><span style=3D"color:#660" class=3D"m_-2965760370562034332styled-by-p=
rettify">-></span><span style=3D"color:#000" class=3D"m_-296576037056203=
4332styled-by-prettify"> </span><span style=3D"color:#008" class=3D"m_-2965=
760370562034332styled-by-prettify">bool</span><span style=3D"color:#000" cl=
ass=3D"m_-2965760370562034332styled-by-prettify"> </span><span style=3D"col=
or:#660" class=3D"m_-2965760370562034332styled-by-prettify">{</span><span s=
tyle=3D"color:#000" class=3D"m_-2965760370562034332styled-by-prettify"> </s=
pan><span style=3D"color:#008" class=3D"m_-2965760370562034332styled-by-pre=
ttify">if</span><span style=3D"color:#000" class=3D"m_-2965760370562034332s=
tyled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_-296576037=
0562034332styled-by-prettify">(!</span><span style=3D"color:#000" class=3D"=
m_-2965760370562034332styled-by-prettify">lhs_v</span><span style=3D"color:=
#660" class=3D"m_-2965760370562034332styled-by-prettify">)</span><span styl=
e=3D"color:#000" class=3D"m_-2965760370562034332styled-by-prettify"> </span=
><span style=3D"color:#660" class=3D"m_-2965760370562034332styled-by-pretti=
fy">{</span><span style=3D"color:#000" class=3D"m_-2965760370562034332style=
d-by-prettify"> lhs_v </span><span style=3D"color:#660" class=3D"m_-2965760=
370562034332styled-by-prettify">=3D</span><span style=3D"color:#000" class=
=3D"m_-2965760370562034332styled-by-prettify"> lhs_lazy</span><span style=
=3D"color:#660" class=3D"m_-2965760370562034332styled-by-prettify">();</spa=
n><span style=3D"color:#000" class=3D"m_-2965760370562034332styled-by-prett=
ify"> </span><span style=3D"color:#660" class=3D"m_-2965760370562034332styl=
ed-by-prettify">}</span><span style=3D"color:#000" class=3D"m_-296576037056=
2034332styled-by-prettify"> </span><span style=3D"color:#008" class=3D"m_-2=
965760370562034332styled-by-prettify">return</span><span style=3D"color:#00=
0" class=3D"m_-2965760370562034332styled-by-prettify"> lhs_v</span><span st=
yle=3D"color:#660" class=3D"m_-2965760370562034332styled-by-prettify">.</sp=
an><span style=3D"color:#000" class=3D"m_-2965760370562034332styled-by-pret=
tify">value</span><span style=3D"color:#660" class=3D"m_-296576037056203433=
2styled-by-prettify">();</span><span style=3D"color:#000" class=3D"m_-29657=
60370562034332styled-by-prettify"> </span><span style=3D"color:#660" class=
=3D"m_-2965760370562034332styled-by-prettify">};</span><span style=3D"color=
:#000" class=3D"m_-2965760370562034332styled-by-prettify"><br></span></code=
><code class=3D"m_-2965760370562034332prettyprint"><span style=3D"color:#00=
0" class=3D"m_-2965760370562034332styled-by-prettify">=C2=A0 </span><span s=
tyle=3D"color:#008" class=3D"m_-2965760370562034332styled-by-prettify">auto=
</span><span style=3D"color:#000" class=3D"m_-2965760370562034332styled-by-=
prettify"> rhs </span><span style=3D"color:#660" class=3D"m_-29657603705620=
34332styled-by-prettify">=3D</span><span style=3D"color:#000" class=3D"m_-2=
965760370562034332styled-by-prettify"> </span><span style=3D"color:#660" cl=
ass=3D"m_-2965760370562034332styled-by-prettify">[&]</span><span style=
=3D"color:#000" class=3D"m_-2965760370562034332styled-by-prettify"> </span>=
<span style=3D"color:#660" class=3D"m_-2965760370562034332styled-by-prettif=
y">()</span><span style=3D"color:#000" class=3D"m_-2965760370562034332style=
d-by-prettify"> </span><span style=3D"color:#660" class=3D"m_-2965760370562=
034332styled-by-prettify">-></span><span style=3D"color:#000" class=3D"m=
_-2965760370562034332styled-by-prettify"> </span><span style=3D"color:#008"=
class=3D"m_-2965760370562034332styled-by-prettify">bool</span><span style=
=3D"color:#000" class=3D"m_-2965760370562034332styled-by-prettify"> </span>=
<span style=3D"color:#660" class=3D"m_-2965760370562034332styled-by-prettif=
y">{</span><span style=3D"color:#000" class=3D"m_-2965760370562034332styled=
-by-prettify"> </span><span style=3D"color:#008" class=3D"m_-29657603705620=
34332styled-by-prettify">if</span><span style=3D"color:#000" class=3D"m_-29=
65760370562034332styled-by-prettify"> </span><span style=3D"color:#660" cla=
ss=3D"m_-2965760370562034332styled-by-prettify">(!</span><span style=3D"col=
or:#000" class=3D"m_-2965760370562034332styled-by-prettify">rhs_v</span><sp=
an style=3D"color:#660" class=3D"m_-2965760370562034332styled-by-prettify">=
)</span><span style=3D"color:#000" class=3D"m_-2965760370562034332styled-by=
-prettify"> </span><span style=3D"color:#660" class=3D"m_-29657603705620343=
32styled-by-prettify">{</span><span style=3D"color:#000" class=3D"m_-296576=
0370562034332styled-by-prettify"> rhs_v </span><span style=3D"color:#660" c=
lass=3D"m_-2965760370562034332styled-by-prettify">=3D</span><span style=3D"=
color:#000" class=3D"m_-2965760370562034332styled-by-prettify"> rhs_lazy</s=
pan><span style=3D"color:#660" class=3D"m_-2965760370562034332styled-by-pre=
ttify">();</span><span style=3D"color:#000" class=3D"m_-2965760370562034332=
styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_-29657603=
70562034332styled-by-prettify">}</span><span style=3D"color:#000" class=3D"=
m_-2965760370562034332styled-by-prettify"> </span><span style=3D"color:#008=
" class=3D"m_-2965760370562034332styled-by-prettify">return</span><span sty=
le=3D"color:#000" class=3D"m_-2965760370562034332styled-by-prettify"> rhs_v=
</span><span style=3D"color:#660" class=3D"m_-2965760370562034332styled-by-=
prettify">.</span><span style=3D"color:#000" class=3D"m_-296576037056203433=
2styled-by-prettify">value</span><span style=3D"color:#660" class=3D"m_-296=
5760370562034332styled-by-prettify">();</span><span style=3D"color:#000" cl=
ass=3D"m_-2965760370562034332styled-by-prettify"> </span><span style=3D"col=
or:#660" class=3D"m_-2965760370562034332styled-by-prettify">};</span><span =
style=3D"color:#000" class=3D"m_-2965760370562034332styled-by-prettify"><br=
></span></code><span style=3D"color:#000" class=3D"m_-2965760370562034332st=
yled-by-prettify">=C2=A0 </span><br><span style=3D"color:#000" class=3D"m_-=
2965760370562034332styled-by-prettify"><code><span style=3D"color:#606">=C2=
=A0 Log</span><span style=3D"color:#660">(</span><span style=3D"color:#080"=
>"Performing andand on"</span><span style=3D"color:#660">,</span>=
<span style=3D"color:#000"> lhs</span><span style=3D"color:#660">(),</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#080">" and &q=
uot;</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> r=
hs</span><span style=3D"color:#660">());</span></code><br>=C2=A0 return lhs=
() && rhs();<br></span><span style=3D"color:#660" class=3D"m_-29657=
60370562034332styled-by-prettify">}</span><span style=3D"color:#000" class=
=3D"m_-2965760370562034332styled-by-prettify"><br></span></div></code></div=
></div><div><br></div><div>This would allow the kind of behavior you want (=
parameters will be evaluated only if they are needed), while keeping lazy a=
rguments returning pr-values.</div><div>We would need to standardize lambda=
captures relating to lazy parameters, but it would be worth it.</div><div>=
<br></div><div>However, if you allow multiple evaluation of the expression:=
either you will not be able to return a pr-value (with caching), or you wi=
ll have problems with overlapping lifetime of the same objects...</div><div=
>So you can implement what you want with what I propose, but I cannot imple=
ment what I want with what you propose.<br></div><div>=C2=A0</div></div></b=
lockquote></div></div><div dir=3D"auto"><br></div><div dir=3D"auto">It shou=
ld be possible to implement multiple evaluation without caching by storing =
lifetime extended temporaries in a conventionally located stack frame and t=
hen not restoring (or only partially restoring) the stack pointer on return=
from evaluation. This should be technically possible on any platform where=
alloca is implementable.=C2=A0</div><div dir=3D"auto"><br></div><div dir=
=3D"auto">The stack would look like: (growing downwards)=C2=A0</div><div di=
r=3D"auto"><br></div><div dir=3D"auto">caller</div><div dir=3D"auto">callee=
</div><div dir=3D"auto">lazy1a temporaries</div><div dir=3D"auto">lazy2 tem=
poraries</div><div dir=3D"auto">lazy1b temporaries</div><div dir=3D"auto">i=
nner function</div><div dir=3D"auto"><br></div><div dir=3D"auto">Here lazy1=
is evaluated twice within the same expression, giving two sets of temporar=
ies. The temporaries would be destructed and their stack space reclaimed at=
the end of the full-expression in the callee. Note that the stack space us=
ed is bounded by the size of the expression in the callee.=C2=A0</div><div =
dir=3D"auto"><br></div><div dir=3D"auto">This would have the advantage that=
scope, lifetime and stack location would be more conventionally correlated=
, and may be technically easier to implement than storing temporaries withi=
n the stack frame of the caller.=C2=A0</div><div dir=3D"auto"><br></div><di=
v dir=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gmail_quote"><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #cc=
c solid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr"><div><br></div><div>Apart from showing the problem=
s with evaluate once principle this example rasies a couple of syntactical =
issues:</div><div><br></div><div>1) How do we declare a variadic template w=
ith lazy parameters?</div></div></blockquote><div><br></div><div>Is there a=
ny problem with this?</div><div><div style=3D"background-color:rgb(250,250,=
250);border-color:rgb(187,187,187);border-style:solid;border-width:1px" cla=
ss=3D"m_-2965760370562034332prettyprint"><code class=3D"m_-2965760370562034=
332prettyprint"><div class=3D"m_-2965760370562034332subprettyprint"><span s=
tyle=3D"color:#606" class=3D"m_-2965760370562034332styled-by-prettify">temp=
late <class... Args><br>void Log([] -> Args... args);</span><span =
style=3D"color:#660" class=3D"m_-2965760370562034332styled-by-prettify"></s=
pan></div></code></div><br></div><div>=C2=A0</div><blockquote class=3D"gmai=
l_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr"><div>2) Is is logical to forward-by-lazy by=
not using postfix(). If so, how many of us will add the () by mistake when=
calling Log, accidentally (but silently) evaluating the lazy parameter and=
forwarding the resulting value as a (very simple) lazy expression to Log?<=
/div></div></blockquote><div>Lazy parameter forwarding is just an optimizat=
ion a compiler would be able to do. But there is no reason it should be in =
the language: if Log takes lazy parameters, when you "evaluate" a=
lazy parameter to forward to Log, you will create a new lazy expression th=
at will evaluate the first lazy expression when it will be evaluated.</div>=
<div>With or without a proper lazy parameter forwarding, the behaviour of t=
he program will be <i>exactly</i> the same.<br></div><div><br></div><div>=
=C2=A0</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>3=
) Could it be considered to use postfix [] (empty bracket) to "derefer=
" a lazy parameter to make it stand out more from function application=
?</div></div></blockquote><div><br></div><div>I have no opinion on what syn=
tax should be used to "evaluate" a lazy expression. For now the m=
ajority seems to prefer postfix ().<br></div><div>=C2=A0</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><div><br></div><div>Personally =
I still think that you should not have to annotate the use of a lazy parame=
ter in the called function, just as the value/reference distinction this is=
something that the function author will have close to the top of her head =
when writing the code. This would nullify the 2) issue above. Maybe it coul=
d be complemented by a template function std::eager() which makes sure eval=
uation is done even if forwarding to a function that may take a lazy parame=
ter. I don't have an example where this would be important though, it s=
eems a bit backwards.</div></div></blockquote><div><br></div><div>If you wa=
nt an expression to be executed even when passed as a lazy parameter, just =
create a local variable constructed from your expression, and pass this var=
iable as the lazy parameter.</div><div><div style=3D"background-color:rgb(2=
50,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1=
px" class=3D"m_-2965760370562034332prettyprint"><code class=3D"m_-296576037=
0562034332prettyprint"><div class=3D"m_-2965760370562034332subprettyprint">=
<span style=3D"color:#606" class=3D"m_-2965760370562034332styled-by-prettif=
y">bool foo() {<br>=C2=A0 bool lhs =3D bar(0); // this expression evaluatio=
n is forced here<br>=C2=A0 return lhs && bar(1); // the evaluation =
of bar(1) might not happen<br>}</span><span style=3D"color:#660" class=3D"m=
_-2965760370562034332styled-by-prettify"></span></div></code></div><br><br>=
</div><div>=C2=A0</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><br></div><div>I think the best would be to view this as a new ki=
nd of reference, possibly using the | token to signify it. That is, it work=
s like a reference, except that before the first use it is evaluated (using=
the flag to check this). As for other references there is no indicating at=
the usage site, as other (lvalue) references it is transparently forwarded=
to subordinate functions (for example Log in my example). The issue of how=
to write a template function has an obvious answer, and, I daresay, there =
should be no syntax issues as we have the example of using the & charac=
ter which as an operator is parallel to | to indicate a type of reference a=
lready.</div><div><br></div><div style=3D"background-color:rgb(250,250,250)=
;border-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wra=
p:break-word"><code><div><span style=3D"color:#800">// Variadic Log with la=
zy parameters only evaluated if logging is enabled.</span><span style=3D"co=
lor:#000"><br></span><span style=3D"color:#008">template</span><span style=
=3D"color:#660"><</span><span style=3D"color:#008">typename</span><span =
style=3D"color:#000"> T</span><span style=3D"color:#660">,</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#008">typename</span><span st=
yle=3D"color:#660">...</span><span style=3D"color:#000"> </span><span style=
=3D"color:#606">Ts</span><span style=3D"color:#660">></span><span style=
=3D"color:#000"> </span><span style=3D"color:#606">Log</span><span style=3D=
"color:#660">(</span><span style=3D"color:#000">T</span><span style=3D"colo=
r:#660">|</span><span style=3D"color:#000"> head</span><span style=3D"color=
:#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#606=
">Ts</span><span style=3D"color:#660">|</span><span style=3D"color:#000"> t=
ail</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><br=
></span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color:#008">if</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">(</span><span style=3D"color:#0=
00">log_enabled</span><span style=3D"color:#660">)</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#0=
00"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 cout </span><span style=3D"color:#660">=
<<</span><span style=3D"color:#000"> head</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:#606">Log</span><span style=3D"color:#660">(</spa=
n><span style=3D"color:#000">tail</span><span style=3D"color:#660">...);</s=
pan><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"colo=
r:#660">}</span><span style=3D"color:#000"><br></span><span style=3D"color:=
#660">}</span><span style=3D"color:#000"><br></span><span style=3D"color:#0=
08">bool</span><span style=3D"color:#000"> andand</span><span style=3D"colo=
r:#660">(</span><span style=3D"color:#008">bool</span><span style=3D"color:=
#660">|</span><span style=3D"color:#000"> lhs</span><span style=3D"color:#6=
60">,</span><span style=3D"color:#000"> </span><span style=3D"color:#008">b=
ool</span><span style=3D"color:#660">|</span><span style=3D"color:#000"> rh=
s</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><br><=
/span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color:#606">Log</span><span style=3D"color=
:#660">(</span><span style=3D"color:#080">"Performing andand on"<=
/span><span style=3D"color:#660">,</span><span style=3D"color:#000"> lhs</s=
pan><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span><=
span style=3D"color:#080">" and "</span><span style=3D"color:#660=
">,</span><span style=3D"color:#000"> rhs</span><span style=3D"color:#660">=
);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D=
"color:#008">return</span><span style=3D"color:#000"> lhs </span><span styl=
e=3D"color:#660">&&</span><span style=3D"color:#000"> rhs</span><sp=
an style=3D"color:#660">;</span><span style=3D"color:#000"><br></span><span=
style=3D"color:#660">}</span><span style=3D"color:#000"><br><br></span></d=
iv></code></div><div><div><br></div></div></div></blockquote><div><br></div=
><div>I fail to see how this new syntax is better. The proposed syntax [] -=
> has a comprehensive meaning once you have seen a lambda. But this is a=
weak argument, I have to admit.<br></div><div>=C2=A0</div><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr"><div><div></div><div>Looking at th=
e big-array-copy scenario, I understand this as a case where a non-inlined =
function gets called and you want to redirect the constructor call of the l=
azy thunk (creating the by value "return" value) to do its constr=
uction directly in the receiving variable, presuming that, as the variable =
type is "big" the ABI will have the caller of the lazy thunk prov=
ide an address to construct the value in. The lazy thunk can use different =
constructors at different call sites which is nice in combination with not =
having to see the callee source code. This has significant performance adva=
ntage in the case that the value is large and does not have a lightweight m=
ove possibility. Apart from std::array all standard containers have cheap m=
oves=C2=A0 so the usefulness is further reduced compared to a regular by va=
lue parameter which is moved into the destination except for objects with l=
arge C or std arrays. Again: Is this functionality really so important that=
it warrants hijacking the original feature at the cost of making it less u=
seful for its original purpose?</div></div><div><br></div></div></blockquot=
e><div><br></div><div>As Edward said, this is not only about big objects wi=
th inefficient moves, but also types that are neither copyable nor moveable=
: for instance std::atomic or std::mutex.</div><div>Also, I have the feelin=
g that lazy parameters would be an efficient way to create complex objects =
without relying on emplace fonctions and std::piecewise_construct.</div><di=
v>I asked before if my feeling on this subject was shared, but the discussi=
on drifted away.<br></div></div>
<p></p>
-- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/unsubscribe" target=3D"_blan=
k" rel=3D"noreferrer">https://groups.google.com/a/isocpp.org/d/topic/std-pr=
oposals/5oUZysJB4HE/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_blank" rel=3D"n=
oreferrer">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank" rel=3D"noreferrer">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/cc20625c-804f-4ad2-8c38-ce443e7314ec%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank" =
rel=3D"noreferrer">https://groups.google.com/a/isocpp.org/d/msgid/std-propo=
sals/cc20625c-804f-4ad2-8c38-ce443e7314ec%40isocpp.org</a>.<br>
</blockquote></div></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/CAJnLdObwz9LJQGtquyGFsGSQawuLWH9kbAQQ=
ZjS9LKrTVxYiNQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdObwz9LJQGtq=
uyGFsGSQawuLWH9kbAQQZjS9LKrTVxYiNQ%40mail.gmail.com</a>.<br />
--00000000000034a4a7056db8237e--
.
Author: Magnus Fromreide <magfr@lysator.liu.se>
Date: Sun, 3 Jun 2018 13:16:14 +0200
Raw View
Hello
I am more than a little concerned about all this talk of multiple evaluatio=
n
of lazy arguments.
I presume that everone agrees that given
void f([]->int);
then after
int a =3D 10;
f(a++);
the value of a is either 10 or 11, no other values are possible.
(BTW, What a great obfuscation tool this would be even with this limitation=
)
This in turn means that any second evaluation of the lazy expression must
be forbidden unless the compiler can prove it to be side effect free.
On Sun, Jun 03, 2018 at 08:55:01AM +0100, 'Edward Catmur' via ISO C++ Stand=
ard - Future Proposals wrote:
> On Sat, 2 Jun 2018, 17:20 , <florian.csdt@gmail.com> wrote:
>=20
> > I know other people already have answered your questions, but I would l=
ike
> > to give my point of view.
> >
> > Le samedi 2 juin 2018 00:52:34 UTC+2, Bengt Gustafsson a =C3=A9crit :
> >>
> >> Considering forwarding of lazy parameters to functions that may or may
> >> not use them it becomes very hard to use them if they can only be eval=
uated
> >> once, or the code must make copies just in case, which defeats the pur=
pose
> >> of the feature. I don't think that avoiding a copy during initializati=
on is
> >> a motivating purpose which should be allowed to rule the definition,
> >> instead we should focus on being able to mimic the shortcut operators =
and
> >> operator? and the classical logging scenario. Here is a nasty example:
> >>
> >> bool andand([]->bool lhs, []->bool rhs)
> >> {
> >> Log("Performing andand on", lhs, " and ", rhs); // Variadic log
> >> with lazy parameters only evaluated if logging is enabled.
> >> return lhs() && rhs(); // This is UB if logging is enabled!
> >> }
> >>
> >>
> >>
> > If you really want something like that you could imagine doing the
> > following:
> > bool andand([] -> bool lhs_lazy, [] -> bool rhs_lazy) {
> > std::optional<bool> lhs_v, rhs_v;
> > auto lhs =3D [&] () -> bool { if (!lhs_v) { lhs_v =3D lhs_lazy(); } r=
eturn
> > lhs_v.value(); };
> > auto rhs =3D [&] () -> bool { if (!rhs_v) { rhs_v =3D rhs_lazy(); } r=
eturn
> > rhs_v.value(); };
> >
> > Log("Performing andand on", lhs(), " and ", rhs());
> > return lhs() && rhs();
> > }
> >
> > This would allow the kind of behavior you want (parameters will be
> > evaluated only if they are needed), while keeping lazy arguments return=
ing
> > pr-values.
> > We would need to standardize lambda captures relating to lazy parameter=
s,
> > but it would be worth it.
> >
> > However, if you allow multiple evaluation of the expression: either you
> > will not be able to return a pr-value (with caching), or you will have
> > problems with overlapping lifetime of the same objects...
> > So you can implement what you want with what I propose, but I cannot
> > implement what I want with what you propose.
> >
> >
>=20
> It should be possible to implement multiple evaluation without caching by
> storing lifetime extended temporaries in a conventionally located stack
> frame and then not restoring (or only partially restoring) the stack
> pointer on return from evaluation. This should be technically possible on
> any platform where alloca is implementable.
>=20
> The stack would look like: (growing downwards)
>=20
> caller
> callee
> lazy1a temporaries
> lazy2 temporaries
> lazy1b temporaries
> inner function
>=20
> Here lazy1 is evaluated twice within the same expression, giving two sets
> of temporaries. The temporaries would be destructed and their stack space
> reclaimed at the end of the full-expression in the callee. Note that the
> stack space used is bounded by the size of the expression in the callee.
>=20
> This would have the advantage that scope, lifetime and stack location wou=
ld
> be more conventionally correlated, and may be technically easier to
> implement than storing temporaries within the stack frame of the caller.
>=20
>=20
>=20
> >> Apart from showing the problems with evaluate once principle this exam=
ple
> >> rasies a couple of syntactical issues:
> >>
> >> 1) How do we declare a variadic template with lazy parameters?
> >>
> >
> > Is there any problem with this?
> > template <class... Args>
> > void Log([] -> Args... args);
> >
> >
> >
> >> 2) Is is logical to forward-by-lazy by not using postfix(). If so, how
> >> many of us will add the () by mistake when calling Log, accidentally (=
but
> >> silently) evaluating the lazy parameter and forwarding the resulting v=
alue
> >> as a (very simple) lazy expression to Log?
> >>
> > Lazy parameter forwarding is just an optimization a compiler would be a=
ble
> > to do. But there is no reason it should be in the language: if Log take=
s
> > lazy parameters, when you "evaluate" a lazy parameter to forward to Log=
,
> > you will create a new lazy expression that will evaluate the first lazy
> > expression when it will be evaluated.
> > With or without a proper lazy parameter forwarding, the behaviour of th=
e
> > program will be *exactly* the same.
> >
> >
> >
> >> 3) Could it be considered to use postfix [] (empty bracket) to "derefe=
r"
> >> a lazy parameter to make it stand out more from function application?
> >>
> >
> > I have no opinion on what syntax should be used to "evaluate" a lazy
> > expression. For now the majority seems to prefer postfix ().
> >
> >
> >>
> >> Personally I still think that you should not have to annotate the use =
of
> >> a lazy parameter in the called function, just as the value/reference
> >> distinction this is something that the function author will have close=
to
> >> the top of her head when writing the code. This would nullify the 2) i=
ssue
> >> above. Maybe it could be complemented by a template function std::eage=
r()
> >> which makes sure evaluation is done even if forwarding to a function t=
hat
> >> may take a lazy parameter. I don't have an example where this would be
> >> important though, it seems a bit backwards.
> >>
> >
> > If you want an expression to be executed even when passed as a lazy
> > parameter, just create a local variable constructed from your expressio=
n,
> > and pass this variable as the lazy parameter.
> > bool foo() {
> > bool lhs =3D bar(0); // this expression evaluation is forced here
> > return lhs && bar(1); // the evaluation of bar(1) might not happen
> > }
> >
> >
> >
> >
> >>
> >> I think the best would be to view this as a new kind of reference,
> >> possibly using the | token to signify it. That is, it works like a
> >> reference, except that before the first use it is evaluated (using the=
flag
> >> to check this). As for other references there is no indicating at the =
usage
> >> site, as other (lvalue) references it is transparently forwarded to
> >> subordinate functions (for example Log in my example). The issue of ho=
w to
> >> write a template function has an obvious answer, and, I daresay, there
> >> should be no syntax issues as we have the example of using the & chara=
cter
> >> which as an operator is parallel to | to indicate a type of reference
> >> already.
> >>
> >> // Variadic Log with lazy parameters only evaluated if logging is enab=
led.
> >> template<typename T, typename... Ts> Log(T| head, Ts| tail)
> >> {
> >> if (log_enabled) {
> >> cout << head;
> >> Log(tail...);
> >> }
> >> }
> >> bool andand(bool| lhs, bool| rhs)
> >> {
> >> Log("Performing andand on", lhs, " and ", rhs);
> >> return lhs && rhs;
> >> }
> >>
> >>
> >>
> > I fail to see how this new syntax is better. The proposed syntax [] -> =
has
> > a comprehensive meaning once you have seen a lambda. But this is a weak
> > argument, I have to admit.
> >
> >
> >> Looking at the big-array-copy scenario, I understand this as a case wh=
ere
> >> a non-inlined function gets called and you want to redirect the constr=
uctor
> >> call of the lazy thunk (creating the by value "return" value) to do it=
s
> >> construction directly in the receiving variable, presuming that, as th=
e
> >> variable type is "big" the ABI will have the caller of the lazy thunk
> >> provide an address to construct the value in. The lazy thunk can use
> >> different constructors at different call sites which is nice in combin=
ation
> >> with not having to see the callee source code. This has significant
> >> performance advantage in the case that the value is large and does not=
have
> >> a lightweight move possibility. Apart from std::array all standard
> >> containers have cheap moves so the usefulness is further reduced comp=
ared
> >> to a regular by value parameter which is moved into the destination ex=
cept
> >> for objects with large C or std arrays. Again: Is this functionality r=
eally
> >> so important that it warrants hijacking the original feature at the co=
st of
> >> making it less useful for its original purpose?
> >>
> >>
> > As Edward said, this is not only about big objects with inefficient mov=
es,
> > but also types that are neither copyable nor moveable: for instance
> > std::atomic or std::mutex.
> > Also, I have the feeling that lazy parameters would be an efficient way=
to
> > create complex objects without relying on emplace fonctions and
> > std::piecewise_construct.
> > I asked before if my feeling on this subject was shared, but the
> > discussion drifted away.
> >
> > --
> > You received this message because you are subscribed to a topic in the
> > Google Groups "ISO C++ Standard - Future Proposals" group.
> > To unsubscribe from this topic, visit
> > https://groups.google.com/a/isocpp.org/d/topic/std-proposals/5oUZysJB4H=
E/unsubscribe
> > .
> > To unsubscribe from this group and all its topics, 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/cc20625c-8=
04f-4ad2-8c38-ce443e7314ec%40isocpp.org
> > <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/cc20625c-=
804f-4ad2-8c38-ce443e7314ec%40isocpp.org?utm_medium=3Demail&utm_source=3Dfo=
oter>
> > .
> >
>=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.
> 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/isoc=
pp.org/d/msgid/std-proposals/CAJnLdObwz9LJQGtquyGFsGSQawuLWH9kbAQQZjS9LKrTV=
xYiNQ%40mail.gmail.com.
--=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/20180603111614.GA18455%40noemi.bahnhof.se.
.
Author: florian.csdt@gmail.com
Date: Sun, 3 Jun 2018 05:20:57 -0700 (PDT)
Raw View
------=_Part_24760_1209700703.1528028457396
Content-Type: multipart/alternative;
boundary="----=_Part_24761_1967935953.1528028457396"
------=_Part_24761_1967935953.1528028457396
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le dimanche 3 juin 2018 13:16:18 UTC+2, Magnus Fromreide a =C3=A9crit :
>
> Hello=20
>
> I am more than a little concerned about all this talk of multiple=20
> evaluation=20
> of lazy arguments.=20
>
> I presume that everone agrees that given=20
>
> void f([]->int);=20
>
> then after=20
>
> int a =3D 10;=20
> f(a++);=20
>
> the value of a is either 10 or 11, no other values are possible.=20
> (BTW, What a great obfuscation tool this would be even with this=20
> limitation)=20
>
This example is really great to show mutliple evaluations should not be=20
allowed, period.
BTW, the example I showed with manually caching the result in a lambda=20
gives this behavior: the lazy expression is evaluated once.
=20
>
> This in turn means that any second evaluation of the lazy expression must=
=20
> be forbidden unless the compiler can prove it to be side effect free.=20
>
> Unless the compiler inline both the caller and the lazy expression, it=20
will not be able to prove this side-effect free property.
And if both are inlined, all technical issues disappear.
@Edward
> It should be possible to implement multiple evaluation without caching by=
=20
> storing lifetime extended temporaries in a conventionally located stack=
=20
> frame and then not restoring (or only partially restoring) the stack=20
> pointer on return from evaluation. This should be technically possible on=
=20
> any platform where alloca is implementable.=20
>
> The stack would look like: (growing downwards)=20
>
> caller
> callee
> lazy1a temporaries
> lazy2 temporaries
> lazy1b temporaries
> inner function
>
> Here lazy1 is evaluated twice within the same expression, giving two sets=
=20
> of temporaries. The temporaries would be destructed and their stack space=
=20
> reclaimed at the end of the full-expression in the callee. Note that the=
=20
> stack space used is bounded by the size of the expression in the callee.=
=20
>
> This would have the advantage that scope, lifetime and stack location=20
> would be more conventionally correlated, and may be technically easier to=
=20
> implement than storing temporaries within the stack frame of the caller.=
=20
>
Unfortunatley, if the lazy expression "calls" alloca, the stack memory will=
=20
be deallocated when the lazy expression ends its scope. That's why=20
allocating this memory in the caller stack frame is much easier.
Also, how would you track down all destructors that would be needed to be=
=20
called?
If you want multiple scopes, you will need heap memory allocation at some=
=20
point, which is really not needed to have a very useful feature.
You can always create more complex objects from the simple lazy expression=
=20
that cannot be evaluated multiple times to achieve your goal.
Also, what if the lazy expression calls new: how do you track down the=20
multiple allocations?
If the lazy expression is very expensive, do you really want do execute the=
=20
all thing again?
Caching is the only sensible way to allow multiple evaluations, but this=20
forbids pr-values, with all the issues mentionned before.
And as I showed earlier, if a caller needs to cache the result, it can do=
=20
it. Whereas other proposals do not/cannot solve altogether the pr-value=20
issue, the lifetime issues and the performance issue.
Of course it needs a bit of boilerplate code to actually do the caching,=20
but this use case should be rare enough. And the caching code is really=20
understandable and easy to come up with, especially if you know the lazy=20
expression will always be evaluated.
One solution might be to have both: [] -> lazy parameter *without* caching =
=20
and [=3D] -> lazy parameter *with* caching (with no consideration on how it=
=20
is implemented).
Anyway, if you need multiple evaluations, why do you pass a lazy expression=
=20
and not a callable? That would make your intent much clearer.
--=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/5cdf347c-a54a-49bb-905f-dc392fedf121%40isocpp.or=
g.
------=_Part_24761_1967935953.1528028457396
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>Le dimanche 3 juin 2018 13:16:18 UTC+2, Magnus Fromrei=
de a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Hello
<br>
<br>I am more than a little concerned about all this talk of multiple evalu=
ation
<br>of lazy arguments.
<br>
<br>I presume that everone agrees that given
<br>
<br>void f([]->int);
<br>
<br>then after
<br>
<br>int a =3D 10;
<br>f(a++);
<br>
<br>the value of a is either 10 or 11, no other values are possible.
<br>(BTW, What a great obfuscation tool this would be even with this limita=
tion)
<br></blockquote><div><br></div><div><div>This example is really great to s=
how mutliple evaluations should not be allowed, period.</div><div>BTW,
the example I showed with manually caching the result in a lambda gives
this behavior: the lazy expression is evaluated once.</div></div><div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>This in turn means that any second evaluation of the lazy expression mu=
st
<br>be forbidden unless the compiler can prove it to be side effect free.
<br>
<br></blockquote>Unless the compiler inline both the caller and the lazy ex=
pression, it will not be able to prove this side-effect free property.<br>A=
nd if both are inlined, all technical issues disappear.<br><div><br></div><=
div>@Edward<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0px=
0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1e=
x;"><div><div dir=3D"auto">It should be possible to implement multiple eval=
uation=20
without caching by storing lifetime extended temporaries in a=20
conventionally located stack frame and then not restoring (or only=20
partially restoring) the stack pointer on return from evaluation. This=20
should be technically possible on any platform where alloca is=20
implementable.=C2=A0</div><div dir=3D"auto"><br></div><div dir=3D"auto">The=
stack would look like: (growing downwards)=C2=A0</div><div dir=3D"auto"><b=
r></div><div dir=3D"auto">caller</div><div dir=3D"auto">callee</div><div di=
r=3D"auto">lazy1a temporaries</div><div dir=3D"auto">lazy2 temporaries</div=
><div dir=3D"auto">lazy1b temporaries</div><div dir=3D"auto">inner function=
</div><div dir=3D"auto"><br></div><div dir=3D"auto">Here
lazy1 is evaluated twice within the same expression, giving two sets of
temporaries. The temporaries would be destructed and their stack space=20
reclaimed at the end of the full-expression in the callee. Note that the
stack space used is bounded by the size of the expression in the=20
callee.=C2=A0</div><div dir=3D"auto"><br></div><div dir=3D"auto">This would=
have=20
the advantage that scope, lifetime and stack location would be more=20
conventionally correlated, and may be technically easier to implement=20
than storing temporaries within the stack frame of the caller. <br></div></=
div></blockquote><div><br></div><div>Unfortunatley, if the lazy expression =
"calls" alloca, the stack memory will be deallocated when the laz=
y expression ends its scope. That's why allocating this memory in the c=
aller stack frame is much easier.</div><div>Also, how would you track down =
all destructors that would be needed to be called?</div><div>If you want mu=
ltiple scopes, you will need heap memory allocation at some point, which is=
really not needed to have a very useful feature.</div><div>You can always =
create more complex objects from the simple lazy expression that cannot be =
evaluated multiple times to achieve your goal.<br></div><div><br></div><div=
>Also, what if the lazy expression calls new: how do you track down the mul=
tiple allocations?</div><div>If the lazy expression is very expensive, do y=
ou really want do execute the all thing again?<br></div><div>Caching is the=
only sensible way to allow multiple evaluations, but this forbids pr-value=
s, with all the issues mentionned before.</div><div><br></div><div>And as I=
showed earlier, if a caller needs to cache the result, it can do it. Where=
as other proposals do not/cannot solve altogether the pr-value issue, the l=
ifetime issues and the performance issue.</div><div>Of course it needs a bi=
t of boilerplate code to actually do the caching, but this use case should =
be rare enough. And the caching code is really understandable and easy to c=
ome up with, especially if you know the lazy expression will always be eval=
uated.</div><div><br></div><div>One solution might be to have both: <span s=
tyle=3D"font-family: courier new, monospace;">[] -></span> lazy paramete=
r <i>without</i> caching=C2=A0 and <span style=3D"font-family: courier new,=
monospace;">[=3D] -></span> lazy parameter <i>with</i> caching (with no=
consideration on how it is implemented).<br></div><div><br></div><div>Anyw=
ay, if you need multiple evaluations, why do you pass a lazy expression and=
not a callable? That would make your intent much clearer.<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/5cdf347c-a54a-49bb-905f-dc392fedf121%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5cdf347c-a54a-49bb-905f-dc392fedf121=
%40isocpp.org</a>.<br />
------=_Part_24761_1967935953.1528028457396--
------=_Part_24760_1209700703.1528028457396--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Mon, 4 Jun 2018 05:53:40 +0100
Raw View
--000000000000347025056dca3d95
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Sun, 3 Jun 2018, 13:21 , <florian.csdt@gmail.com> wrote:
>
> Le dimanche 3 juin 2018 13:16:18 UTC+2, Magnus Fromreide a =C3=A9crit :
>>
>> Hello
>>
>> I am more than a little concerned about all this talk of multiple
>> evaluation
>> of lazy arguments.
>>
>> I presume that everone agrees that given
>>
>> void f([]->int);
>>
>> then after
>>
>> int a =3D 10;
>> f(a++);
>>
>> the value of a is either 10 or 11, no other values are possible.
>> (BTW, What a great obfuscation tool this would be even with this
>> limitation)
>>
>
> This example is really great to show mutliple evaluations should not be
> allowed, period.
> BTW, the example I showed with manually caching the result in a lambda
> gives this behavior: the lazy expression is evaluated once.
>
>
That depends, though. We're perfectly happy to write `while (a++) ...;` and
it's not unreasonable to think that this facility might be used for
functions with control flow that requires multiple invocation.
>> This in turn means that any second evaluation of the lazy expression mus=
t
>> be forbidden unless the compiler can prove it to be side effect free.
>>
>> Unless the compiler inline both the caller and the lazy expression, it
> will not be able to prove this side-effect free property.
> And if both are inlined, all technical issues disappear.
>
> @Edward
>
>> It should be possible to implement multiple evaluation without caching b=
y
>> storing lifetime extended temporaries in a conventionally located stack
>> frame and then not restoring (or only partially restoring) the stack
>> pointer on return from evaluation. This should be technically possible o=
n
>> any platform where alloca is implementable.
>>
>> The stack would look like: (growing downwards)
>>
>> caller
>> callee
>> lazy1a temporaries
>> lazy2 temporaries
>> lazy1b temporaries
>> inner function
>>
>> Here lazy1 is evaluated twice within the same expression, giving two set=
s
>> of temporaries. The temporaries would be destructed and their stack spac=
e
>> reclaimed at the end of the full-expression in the callee. Note that the
>> stack space used is bounded by the size of the expression in the callee.
>>
>> This would have the advantage that scope, lifetime and stack location
>> would be more conventionally correlated, and may be technically easier t=
o
>> implement than storing temporaries within the stack frame of the caller.
>>
>
> Unfortunatley, if the lazy expression "calls" alloca, the stack memory
> will be deallocated when the lazy expression ends its scope. That's why
> allocating this memory in the caller stack frame is much easier.
>
Sorry, I didn't mean to imply that the lazy expression would call alloca.
Rather it would behave like alloca, giving the stack pointer a different
value on exit than on entry.
Also, how would you track down all destructors that would be needed to be
> called?
>
That would be the job of the lazy expression routine; the callee would
invoke the lazy expression routines in destruct mode as many times as they
were invoked in evaluate mode and in reverse.
Recall that you need a destruct mode to be invoked by the callee to ensure
that destructors of temporaries are called at the end of the correct
statement in the callee.
If you want multiple scopes, you will need heap memory allocation at some
> point, which is really not needed to have a very useful feature.
>
I don't see why?
You can always create more complex objects from the simple lazy expression
> that cannot be evaluated multiple times to achieve your goal.
>
Yes, but then you lose prvalue-ness, as you have pointed out.
> Also, what if the lazy expression calls new: how do you track down the
> multiple allocations?
>
Assuming the new-expressions are adopted by a smart pointer, normal RAII
would apply.
If the lazy expression is very expensive, do you really want do execute the
> all thing again?
>
Probably not, but that should generally be the user's choice.
Caching is the only sensible way to allow multiple evaluations, but this
> forbids pr-values, with all the issues mentionned before.
>
> And as I showed earlier, if a caller needs to cache the result, it can do
> it. Whereas other proposals do not/cannot solve altogether the pr-value
> issue, the lifetime issues and the performance issue.
> Of course it needs a bit of boilerplate code to actually do the caching,
> but this use case should be rare enough. And the caching code is really
> understandable and easy to come up with, especially if you know the lazy
> expression will always be evaluated.
>
> One solution might be to have both: [] -> lazy parameter *without*
> caching and [=3D] -> lazy parameter *with* caching (with no consideratio=
n
> on how it is implemented).
>
> Anyway, if you need multiple evaluations, why do you pass a lazy
> expression and not a callable? That would make your intent much clearer.
>
In general, I agree with all of the above. I am concerned that there may be
use cases (e.g. current macros) that would benefit from multiple evaluation
(non-cached) being defined, and I would not want multiple evaluation to be
excluded that I believe I have shown can be avoided.
--=20
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/=
unsubscribe
> .
> To unsubscribe from this group and all its topics, 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/5cdf347c-a54=
a-49bb-905f-dc392fedf121%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/5cdf347c-a5=
4a-49bb-905f-dc392fedf121%40isocpp.org?utm_medium=3Demail&utm_source=3Dfoot=
er>
> .
>
--=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/CAJnLdObXMJ1asdysT%3DD8Mg8TV1WHv5wiB6BnrL9UQYK-m=
AL65w%40mail.gmail.com.
--000000000000347025056dca3d95
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"auto"><div><br><br><div class=3D"gmail_quote"><div dir=3D"ltr">=
On Sun, 3 Jun 2018, 13:21 , <<a href=3D"mailto:florian.csdt@gmail.com" t=
arget=3D"_blank" rel=3D"noreferrer">florian.csdt@gmail.com</a>> wrote:<b=
r></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border=
-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br>Le dimanche 3 j=
uin 2018 13:16:18 UTC+2, Magnus Fromreide a =C3=A9crit=C2=A0:<blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #cc=
c solid;padding-left:1ex">Hello
<br>
<br>I am more than a little concerned about all this talk of multiple evalu=
ation
<br>of lazy arguments.
<br>
<br>I presume that everone agrees that given
<br>
<br>void f([]->int);
<br>
<br>then after
<br>
<br>int a =3D 10;
<br>f(a++);
<br>
<br>the value of a is either 10 or 11, no other values are possible.
<br>(BTW, What a great obfuscation tool this would be even with this limita=
tion)
<br></blockquote><div><br></div><div><div>This example is really great to s=
how mutliple evaluations should not be allowed, period.</div><div>BTW,
the example I showed with manually caching the result in a lambda gives
this behavior: the lazy expression is evaluated once.</div></div><div>=C2=
=A0</div></div></blockquote></div></div><div dir=3D"auto"><br></div><div di=
r=3D"auto"><br></div><div dir=3D"auto">That depends, though. We're perf=
ectly happy to write `while (a++) ...;` and it's not unreasonable to th=
ink that this facility might be used for functions with control flow that r=
equires multiple invocation.=C2=A0</div><div dir=3D"auto"></div><div dir=3D=
"auto"><br></div><div dir=3D"auto"><br></div><div dir=3D"auto"><div class=
=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquot=
e class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px=
#ccc solid;padding-left:1ex">
<br>This in turn means that any second evaluation of the lazy expression mu=
st
<br>be forbidden unless the compiler can prove it to be side effect free.
<br>
<br></blockquote>Unless the compiler inline both the caller and the lazy ex=
pression, it will not be able to prove this side-effect free property.<br>A=
nd if both are inlined, all technical issues disappear.<br><div><br></div><=
div>@Edward<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div=
><div dir=3D"auto">It should be possible to implement multiple evaluation=
=20
without caching by storing lifetime extended temporaries in a=20
conventionally located stack frame and then not restoring (or only=20
partially restoring) the stack pointer on return from evaluation. This=20
should be technically possible on any platform where alloca is=20
implementable.=C2=A0</div><div dir=3D"auto"><br></div><div dir=3D"auto">The=
stack would look like: (growing downwards)=C2=A0</div><div dir=3D"auto"><b=
r></div><div dir=3D"auto">caller</div><div dir=3D"auto">callee</div><div di=
r=3D"auto">lazy1a temporaries</div><div dir=3D"auto">lazy2 temporaries</div=
><div dir=3D"auto">lazy1b temporaries</div><div dir=3D"auto">inner function=
</div><div dir=3D"auto"><br></div><div dir=3D"auto">Here
lazy1 is evaluated twice within the same expression, giving two sets of
temporaries. The temporaries would be destructed and their stack space=20
reclaimed at the end of the full-expression in the callee. Note that the
stack space used is bounded by the size of the expression in the=20
callee.=C2=A0</div><div dir=3D"auto"><br></div><div dir=3D"auto">This would=
have=20
the advantage that scope, lifetime and stack location would be more=20
conventionally correlated, and may be technically easier to implement=20
than storing temporaries within the stack frame of the caller. <br></div></=
div></blockquote><div><br></div><div>Unfortunatley, if the lazy expression =
"calls" alloca, the stack memory will be deallocated when the laz=
y expression ends its scope. That's why allocating this memory in the c=
aller stack frame is much easier.</div></div></blockquote></div></div><div =
dir=3D"auto"><br></div><div dir=3D"auto">Sorry, I didn't mean to imply =
that the lazy expression would call alloca. Rather it would behave like all=
oca, giving the stack pointer a different value on exit than on entry.=C2=
=A0</div><div dir=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gmail_=
quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-=
left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Also, how would=
you track down all destructors that would be needed to be called?</div></d=
iv></blockquote></div></div><div dir=3D"auto"><br></div><div dir=3D"auto">T=
hat would be the job of the lazy expression routine; the callee would invok=
e the lazy expression routines in destruct mode as many times as they were =
invoked in evaluate mode and in reverse.=C2=A0</div><div dir=3D"auto"><br><=
/div><div dir=3D"auto">Recall that you need a destruct mode to be invoked b=
y the callee to ensure that destructors of temporaries are called at the en=
d of the correct statement in the callee.=C2=A0</div><div dir=3D"auto"><br>=
</div><div dir=3D"auto"><div class=3D"gmail_quote"><blockquote class=3D"gma=
il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef=
t:1ex"><div dir=3D"ltr"><div>If you want multiple scopes, you will need hea=
p memory allocation at some point, which is really not needed to have a ver=
y useful feature.</div></div></blockquote></div></div><div dir=3D"auto"><br=
></div><div dir=3D"auto">I don't see why?=C2=A0</div><div dir=3D"auto">=
<br></div><div dir=3D"auto"><div class=3D"gmail_quote"><blockquote class=3D=
"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding=
-left:1ex"><div dir=3D"ltr"><div>You can always create more complex objects=
from the simple lazy expression that cannot be evaluated multiple times to=
achieve your goal.<br></div></div></blockquote></div></div><div dir=3D"aut=
o"><br></div><div dir=3D"auto">Yes, but then you lose prvalue-ness, as you =
have pointed out.=C2=A0</div><div dir=3D"auto"><br></div><div dir=3D"auto">=
<div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margi=
n:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
<div></div><div><br></div><div>Also, what if the lazy expression calls new:=
how do you track down the multiple allocations?</div></div></blockquote></=
div></div><div dir=3D"auto"><br></div><div dir=3D"auto">Assuming the new-ex=
pressions are adopted by a smart pointer, normal RAII would apply.=C2=A0</d=
iv><div dir=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gmail_quote"=
><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>If the lazy expressio=
n is very expensive, do you really want do execute the all thing again?<br>=
</div></div></blockquote></div></div><div dir=3D"auto"><br></div><div dir=
=3D"auto">Probably not, but that should generally be the user's choice.=
=C2=A0</div><div dir=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gma=
il_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div></div><div>C=
aching is the only sensible way to allow multiple evaluations, but this for=
bids pr-values, with all the issues mentionned before.</div><div><br></div>=
<div>And as I showed earlier, if a caller needs to cache the result, it can=
do it. Whereas other proposals do not/cannot solve altogether the pr-value=
issue, the lifetime issues and the performance issue.</div><div>Of course =
it needs a bit of boilerplate code to actually do the caching, but this use=
case should be rare enough. And the caching code is really understandable =
and easy to come up with, especially if you know the lazy expression will a=
lways be evaluated.</div><div><br></div><div>One solution might be to have =
both: <span style=3D"font-family:courier new,monospace">[] -></span> laz=
y parameter <i>without</i> caching=C2=A0 and <span style=3D"font-family:cou=
rier new,monospace">[=3D] -></span> lazy parameter <i>with</i> caching (=
with no consideration on how it is implemented).<br></div><div><br></div><d=
iv>Anyway, if you need multiple evaluations, why do you pass a lazy express=
ion and not a callable? That would make your intent much clearer.<br></div>=
</div></blockquote></div></div><div dir=3D"auto"><br></div><div dir=3D"auto=
">In general, I agree with all of the above. I am concerned that there may =
be use cases (e.g. current macros) that would benefit from multiple evaluat=
ion (non-cached) being defined, and I would not want multiple evaluation to=
be excluded that I believe I have shown can be avoided.=C2=A0</div><div di=
r=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gmail_quote"><blockquo=
te class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc so=
lid;padding-left:1ex"><div dir=3D"ltr"><div></div></div>
<p></p>
-- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/unsubscribe" rel=3D"noreferr=
er noreferrer" target=3D"_blank">https://groups.google.com/a/isocpp.org/d/t=
opic/std-proposals/5oUZysJB4HE/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org" rel=3D"noreferrer noreferr=
er" target=3D"_blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" rel=3D"noreferrer noreferrer" target=3D"_blank">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/5cdf347c-a54a-49bb-905f-dc392fedf121%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" rel=3D"noreferrer =
noreferrer" target=3D"_blank">https://groups.google.com/a/isocpp.org/d/msgi=
d/std-proposals/5cdf347c-a54a-49bb-905f-dc392fedf121%40isocpp.org</a>.<br>
</blockquote></div></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/CAJnLdObXMJ1asdysT%3DD8Mg8TV1WHv5wiB6=
BnrL9UQYK-mAL65w%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdObXMJ1asd=
ysT%3DD8Mg8TV1WHv5wiB6BnrL9UQYK-mAL65w%40mail.gmail.com</a>.<br />
--000000000000347025056dca3d95--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Mon, 4 Jun 2018 09:13:39 +0100
Raw View
--000000000000e142ba056dcc8231
Content-Type: text/plain; charset="UTF-8"
On Mon, Jun 4, 2018 at 5:53 AM, Edward Catmur <ecatmur@googlemail.com>
wrote:
>
> In general, I agree with all of the above. I am concerned that there may
> be use cases (e.g. current macros) that would benefit from multiple
> evaluation (non-cached) being defined, and I would not want multiple
> evaluation to be excluded that I believe I have shown can be avoided.
>
> Sorry, missed a few words there: I would not want multiple evaluation to
be excluded *on the basis of technical considerations* that I believe I
have shown can be avoided.
--
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/CAJnLdOZX12VE5zs%2BvTNB_tESgJdWVXQRaQ3AyQnB0jZs5%2B_%3Dsg%40mail.gmail.com.
--000000000000e142ba056dcc8231
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Mon, Jun 4, 2018 at 5:53 AM, Edward Catmur <span dir=3D"ltr"><<a =
href=3D"mailto:ecatmur@googlemail.com" target=3D"_blank">ecatmur@googlemail=
..com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"au=
to"><span class=3D""><div><br></div></span><div dir=3D"auto">In general, I =
agree with all of the above. I am concerned that there may be use cases (e.=
g. current macros) that would benefit from multiple evaluation (non-cached)=
being defined, and I would not want multiple evaluation to be excluded tha=
t I believe I have shown can be avoided.=C2=A0</div><span class=3D""><div d=
ir=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gmail_quote"><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div></div></div>
<p></p></blockquote></div></div></span></div></blockquote></div>
<span style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:s=
mall;font-style:normal;font-variant-ligatures:normal;font-variant-caps:norm=
al;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;t=
ext-transform:none;white-space:normal;word-spacing:0px;background-color:rgb=
(255,255,255);text-decoration-style:initial;text-decoration-color:initial;f=
loat:none;display:inline">Sorry, missed a few words there: I would not want=
multiple evaluation to be excluded *on the basis of technical consideratio=
ns* that I believe I have shown can be avoided.=C2=A0</span>
<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/CAJnLdOZX12VE5zs%2BvTNB_tESgJdWVXQRaQ=
3AyQnB0jZs5%2B_%3Dsg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdOZX12=
VE5zs%2BvTNB_tESgJdWVXQRaQ3AyQnB0jZs5%2B_%3Dsg%40mail.gmail.com</a>.<br />
--000000000000e142ba056dcc8231--
.
Author: florian.csdt@gmail.com
Date: Mon, 4 Jun 2018 01:24:17 -0700 (PDT)
Raw View
------=_Part_31393_764591894.1528100657299
Content-Type: multipart/alternative;
boundary="----=_Part_31394_291958874.1528100657300"
------=_Part_31394_291958874.1528100657300
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le lundi 4 juin 2018 07:31:03 UTC+2, Edward Catmur a =C3=A9crit :
>
>
>
> On Sun, 3 Jun 2018, 13:21 , <floria...@gmail.com <javascript:>> wrote:
>
>>
>> Le dimanche 3 juin 2018 13:16:18 UTC+2, Magnus Fromreide a =C3=A9crit :
>>>
>>> Hello=20
>>>
>>> I am more than a little concerned about all this talk of multiple=20
>>> evaluation=20
>>> of lazy arguments.=20
>>>
>>> I presume that everone agrees that given=20
>>>
>>> void f([]->int);=20
>>>
>>> then after=20
>>>
>>> int a =3D 10;=20
>>> f(a++);=20
>>>
>>> the value of a is either 10 or 11, no other values are possible.=20
>>> (BTW, What a great obfuscation tool this would be even with this=20
>>> limitation)=20
>>>
>>
>> This example is really great to show mutliple evaluations should not be=
=20
>> allowed, period.
>> BTW, the example I showed with manually caching the result in a lambda=
=20
>> gives this behavior: the lazy expression is evaluated once.
>> =20
>>
>
>
> That depends, though. We're perfectly happy to write `while (a++) ...;`=
=20
> and it's not unreasonable to think that this facility might be used for=
=20
> functions with control flow that requires multiple invocation.=20
>
For that kind of stuff, I would prefer a "macro-like" approach. I know some=
=20
people were working on that. It's personal taste here.
=20
>
>
>
>>> This in turn means that any second evaluation of the lazy expression=20
>>> must=20
>>> be forbidden unless the compiler can prove it to be side effect free.=
=20
>>>
>>> Unless the compiler inline both the caller and the lazy expression, it=
=20
>> will not be able to prove this side-effect free property.
>> And if both are inlined, all technical issues disappear.
>>
>> @Edward
>>
>>> It should be possible to implement multiple evaluation without caching=
=20
>>> by storing lifetime extended temporaries in a conventionally located st=
ack=20
>>> frame and then not restoring (or only partially restoring) the stack=20
>>> pointer on return from evaluation. This should be technically possible =
on=20
>>> any platform where alloca is implementable.=20
>>>
>>> The stack would look like: (growing downwards)=20
>>>
>>> caller
>>> callee
>>> lazy1a temporaries
>>> lazy2 temporaries
>>> lazy1b temporaries
>>> inner function
>>>
>>> Here lazy1 is evaluated twice within the same expression, giving two=20
>>> sets of temporaries. The temporaries would be destructed and their stac=
k=20
>>> space reclaimed at the end of the full-expression in the callee. Note t=
hat=20
>>> the stack space used is bounded by the size of the expression in the=20
>>> callee.=20
>>>
>>> This would have the advantage that scope, lifetime and stack location=
=20
>>> would be more conventionally correlated, and may be technically easier =
to=20
>>> implement than storing temporaries within the stack frame of the caller=
..=20
>>>
>>
>> Unfortunatley, if the lazy expression "calls" alloca, the stack memory=
=20
>> will be deallocated when the lazy expression ends its scope. That's why=
=20
>> allocating this memory in the caller stack frame is much easier.
>>
>
> Sorry, I didn't mean to imply that the lazy expression would call alloca.=
=20
> Rather it would behave like alloca, giving the stack pointer a different=
=20
> value on exit than on entry.=20
>
(alloca is not a function anyway, it is just some arithmetic on pointers)
The problem is: if you give a different stack pointer to the callee, it=20
would need to adjust back the pointer itself to access its data. And what=
=20
if the callee needs to allocate some stack after evaluating a lazy=20
expression? Where would the new stack frame go? How does the caller know=20
where it would go?
After some thinking, I agree it might be possible to implement, but at what=
=20
costs?
=20
>
> Also, how would you track down all destructors that would be needed to be=
=20
>> called?
>>
>
> That would be the job of the lazy expression routine; the callee would=20
> invoke the lazy expression routines in destruct mode as many times as the=
y=20
> were invoked in evaluate mode and in reverse.=20
>
> Recall that you need a destruct mode to be invoked by the callee to ensur=
e=20
> that destructors of temporaries are called at the end of the correct=20
> statement in the callee.=20
>
I don't recall that. It was suggested, but I think the lazy expression=20
temporaries must outlive the caller expression (not only the callee one).
void print(std::string_view sv) { std::cout << sv << std::endl; }
std::string_view lazy([] -> std::string s) { return s; }
std::string_view eager(const std::string & s) { return s; }
print(eager("hello world!"));
print(lazy("hello world!"));
The eager expression works perfectly fine now: the std::string temporary=20
lifetime ends at the semicolon (https://godbolt.org/g/6xV4aM).
I would expect the second to also works for the very same reason.
This can happen only if the caller is the one to destroy the lazy=20
expression temporaries.
=20
>
> If you want multiple scopes, you will need heap memory allocation at some=
=20
>> point, which is really not needed to have a very useful feature.
>>
>
> I don't see why?=20
>
Maybe not, but very hard. Especially to make the destruction happens in the=
=20
caller as I explained just above.
=20
>
> You can always create more complex objects from the simple lazy expressio=
n=20
>> that cannot be evaluated multiple times to achieve your goal.
>>
>
> Yes, but then you lose prvalue-ness, as you have pointed out.=20
>
I don't see any valid use case where these 2 features might be needed at=20
the same time. If you really want multiple evaluations also allowing=20
prvalues, why callables are not enough?
=20
>
>
>> Also, what if the lazy expression calls new: how do you track down the=
=20
>> multiple allocations?
>>
>
> Assuming the new-expressions are adopted by a smart pointer, normal RAII=
=20
> would apply.=20
>
You don't need RAII for this code to be correct:
int i =3D /* ... */;
int* p =3D i > 0 ? new int(i) : nullptr;
/* ... */
if (p) delete p;
Why would it be different with custom functions, or custom types?
I agree smart pointers are much safer and should be used everywhere a=20
new/delete was used. But this is still valid code.
=20
>
> If the lazy expression is very expensive, do you really want do execute=
=20
>> the all thing again?
>>
>
> Probably not, but that should generally be the user's choice.=20
>
A user might not be able to tell if an expression is expensive or not. It=
=20
will be even more true with this because it will be simpler to call complex=
=20
constructors without even noticing (and that's part of the point).
=20
>
> Caching is the only sensible way to allow multiple evaluations, but this=
=20
>> forbids pr-values, with all the issues mentionned before.
>>
>> And as I showed earlier, if a caller needs to cache the result, it can d=
o=20
>> it. Whereas other proposals do not/cannot solve altogether the pr-value=
=20
>> issue, the lifetime issues and the performance issue.
>> Of course it needs a bit of boilerplate code to actually do the caching,=
=20
>> but this use case should be rare enough. And the caching code is really=
=20
>> understandable and easy to come up with, especially if you know the lazy=
=20
>> expression will always be evaluated.
>>
>> One solution might be to have both: [] -> lazy parameter *without*=20
>> caching and [=3D] -> lazy parameter *with* caching (with no considerati=
on=20
>> on how it is implemented).
>>
>> Anyway, if you need multiple evaluations, why do you pass a lazy=20
>> expression and not a callable? That would make your intent much clearer.
>>
>
> In general, I agree with all of the above. I am concerned that there may=
=20
> be use cases (e.g. current macros) that would benefit from multiple=20
> evaluation (non-cached) being defined, and I would not want multiple=20
> evaluation to be excluded that I believe I have shown can be avoided.=20
>
For now, I don't see any use case that would really need this syntax=20
boilerplate free at call site feature.
I really believe that this kind of problems should be solved either with=20
callables or "macro"-like constructions.
Also multiple evaluation could also be added afterwards if there is a need=
=20
for it. As long as we say multiple evaluation is undefined, then extending=
=20
it would be possible.
> Sorry, missed a few words there: I would not want multiple evaluation to=
=20
> be excluded *on the basis of technical considerations* that I believe I=
=20
> have shown can be avoided.
>
More than technical considerations, it is performance considerations. You=
=20
want the fast cases being fast: if the lazy expression is just a literal,=
=20
you really don't want all the implementation boilerplate to deal with=20
multiple evaluations and temporaries bookkeeping.
Your solution makes this use case inefficient because the callee won't know=
=20
the lazy expression is as simple as that.
In the implementation I proposed, this is as fast as it could get without=
=20
inlining: just a call to a function returning the literal.
--=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/ff30ffc4-f898-4b10-a26e-a6e9c2560642%40isocpp.or=
g.
------=_Part_31394_291958874.1528100657300
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Le lundi 4 juin 2018 07:31:03 UTC+2, Edward Catmur=
a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"auto"><div><br><br><div class=3D"gmail_quote"><div dir=3D"ltr">On Sun, =
3 Jun 2018, 13:21 , <<a href=3D"javascript:" rel=3D"nofollow" target=3D"=
_blank" gdf-obfuscated-mailto=3D"29_aYVjSAwAJ" onmousedown=3D"this.href=3D&=
#39;javascript:';return true;" onclick=3D"this.href=3D'javascript:&=
#39;;return true;">floria...@gmail.com</a>> wrote:<br></div><blockquote =
class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid=
;padding-left:1ex"><div dir=3D"ltr"><br>Le dimanche 3 juin 2018 13:16:18 UT=
C+2, Magnus Fromreide a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" =
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left=
:1ex">Hello
<br>
<br>I am more than a little concerned about all this talk of multiple evalu=
ation
<br>of lazy arguments.
<br>
<br>I presume that everone agrees that given
<br>
<br>void f([]->int);
<br>
<br>then after
<br>
<br>int a =3D 10;
<br>f(a++);
<br>
<br>the value of a is either 10 or 11, no other values are possible.
<br>(BTW, What a great obfuscation tool this would be even with this limita=
tion)
<br></blockquote><div><br></div><div><div>This example is really great to s=
how mutliple evaluations should not be allowed, period.</div><div>BTW,
the example I showed with manually caching the result in a lambda gives
this behavior: the lazy expression is evaluated once.</div></div><div>=C2=
=A0</div></div></blockquote></div></div><div dir=3D"auto"><br></div><div di=
r=3D"auto"><br></div><div dir=3D"auto">That depends, though. We're perf=
ectly happy to write `while (a++) ...;` and it's not unreasonable to th=
ink that this facility might be used for functions with control flow that r=
equires multiple invocation.=C2=A0</div></div></blockquote><div><br></div><=
div>For that kind of stuff, I would prefer a "macro-like" approac=
h. I know some people were working on that. It's personal taste here.</=
div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"auto"><div dir=3D"auto"></div><div dir=3D"auto"><br></div><div dir=3D"a=
uto"><br></div><div dir=3D"auto"><div class=3D"gmail_quote"><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D=
"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>This in turn means that any second evaluation of the lazy expression mu=
st
<br>be forbidden unless the compiler can prove it to be side effect free.
<br>
<br></blockquote>Unless the compiler inline both the caller and the lazy ex=
pression, it will not be able to prove this side-effect free property.<br>A=
nd if both are inlined, all technical issues disappear.<br><div><br></div><=
div>@Edward<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div=
><div dir=3D"auto">It should be possible to implement multiple evaluation=
=20
without caching by storing lifetime extended temporaries in a=20
conventionally located stack frame and then not restoring (or only=20
partially restoring) the stack pointer on return from evaluation. This=20
should be technically possible on any platform where alloca is=20
implementable.=C2=A0</div><div dir=3D"auto"><br></div><div dir=3D"auto">The=
stack would look like: (growing downwards)=C2=A0</div><div dir=3D"auto"><b=
r></div><div dir=3D"auto">caller</div><div dir=3D"auto">callee</div><div di=
r=3D"auto">lazy1a temporaries</div><div dir=3D"auto">lazy2 temporaries</div=
><div dir=3D"auto">lazy1b temporaries</div><div dir=3D"auto">inner function=
</div><div dir=3D"auto"><br></div><div dir=3D"auto">Here
lazy1 is evaluated twice within the same expression, giving two sets of
temporaries. The temporaries would be destructed and their stack space=20
reclaimed at the end of the full-expression in the callee. Note that the
stack space used is bounded by the size of the expression in the=20
callee.=C2=A0</div><div dir=3D"auto"><br></div><div dir=3D"auto">This would=
have=20
the advantage that scope, lifetime and stack location would be more=20
conventionally correlated, and may be technically easier to implement=20
than storing temporaries within the stack frame of the caller. <br></div></=
div></blockquote><div><br></div><div>Unfortunatley, if the lazy expression =
"calls" alloca, the stack memory will be deallocated when the laz=
y expression ends its scope. That's why allocating this memory in the c=
aller stack frame is much easier.</div></div></blockquote></div></div><div =
dir=3D"auto"><br></div><div dir=3D"auto">Sorry, I didn't mean to imply =
that the lazy expression would call alloca. Rather it would behave like all=
oca, giving the stack pointer a different value on exit than on entry.=C2=
=A0</div></div></blockquote><div><br></div><div>(alloca is not a function a=
nyway, it is just some arithmetic on pointers)</div><div>The problem is: if=
you give a different stack pointer to the callee, it would need to adjust =
back the pointer itself to access its data. And what if the callee needs to=
allocate some stack after evaluating a lazy expression? Where would the ne=
w stack frame go? How does the caller know where it would go?</div><div><br=
></div><div>After some thinking, I agree it might be possible to implement,=
but at what costs?<br></div><div>=C2=A0</div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;"><div dir=3D"auto"><div dir=3D"auto"><br></div><div dir=3D"a=
uto"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"=
margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"=
ltr"><div>Also, how would you track down all destructors that would be need=
ed to be called?</div></div></blockquote></div></div><div dir=3D"auto"><br>=
</div><div dir=3D"auto">That would be the job of the lazy expression routin=
e; the callee would invoke the lazy expression routines in destruct mode as=
many times as they were invoked in evaluate mode and in reverse.=C2=A0</di=
v><div dir=3D"auto"><br></div><div dir=3D"auto">Recall that you need a dest=
ruct mode to be invoked by the callee to ensure that destructors of tempora=
ries are called at the end of the correct statement in the callee.=C2=A0</d=
iv></div></blockquote><div><br></div><div>I don't recall that. It was s=
uggested, but I think the lazy expression temporaries must outlive the call=
er expression (not only the callee one).</div><div><div style=3D"background=
-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style:=
solid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint=
"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"=
color: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">print</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">std</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
string_view sv</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: #660;" class=3D"styled-by-prettify">{</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">cout </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify"><<</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> sv </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify"><<</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">endl</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: #660;" class=3D"styled-by-prettify">}</span><code =
class=3D"prettyprint"><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br>std</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">string=
_view lazy</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><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">string</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> s</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"=
> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">return</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> s</span><sp=
an 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"></span></code><code class=3D"prettyprint"><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br>std</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">string_view eager</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">(const </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;" cl=
ass=3D"styled-by-prettify">std</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">::</span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">string</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> & s</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><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> s</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br></span></code><code class=3D"prettyprint"><span style=3D"color:=
#000;" class=3D"styled-by-prettify"><code class=3D"prettyprint"><code clas=
s=3D"prettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br>print(eager("hello world!"));</span></code></code><br>print(=
lazy("hello world!"));<br></span></code><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"></span></div></code></div>The eager expres=
sion works perfectly fine now: the std::string temporary lifetime ends at t=
he semicolon (https://godbolt.org/g/6xV4aM).<br></div><div>I would expect t=
he second to also works for the very same reason.</div><div><br></div><div>=
This can happen only if the caller is the one to destroy the lazy expressio=
n temporaries.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" =
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-l=
eft: 1ex;"><div dir=3D"auto"><div dir=3D"auto"><br></div><div dir=3D"auto">=
<div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margi=
n:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
<div>If you want multiple scopes, you will need heap memory allocation at s=
ome point, which is really not needed to have a very useful feature.</div><=
/div></blockquote></div></div><div dir=3D"auto"><br></div><div dir=3D"auto"=
>I don't see why?=C2=A0</div></div></blockquote><div><br></div><div>May=
be not, but very hard. Especially to make the destruction happens in the ca=
ller as I explained just above.<br></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"auto"><div dir=3D"auto"><br></div><=
div dir=3D"auto"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quot=
e" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">=
<div dir=3D"ltr"><div>You can always create more complex objects from the s=
imple lazy expression that cannot be evaluated multiple times to achieve yo=
ur goal.<br></div></div></blockquote></div></div><div dir=3D"auto"><br></di=
v><div dir=3D"auto">Yes, but then you lose prvalue-ness, as you have pointe=
d out.=C2=A0</div></div></blockquote><div><br></div><div>I don't see an=
y valid use case where these 2 features might be needed at the same time. I=
f you really want multiple evaluations also allowing prvalues, why callable=
s are not enough?<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div dir=3D"auto"><div dir=3D"auto"><br></div><div dir=3D"aut=
o"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"lt=
r"><div></div><div><br></div><div>Also, what if the lazy expression calls n=
ew: how do you track down the multiple allocations?</div></div></blockquote=
></div></div><div dir=3D"auto"><br></div><div dir=3D"auto">Assuming the new=
-expressions are adopted by a smart pointer, normal RAII would apply.=C2=A0=
</div></div></blockquote><div><br></div><div>You don't need RAII for th=
is code to be correct:</div><div><div style=3D"background-color: rgb(250, 2=
50, 250); border-color: rgb(187, 187, 187); border-style: solid; border-wid=
th: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"p=
rettyprint"><div class=3D"subprettyprint"><span style=3D"color: #606;" clas=
s=3D"styled-by-prettify">int i =3D /* ... */;<br>int* p =3D i > 0 ? new =
int(i) : nullptr;<br>/* ... */<br>if (p) delete p;<br></span><span style=3D=
"color: #660;" class=3D"styled-by-prettify"></span></div></code></div>Why w=
ould it be different with custom functions, or custom types?</div><div><br>=
</div><div>I agree smart pointers are much safer and should be used everywh=
ere a new/delete was used. But this is still valid code.<br></div><div>=C2=
=A0</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"auto"><di=
v dir=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gmail_quote"><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #cc=
c solid;padding-left:1ex"><div dir=3D"ltr"><div>If the lazy expression is v=
ery expensive, do you really want do execute the all thing again?<br></div>=
</div></blockquote></div></div><div dir=3D"auto"><br></div><div dir=3D"auto=
">Probably not, but that should generally be the user's choice.=C2=A0</=
div></div></blockquote><div><br></div><div>A user might not be able to tell=
if an expression is expensive or not. It will be even more true with this =
because it will be simpler to call complex constructors without even notici=
ng (and that's part of the point).<br></div><div>=C2=A0</div><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;"><div dir=3D"auto"><div dir=3D"auto"><br>=
</div><div dir=3D"auto"><div class=3D"gmail_quote"><blockquote class=3D"gma=
il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef=
t:1ex"><div dir=3D"ltr"><div></div><div>Caching is the only sensible way to=
allow multiple evaluations, but this forbids pr-values, with all the issue=
s mentionned before.</div><div><br></div><div>And as I showed earlier, if a=
caller needs to cache the result, it can do it. Whereas other proposals do=
not/cannot solve altogether the pr-value issue, the lifetime issues and th=
e performance issue.</div><div>Of course it needs a bit of boilerplate code=
to actually do the caching, but this use case should be rare enough. And t=
he caching code is really understandable and easy to come up with, especial=
ly if you know the lazy expression will always be evaluated.</div><div><br>=
</div><div>One solution might be to have both: <span style=3D"font-family:c=
ourier new,monospace">[] -></span> lazy parameter <i>without</i> caching=
=C2=A0 and <span style=3D"font-family:courier new,monospace">[=3D] -></s=
pan> lazy parameter <i>with</i> caching (with no consideration on how it is=
implemented).<br></div><div><br></div><div>Anyway, if you need multiple ev=
aluations, why do you pass a lazy expression and not a callable? That would=
make your intent much clearer.<br></div></div></blockquote></div></div><di=
v dir=3D"auto"><br></div><div dir=3D"auto">In general, I agree with all of =
the above. I am concerned that there may be use cases (e.g. current macros)=
that would benefit from multiple evaluation (non-cached) being defined, an=
d I would not want multiple evaluation to be excluded that I believe I have=
shown can be avoided.=C2=A0</div></div></blockquote><div><br></div><div>Fo=
r now, I don't see any use case that would really need this syntax boil=
erplate free at call site feature.</div><div>I really believe that this kin=
d of problems should be solved either with callables or "macro"-l=
ike constructions.</div><div><br></div><div>Also multiple evaluation could =
also be added afterwards if there is a need for it. As long as we say multi=
ple evaluation is undefined, then extending it would be possible.</div><div=
><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0=
..8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div><=
br></div><div><span style=3D"color:rgb(34,34,34);font-family:arial,sans-ser=
if;font-size:small;font-style:normal;font-weight:400;letter-spacing:normal;=
text-align:start;text-indent:0px;text-transform:none;white-space:normal;wor=
d-spacing:0px;background-color:rgb(255,255,255);float:none;display:inline">=
Sorry,
missed a few words there: I would not want multiple evaluation to be=20
excluded *on the basis of technical considerations* that I believe I=20
have shown can be avoided.</span></div></blockquote><div><span style=3D"col=
or:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:no=
rmal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px=
;text-transform:none;white-space:normal;word-spacing:0px;background-color:r=
gb(255,255,255);float:none;display:inline"><br></span></div><div><span styl=
e=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-=
style:normal;font-weight:400;letter-spacing:normal;text-align:start;text-in=
dent:0px;text-transform:none;white-space:normal;word-spacing:0px;background=
-color:rgb(255,255,255);float:none;display:inline">More than technical cons=
iderations, it is performance considerations. You want the fast cases being=
fast: if the lazy expression is just a literal, you really don't want =
all the implementation boilerplate to deal with multiple evaluations and te=
mporaries bookkeeping.</span></div><div><span style=3D"color:rgb(34,34,34);=
font-family:arial,sans-serif;font-size:small;font-style:normal;font-weight:=
400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:n=
one;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);f=
loat:none;display:inline">Your solution makes this use case inefficient bec=
ause the callee won't know the lazy expression is as simple as that.<br=
></span></div><div><span style=3D"color:rgb(34,34,34);font-family:arial,san=
s-serif;font-size:small;font-style:normal;font-weight:400;letter-spacing:no=
rmal;text-align:start;text-indent:0px;text-transform:none;white-space:norma=
l;word-spacing:0px;background-color:rgb(255,255,255);float:none;display:inl=
ine">In the implementation I proposed, this is as fast as it could get with=
out inlining: just a call to a function returning the literal.<br></span></=
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/ff30ffc4-f898-4b10-a26e-a6e9c2560642%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/ff30ffc4-f898-4b10-a26e-a6e9c2560642=
%40isocpp.org</a>.<br />
------=_Part_31394_291958874.1528100657300--
------=_Part_31393_764591894.1528100657299--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Wed, 6 Jun 2018 01:47:19 +0100
Raw View
--000000000000eac3d6056dee82e7
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Mon, 4 Jun 2018, 09:24 , <florian.csdt@gmail.com> wrote:
>
>
> Le lundi 4 juin 2018 07:31:03 UTC+2, Edward Catmur a =C3=A9crit :
>>
>>
>>
>> On Sun, 3 Jun 2018, 13:21 , <floria...@gmail.com> wrote:
>>
>>>
>>> Le dimanche 3 juin 2018 13:16:18 UTC+2, Magnus Fromreide a =C3=A9crit :
>>>>
>>>> Hello
>>>>
>>>> I am more than a little concerned about all this talk of multiple
>>>> evaluation
>>>> of lazy arguments.
>>>>
>>>> I presume that everone agrees that given
>>>>
>>>> void f([]->int);
>>>>
>>>> then after
>>>>
>>>> int a =3D 10;
>>>> f(a++);
>>>>
>>>> the value of a is either 10 or 11, no other values are possible.
>>>> (BTW, What a great obfuscation tool this would be even with this
>>>> limitation)
>>>>
>>>
>>> This example is really great to show mutliple evaluations should not be
>>> allowed, period.
>>> BTW, the example I showed with manually caching the result in a lambda
>>> gives this behavior: the lazy expression is evaluated once.
>>>
>>>
>>
>>
>> That depends, though. We're perfectly happy to write `while (a++) ...;`
>> and it's not unreasonable to think that this facility might be used for
>> functions with control flow that requires multiple invocation.
>>
>
> For that kind of stuff, I would prefer a "macro-like" approach. I know
> some people were working on that. It's personal taste here.
>
>
If this could be (part of) that macro-like approach, I'm sure conventions
would arise to distinguish between functions taking lazy arguments that are
evaluated at most once and those whose lazy arguments may be evaluated
multiple times.
>>
>>
>>>> This in turn means that any second evaluation of the lazy expression
>>>> must
>>>> be forbidden unless the compiler can prove it to be side effect free.
>>>>
>>>> Unless the compiler inline both the caller and the lazy expression, it
>>> will not be able to prove this side-effect free property.
>>> And if both are inlined, all technical issues disappear.
>>>
>>> @Edward
>>>
>>>> It should be possible to implement multiple evaluation without caching
>>>> by storing lifetime extended temporaries in a conventionally located s=
tack
>>>> frame and then not restoring (or only partially restoring) the stack
>>>> pointer on return from evaluation. This should be technically possible=
on
>>>> any platform where alloca is implementable.
>>>>
>>>> The stack would look like: (growing downwards)
>>>>
>>>> caller
>>>> callee
>>>> lazy1a temporaries
>>>> lazy2 temporaries
>>>> lazy1b temporaries
>>>> inner function
>>>>
>>>> Here lazy1 is evaluated twice within the same expression, giving two
>>>> sets of temporaries. The temporaries would be destructed and their sta=
ck
>>>> space reclaimed at the end of the full-expression in the callee. Note =
that
>>>> the stack space used is bounded by the size of the expression in the
>>>> callee.
>>>>
>>>> This would have the advantage that scope, lifetime and stack location
>>>> would be more conventionally correlated, and may be technically easier=
to
>>>> implement than storing temporaries within the stack frame of the calle=
r.
>>>>
>>>
>>> Unfortunatley, if the lazy expression "calls" alloca, the stack memory
>>> will be deallocated when the lazy expression ends its scope. That's why
>>> allocating this memory in the caller stack frame is much easier.
>>>
>>
>> Sorry, I didn't mean to imply that the lazy expression would call alloca=
..
>> Rather it would behave like alloca, giving the stack pointer a different
>> value on exit than on entry.
>>
>
> (alloca is not a function anyway, it is just some arithmetic on pointers)
> The problem is: if you give a different stack pointer to the callee, it
> would need to adjust back the pointer itself to access its data. And what
> if the callee needs to allocate some stack after evaluating a lazy
> expression? Where would the new stack frame go? How does the caller know
> where it would go?
>
> After some thinking, I agree it might be possible to implement, but at
> what costs?
>
>
It would require the use of an additional register to hold the base
address. This wouldn't be particularly expensive; it was after all till
relatively recently the convention to hold a base pointer in ebp.
>> Also, how would you track down all destructors that would be needed to b=
e
>>> called?
>>>
>>
>> That would be the job of the lazy expression routine; the callee would
>> invoke the lazy expression routines in destruct mode as many times as th=
ey
>> were invoked in evaluate mode and in reverse.
>>
>> Recall that you need a destruct mode to be invoked by the callee to
>> ensure that destructors of temporaries are called at the end of the corr=
ect
>> statement in the callee.
>>
>
> I don't recall that. It was suggested, but I think the lazy expression
> temporaries must outlive the caller expression (not only the callee one).
> void print(std::string_view sv) { std::cout << sv << std::endl; }
> std::string_view lazy([] -> std::string s) { return s; }
> std::string_view eager(const std::string & s) { return s; }
>
> print(eager("hello world!"));
> print(lazy("hello world!"));
> The eager expression works perfectly fine now: the std::string temporary
> lifetime ends at the semicolon (https://godbolt.org/g/6xV4aM).
> I would expect the second to also works for the very same reason.
>
> This can happen only if the caller is the one to destroy the lazy
> expression temporaries.
>
>
Ah, that's an interesting point, thanks. I suppose it makes a difference
whether you regard this facility as a different kind of parameter or as a
macro replacement, but certainly your example should work, which is a
strong argument for destruction handled by the caller.
>> If you want multiple scopes, you will need heap memory allocation at som=
e
>>> point, which is really not needed to have a very useful feature.
>>>
>>
>> I don't see why?
>>
>
> Maybe not, but very hard. Especially to make the destruction happens in
> the caller as I explained just above.
>
>
>>
>> You can always create more complex objects from the simple lazy
>>> expression that cannot be evaluated multiple times to achieve your goal=
..
>>>
>>
>> Yes, but then you lose prvalue-ness, as you have pointed out.
>>
>
> I don't see any valid use case where these 2 features might be needed at
> the same time. If you really want multiple evaluations also allowing
> prvalues, why callables are not enough?
>
>
There's advantages of terseness, and also of lifetime of temporaries -
extended into the callee, if not the caller.
>>
>>> Also, what if the lazy expression calls new: how do you track down the
>>> multiple allocations?
>>>
>>
>> Assuming the new-expressions are adopted by a smart pointer, normal RAII
>> would apply.
>>
>
> You don't need RAII for this code to be correct:
> int i =3D /* ... */;
> int* p =3D i > 0 ? new int(i) : nullptr;
> /* ... */
> if (p) delete p;
> Why would it be different with custom functions, or custom types?
>
> I agree smart pointers are much safer and should be used everywhere a
> new/delete was used. But this is still valid code.
>
>
It's fragile if the ellipsized code can throw, or merely return. I prefer
smart pointers or scope guards wherever reasonable.
>> If the lazy expression is very expensive, do you really want do execute
>>> the all thing again?
>>>
>>
>> Probably not, but that should generally be the user's choice.
>>
>
> A user might not be able to tell if an expression is expensive or not. It
> will be even more true with this because it will be simpler to call compl=
ex
> constructors without even noticing (and that's part of the point).
>
>
>>
>> Caching is the only sensible way to allow multiple evaluations, but this
>>> forbids pr-values, with all the issues mentionned before.
>>>
>>> And as I showed earlier, if a caller needs to cache the result, it can
>>> do it. Whereas other proposals do not/cannot solve altogether the pr-va=
lue
>>> issue, the lifetime issues and the performance issue.
>>> Of course it needs a bit of boilerplate code to actually do the caching=
,
>>> but this use case should be rare enough. And the caching code is really
>>> understandable and easy to come up with, especially if you know the laz=
y
>>> expression will always be evaluated.
>>>
>>> One solution might be to have both: [] -> lazy parameter *without*
>>> caching and [=3D] -> lazy parameter *with* caching (with no
>>> consideration on how it is implemented).
>>>
>>> Anyway, if you need multiple evaluations, why do you pass a lazy
>>> expression and not a callable? That would make your intent much clearer=
..
>>>
>>
>> In general, I agree with all of the above. I am concerned that there may
>> be use cases (e.g. current macros) that would benefit from multiple
>> evaluation (non-cached) being defined, and I would not want multiple
>> evaluation to be excluded that I believe I have shown can be avoided.
>>
>
> For now, I don't see any use case that would really need this syntax
> boilerplate free at call site feature.
> I really believe that this kind of problems should be solved either with
> callables or "macro"-like constructions.
>
> Also multiple evaluation could also be added afterwards if there is a nee=
d
> for it. As long as we say multiple evaluation is undefined, then extendin=
g
> it would be possible.
>
Yes, that's reasonable. Thanks for taking the time to present your ideas
and arguments.
>
>> Sorry, missed a few words there: I would not want multiple evaluation to
>> be excluded *on the basis of technical considerations* that I believe I
>> have shown can be avoided.
>>
>
> More than technical considerations, it is performance considerations. You
> want the fast cases being fast: if the lazy expression is just a literal,
> you really don't want all the implementation boilerplate to deal with
> multiple evaluations and temporaries bookkeeping.
> Your solution makes this use case inefficient because the callee won't
> know the lazy expression is as simple as that.
> In the implementation I proposed, this is as fast as it could get without
> inlining: just a call to a function returning the literal.
>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/=
unsubscribe
> .
> To unsubscribe from this group and all its topics, 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/ff30ffc4-f89=
8-4b10-a26e-a6e9c2560642%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/ff30ffc4-f8=
98-4b10-a26e-a6e9c2560642%40isocpp.org?utm_medium=3Demail&utm_source=3Dfoot=
er>
> .
>
--=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/CAJnLdObh9-Ysxm9awoc_-Ysz30GkwFjx8TYt%3DhzkXiw9R=
xttug%40mail.gmail.com.
--000000000000eac3d6056dee82e7
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"auto"><div><br><br><div class=3D"gmail_quote"><div dir=3D"ltr">=
On Mon, 4 Jun 2018, 09:24 , <<a href=3D"mailto:florian.csdt@gmail.com" t=
arget=3D"_blank" rel=3D"noreferrer">florian.csdt@gmail.com</a>> wrote:<b=
r></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border=
-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><br>Le lundi 4 =
juin 2018 07:31:03 UTC+2, Edward Catmur a =C3=A9crit=C2=A0:<blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"auto"><div><br><br><div class=3D"gmail_=
quote"><div dir=3D"ltr">On Sun, 3 Jun 2018, 13:21 , <<a rel=3D"nofollow =
noreferrer noreferrer">floria...@gmail.com</a>> wrote:<br></div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><br>Le dimanche 3 juin 2018 13:16:1=
8 UTC+2, Magnus Fromreide a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex">Hello
<br>
<br>I am more than a little concerned about all this talk of multiple evalu=
ation
<br>of lazy arguments.
<br>
<br>I presume that everone agrees that given
<br>
<br>void f([]->int);
<br>
<br>then after
<br>
<br>int a =3D 10;
<br>f(a++);
<br>
<br>the value of a is either 10 or 11, no other values are possible.
<br>(BTW, What a great obfuscation tool this would be even with this limita=
tion)
<br></blockquote><div><br></div><div><div>This example is really great to s=
how mutliple evaluations should not be allowed, period.</div><div>BTW,
the example I showed with manually caching the result in a lambda gives
this behavior: the lazy expression is evaluated once.</div></div><div>=C2=
=A0</div></div></blockquote></div></div><div dir=3D"auto"><br></div><div di=
r=3D"auto"><br></div><div dir=3D"auto">That depends, though. We're perf=
ectly happy to write `while (a++) ...;` and it's not unreasonable to th=
ink that this facility might be used for functions with control flow that r=
equires multiple invocation.=C2=A0</div></div></blockquote><div><br></div><=
div>For that kind of stuff, I would prefer a "macro-like" approac=
h. I know some people were working on that. It's personal taste here.</=
div><div>=C2=A0</div></div></blockquote></div></div><div dir=3D"auto"><br><=
/div><div dir=3D"auto">If this could be (part of) that macro-like approach,=
I'm sure conventions would arise to distinguish between functions taki=
ng lazy arguments that are evaluated at most once and those whose lazy argu=
ments may be evaluated multiple times.=C2=A0</div><div dir=3D"auto"><br></d=
iv><div dir=3D"auto"><div class=3D"gmail_quote"><blockquote class=3D"gmail_=
quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1=
ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;ma=
rgin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"au=
to"><div dir=3D"auto"></div><div dir=3D"auto"><br></div><div dir=3D"auto"><=
br></div><div dir=3D"auto"><div class=3D"gmail_quote"><blockquote class=3D"=
gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-=
left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margi=
n:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>This in turn means that any second evaluation of the lazy expression mu=
st
<br>be forbidden unless the compiler can prove it to be side effect free.
<br>
<br></blockquote>Unless the compiler inline both the caller and the lazy ex=
pression, it will not be able to prove this side-effect free property.<br>A=
nd if both are inlined, all technical issues disappear.<br><div><br></div><=
div>@Edward<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div=
><div dir=3D"auto">It should be possible to implement multiple evaluation=
=20
without caching by storing lifetime extended temporaries in a=20
conventionally located stack frame and then not restoring (or only=20
partially restoring) the stack pointer on return from evaluation. This=20
should be technically possible on any platform where alloca is=20
implementable.=C2=A0</div><div dir=3D"auto"><br></div><div dir=3D"auto">The=
stack would look like: (growing downwards)=C2=A0</div><div dir=3D"auto"><b=
r></div><div dir=3D"auto">caller</div><div dir=3D"auto">callee</div><div di=
r=3D"auto">lazy1a temporaries</div><div dir=3D"auto">lazy2 temporaries</div=
><div dir=3D"auto">lazy1b temporaries</div><div dir=3D"auto">inner function=
</div><div dir=3D"auto"><br></div><div dir=3D"auto">Here
lazy1 is evaluated twice within the same expression, giving two sets of
temporaries. The temporaries would be destructed and their stack space=20
reclaimed at the end of the full-expression in the callee. Note that the
stack space used is bounded by the size of the expression in the=20
callee.=C2=A0</div><div dir=3D"auto"><br></div><div dir=3D"auto">This would=
have=20
the advantage that scope, lifetime and stack location would be more=20
conventionally correlated, and may be technically easier to implement=20
than storing temporaries within the stack frame of the caller. <br></div></=
div></blockquote><div><br></div><div>Unfortunatley, if the lazy expression =
"calls" alloca, the stack memory will be deallocated when the laz=
y expression ends its scope. That's why allocating this memory in the c=
aller stack frame is much easier.</div></div></blockquote></div></div><div =
dir=3D"auto"><br></div><div dir=3D"auto">Sorry, I didn't mean to imply =
that the lazy expression would call alloca. Rather it would behave like all=
oca, giving the stack pointer a different value on exit than on entry.=C2=
=A0</div></div></blockquote><div><br></div><div>(alloca is not a function a=
nyway, it is just some arithmetic on pointers)</div><div>The problem is: if=
you give a different stack pointer to the callee, it would need to adjust =
back the pointer itself to access its data. And what if the callee needs to=
allocate some stack after evaluating a lazy expression? Where would the ne=
w stack frame go? How does the caller know where it would go?</div><div><br=
></div><div>After some thinking, I agree it might be possible to implement,=
but at what costs?<br></div><div>=C2=A0</div></div></blockquote></div></di=
v><div dir=3D"auto"><br></div><div dir=3D"auto">It would require the use of=
an additional register to hold the base address. This wouldn't be part=
icularly expensive; it was after all till relatively recently the conventio=
n to hold a base pointer in ebp.=C2=A0</div><div dir=3D"auto"><br></div><di=
v dir=3D"auto"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote"=
style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-l=
eft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"auto"><d=
iv dir=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gmail_quote"><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><div>Also, how would you track =
down all destructors that would be needed to be called?</div></div></blockq=
uote></div></div><div dir=3D"auto"><br></div><div dir=3D"auto">That would b=
e the job of the lazy expression routine; the callee would invoke the lazy =
expression routines in destruct mode as many times as they were invoked in =
evaluate mode and in reverse.=C2=A0</div><div dir=3D"auto"><br></div><div d=
ir=3D"auto">Recall that you need a destruct mode to be invoked by the calle=
e to ensure that destructors of temporaries are called at the end of the co=
rrect statement in the callee.=C2=A0</div></div></blockquote><div><br></div=
><div>I don't recall that. It was suggested, but I think the lazy expre=
ssion temporaries must outlive the caller expression (not only the callee o=
ne).</div><div><div style=3D"background-color:rgb(250,250,250);border-color=
:rgb(187,187,187);border-style:solid;border-width:1px" class=3D"m_-18115110=
14130285790m_5349201106274152878prettyprint"><code class=3D"m_-181151101413=
0285790m_5349201106274152878prettyprint"><div class=3D"m_-18115110141302857=
90m_5349201106274152878subprettyprint"><span style=3D"color:#008" class=3D"=
m_-1811511014130285790m_5349201106274152878styled-by-prettify">void</span><=
span style=3D"color:#000" class=3D"m_-1811511014130285790m_5349201106274152=
878styled-by-prettify"> </span><span style=3D"color:#008" class=3D"m_-18115=
11014130285790m_5349201106274152878styled-by-prettify">print</span><span st=
yle=3D"color:#660" class=3D"m_-1811511014130285790m_5349201106274152878styl=
ed-by-prettify">(</span><span style=3D"color:#000" class=3D"m_-181151101413=
0285790m_5349201106274152878styled-by-prettify">std</span><span style=3D"co=
lor:#660" class=3D"m_-1811511014130285790m_5349201106274152878styled-by-pre=
ttify">::</span><span style=3D"color:#000" class=3D"m_-1811511014130285790m=
_5349201106274152878styled-by-prettify">string_view sv</span><span style=3D=
"color:#660" class=3D"m_-1811511014130285790m_5349201106274152878styled-by-=
prettify">)</span><span style=3D"color:#000" class=3D"m_-181151101413028579=
0m_5349201106274152878styled-by-prettify"> </span><span style=3D"color:#660=
" class=3D"m_-1811511014130285790m_5349201106274152878styled-by-prettify">{=
</span><span style=3D"color:#000" class=3D"m_-1811511014130285790m_53492011=
06274152878styled-by-prettify"> std</span><span style=3D"color:#660" class=
=3D"m_-1811511014130285790m_5349201106274152878styled-by-prettify">::</span=
><span style=3D"color:#000" class=3D"m_-1811511014130285790m_53492011062741=
52878styled-by-prettify">cout </span><span style=3D"color:#660" class=3D"m_=
-1811511014130285790m_5349201106274152878styled-by-prettify"><<</span=
><span style=3D"color:#000" class=3D"m_-1811511014130285790m_53492011062741=
52878styled-by-prettify"> sv </span><span style=3D"color:#660" class=3D"m_-=
1811511014130285790m_5349201106274152878styled-by-prettify"><<</span>=
<span style=3D"color:#000" class=3D"m_-1811511014130285790m_534920110627415=
2878styled-by-prettify"> std</span><span style=3D"color:#660" class=3D"m_-1=
811511014130285790m_5349201106274152878styled-by-prettify">::</span><span s=
tyle=3D"color:#000" class=3D"m_-1811511014130285790m_5349201106274152878sty=
led-by-prettify">endl</span><span style=3D"color:#660" class=3D"m_-18115110=
14130285790m_5349201106274152878styled-by-prettify">;</span><span style=3D"=
color:#000" class=3D"m_-1811511014130285790m_5349201106274152878styled-by-p=
rettify"> </span><span style=3D"color:#660" class=3D"m_-1811511014130285790=
m_5349201106274152878styled-by-prettify">}</span><code class=3D"m_-18115110=
14130285790m_5349201106274152878prettyprint"><span style=3D"color:#000" cla=
ss=3D"m_-1811511014130285790m_5349201106274152878styled-by-prettify"><br>st=
d</span><span style=3D"color:#660" class=3D"m_-1811511014130285790m_5349201=
106274152878styled-by-prettify">::</span><span style=3D"color:#000" class=
=3D"m_-1811511014130285790m_5349201106274152878styled-by-prettify">string_v=
iew lazy</span><span style=3D"color:#660" class=3D"m_-1811511014130285790m_=
5349201106274152878styled-by-prettify">([]</span><span style=3D"color:#000"=
class=3D"m_-1811511014130285790m_5349201106274152878styled-by-prettify"> <=
/span><span style=3D"color:#660" class=3D"m_-1811511014130285790m_534920110=
6274152878styled-by-prettify">-></span><span style=3D"color:#000" class=
=3D"m_-1811511014130285790m_5349201106274152878styled-by-prettify"> std</sp=
an><span style=3D"color:#660" class=3D"m_-1811511014130285790m_534920110627=
4152878styled-by-prettify">::</span><span style=3D"color:#008" class=3D"m_-=
1811511014130285790m_5349201106274152878styled-by-prettify">string</span><s=
pan style=3D"color:#000" class=3D"m_-1811511014130285790m_53492011062741528=
78styled-by-prettify"> s</span><span style=3D"color:#660" class=3D"m_-18115=
11014130285790m_5349201106274152878styled-by-prettify">)</span><span style=
=3D"color:#000" class=3D"m_-1811511014130285790m_5349201106274152878styled-=
by-prettify"> </span><span style=3D"color:#660" class=3D"m_-181151101413028=
5790m_5349201106274152878styled-by-prettify">{</span><span style=3D"color:#=
000" class=3D"m_-1811511014130285790m_5349201106274152878styled-by-prettify=
"> </span><span style=3D"color:#008" class=3D"m_-1811511014130285790m_53492=
01106274152878styled-by-prettify">return</span><span style=3D"color:#000" c=
lass=3D"m_-1811511014130285790m_5349201106274152878styled-by-prettify"> s</=
span><span style=3D"color:#660" class=3D"m_-1811511014130285790m_5349201106=
274152878styled-by-prettify">;</span><span style=3D"color:#000" class=3D"m_=
-1811511014130285790m_5349201106274152878styled-by-prettify"> </span><span =
style=3D"color:#660" class=3D"m_-1811511014130285790m_5349201106274152878st=
yled-by-prettify">}</span><span style=3D"color:#000" class=3D"m_-1811511014=
130285790m_5349201106274152878styled-by-prettify"></span></code><code class=
=3D"m_-1811511014130285790m_5349201106274152878prettyprint"><span style=3D"=
color:#000" class=3D"m_-1811511014130285790m_5349201106274152878styled-by-p=
rettify"><br>std</span><span style=3D"color:#660" class=3D"m_-1811511014130=
285790m_5349201106274152878styled-by-prettify">::</span><span style=3D"colo=
r:#000" class=3D"m_-1811511014130285790m_5349201106274152878styled-by-prett=
ify">string_view eager</span><span style=3D"color:#660" class=3D"m_-1811511=
014130285790m_5349201106274152878styled-by-prettify">(const </span><span st=
yle=3D"color:#000" class=3D"m_-1811511014130285790m_5349201106274152878styl=
ed-by-prettify"></span><span style=3D"color:#660" class=3D"m_-1811511014130=
285790m_5349201106274152878styled-by-prettify"></span><span style=3D"color:=
#000" class=3D"m_-1811511014130285790m_5349201106274152878styled-by-prettif=
y">std</span><span style=3D"color:#660" class=3D"m_-1811511014130285790m_53=
49201106274152878styled-by-prettify">::</span><span style=3D"color:#008" cl=
ass=3D"m_-1811511014130285790m_5349201106274152878styled-by-prettify">strin=
g</span><span style=3D"color:#000" class=3D"m_-1811511014130285790m_5349201=
106274152878styled-by-prettify"> & s</span><span style=3D"color:#660" c=
lass=3D"m_-1811511014130285790m_5349201106274152878styled-by-prettify">)</s=
pan><span style=3D"color:#000" class=3D"m_-1811511014130285790m_53492011062=
74152878styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_-=
1811511014130285790m_5349201106274152878styled-by-prettify">{</span><span s=
tyle=3D"color:#000" class=3D"m_-1811511014130285790m_5349201106274152878sty=
led-by-prettify"> </span><span style=3D"color:#008" class=3D"m_-18115110141=
30285790m_5349201106274152878styled-by-prettify">return</span><span style=
=3D"color:#000" class=3D"m_-1811511014130285790m_5349201106274152878styled-=
by-prettify"> s</span><span style=3D"color:#660" class=3D"m_-18115110141302=
85790m_5349201106274152878styled-by-prettify">;</span><span style=3D"color:=
#000" class=3D"m_-1811511014130285790m_5349201106274152878styled-by-prettif=
y"> </span><span style=3D"color:#660" class=3D"m_-1811511014130285790m_5349=
201106274152878styled-by-prettify">}</span><span style=3D"color:#000" class=
=3D"m_-1811511014130285790m_5349201106274152878styled-by-prettify"><br></sp=
an></code><code class=3D"m_-1811511014130285790m_5349201106274152878prettyp=
rint"><span style=3D"color:#000" class=3D"m_-1811511014130285790m_534920110=
6274152878styled-by-prettify"><code class=3D"m_-1811511014130285790m_534920=
1106274152878prettyprint"><code class=3D"m_-1811511014130285790m_5349201106=
274152878prettyprint"><span style=3D"color:#000" class=3D"m_-18115110141302=
85790m_5349201106274152878styled-by-prettify"><br>print(eager("hello w=
orld!"));</span></code></code><br>print(lazy("hello world!")=
);<br></span></code><span style=3D"color:#000" class=3D"m_-1811511014130285=
790m_5349201106274152878styled-by-prettify"></span></div></code></div>The e=
ager expression works perfectly fine now: the std::string temporary lifetim=
e ends at the semicolon (<a href=3D"https://godbolt.org/g/6xV4aM" rel=3D"no=
referrer noreferrer" target=3D"_blank">https://godbolt.org/g/6xV4aM</a>).<b=
r></div><div>I would expect the second to also works for the very same reas=
on.</div><div><br></div><div>This can happen only if the caller is the one =
to destroy the lazy expression temporaries.<br></div><div>=C2=A0</div></div=
></blockquote></div></div><div dir=3D"auto"><br></div><div dir=3D"auto">Ah,=
that's an interesting point, thanks. I suppose it makes a difference w=
hether you regard this facility as a different kind of parameter or as a ma=
cro replacement, but certainly your example should work, which is a strong =
argument for destruction handled by the caller.=C2=A0</div><div dir=3D"auto=
"></div><div dir=3D"auto"><br></div><div dir=3D"auto"><br></div><div dir=3D=
"auto"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.=
8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"auto"><div dir=
=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gmail_quote"><blockquot=
e class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc sol=
id;padding-left:1ex"><div dir=3D"ltr"><div>If you want multiple scopes, you=
will need heap memory allocation at some point, which is really not needed=
to have a very useful feature.</div></div></blockquote></div></div><div di=
r=3D"auto"><br></div><div dir=3D"auto">I don't see why?=C2=A0</div></di=
v></blockquote><div><br></div><div>Maybe not, but very hard. Especially to =
make the destruction happens in the caller as I explained just above.<br></=
div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0;ma=
rgin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"au=
to"><div dir=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gmail_quote=
"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:=
1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>You can always creat=
e more complex objects from the simple lazy expression that cannot be evalu=
ated multiple times to achieve your goal.<br></div></div></blockquote></div=
></div><div dir=3D"auto"><br></div><div dir=3D"auto">Yes, but then you lose=
prvalue-ness, as you have pointed out.=C2=A0</div></div></blockquote><div>=
<br></div><div>I don't see any valid use case where these 2 features mi=
ght be needed at the same time. If you really want multiple evaluations als=
o allowing prvalues, why callables are not enough?<br></div><div>=C2=A0</di=
v></div></blockquote></div></div><div dir=3D"auto"><br></div><div dir=3D"au=
to">There's advantages of terseness, and also of lifetime of temporarie=
s - extended into the callee, if not the caller.=C2=A0</div><div dir=3D"aut=
o"></div><div dir=3D"auto"><br></div><div dir=3D"auto"><br></div><div dir=
=3D"auto"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div di=
r=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0=
..8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"auto"><div di=
r=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gmail_quote"><blockquo=
te class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc so=
lid;padding-left:1ex"><div dir=3D"ltr"><div></div><div><br></div><div>Also,=
what if the lazy expression calls new: how do you track down the multiple =
allocations?</div></div></blockquote></div></div><div dir=3D"auto"><br></di=
v><div dir=3D"auto">Assuming the new-expressions are adopted by a smart poi=
nter, normal RAII would apply.=C2=A0</div></div></blockquote><div><br></div=
><div>You don't need RAII for this code to be correct:</div><div><div s=
tyle=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bor=
der-style:solid;border-width:1px" class=3D"m_-1811511014130285790m_53492011=
06274152878prettyprint"><code class=3D"m_-1811511014130285790m_534920110627=
4152878prettyprint"><div class=3D"m_-1811511014130285790m_53492011062741528=
78subprettyprint"><span style=3D"color:#606" class=3D"m_-181151101413028579=
0m_5349201106274152878styled-by-prettify">int i =3D /* ... */;<br>int* p =
=3D i > 0 ? new int(i) : nullptr;<br>/* ... */<br>if (p) delete p;<br></=
span><span style=3D"color:#660" class=3D"m_-1811511014130285790m_5349201106=
274152878styled-by-prettify"></span></div></code></div>Why would it be diff=
erent with custom functions, or custom types?</div><div><br></div><div>I ag=
ree smart pointers are much safer and should be used everywhere a new/delet=
e was used. But this is still valid code.<br></div><div>=C2=A0</div></div><=
/blockquote></div></div><div dir=3D"auto"><br></div><div dir=3D"auto">It=
9;s fragile if the ellipsized code can throw, or merely return. I prefer sm=
art pointers or scope guards wherever reasonable.=C2=A0</div><div dir=3D"au=
to"><br></div><div dir=3D"auto"><div class=3D"gmail_quote"><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"=
margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><di=
v dir=3D"auto"><div dir=3D"auto"><br></div><div dir=3D"auto"><div class=3D"=
gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>If the la=
zy expression is very expensive, do you really want do execute the all thin=
g again?<br></div></div></blockquote></div></div><div dir=3D"auto"><br></di=
v><div dir=3D"auto">Probably not, but that should generally be the user'=
;s choice.=C2=A0</div></div></blockquote><div><br></div><div>A user might n=
ot be able to tell if an expression is expensive or not. It will be even mo=
re true with this because it will be simpler to call complex constructors w=
ithout even noticing (and that's part of the point).<br></div><div>=C2=
=A0</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"auto"><div dir=
=3D"auto"><br></div><div dir=3D"auto"><div class=3D"gmail_quote"><blockquot=
e class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc sol=
id;padding-left:1ex"><div dir=3D"ltr"><div></div><div>Caching is the only s=
ensible way to allow multiple evaluations, but this forbids pr-values, with=
all the issues mentionned before.</div><div><br></div><div>And as I showed=
earlier, if a caller needs to cache the result, it can do it. Whereas othe=
r proposals do not/cannot solve altogether the pr-value issue, the lifetime=
issues and the performance issue.</div><div>Of course it needs a bit of bo=
ilerplate code to actually do the caching, but this use case should be rare=
enough. And the caching code is really understandable and easy to come up =
with, especially if you know the lazy expression will always be evaluated.<=
/div><div><br></div><div>One solution might be to have both: <span style=3D=
"font-family:courier new,monospace">[] -></span> lazy parameter <i>witho=
ut</i> caching=C2=A0 and <span style=3D"font-family:courier new,monospace">=
[=3D] -></span> lazy parameter <i>with</i> caching (with no consideratio=
n on how it is implemented).<br></div><div><br></div><div>Anyway, if you ne=
ed multiple evaluations, why do you pass a lazy expression and not a callab=
le? That would make your intent much clearer.<br></div></div></blockquote><=
/div></div><div dir=3D"auto"><br></div><div dir=3D"auto">In general, I agre=
e with all of the above. I am concerned that there may be use cases (e.g. c=
urrent macros) that would benefit from multiple evaluation (non-cached) bei=
ng defined, and I would not want multiple evaluation to be excluded that I =
believe I have shown can be avoided.=C2=A0</div></div></blockquote><div><br=
></div><div>For now, I don't see any use case that would really need th=
is syntax boilerplate free at call site feature.</div><div>I really believe=
that this kind of problems should be solved either with callables or "=
;macro"-like constructions.</div><div><br></div><div>Also multiple eva=
luation could also be added afterwards if there is a need for it. As long a=
s we say multiple evaluation is undefined, then extending it would be possi=
ble.</div><div></div></div></blockquote></div></div><div dir=3D"auto"><br><=
/div><div dir=3D"auto">Yes, that's reasonable. Thanks for taking the ti=
me to present your ideas and arguments.=C2=A0</div><div dir=3D"auto"><br></=
div><div dir=3D"auto"><div class=3D"gmail_quote"><blockquote class=3D"gmail=
_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:=
1ex"><div dir=3D"ltr"><div><br></div><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);paddin=
g-left:1ex"><div><br></div><div><span style=3D"color:rgb(34,34,34);font-fam=
ily:arial,sans-serif;font-size:small;font-style:normal;font-weight:400;lett=
er-spacing:normal;text-align:start;text-indent:0px;text-transform:none;whit=
e-space:normal;word-spacing:0px;background-color:rgb(255,255,255);float:non=
e;display:inline">Sorry,
missed a few words there: I would not want multiple evaluation to be=20
excluded *on the basis of technical considerations* that I believe I=20
have shown can be avoided.</span></div></blockquote><div><span style=3D"col=
or:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:no=
rmal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px=
;text-transform:none;white-space:normal;word-spacing:0px;background-color:r=
gb(255,255,255);float:none;display:inline"><br></span></div><div><span styl=
e=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-=
style:normal;font-weight:400;letter-spacing:normal;text-align:start;text-in=
dent:0px;text-transform:none;white-space:normal;word-spacing:0px;background=
-color:rgb(255,255,255);float:none;display:inline">More than technical cons=
iderations, it is performance considerations. You want the fast cases being=
fast: if the lazy expression is just a literal, you really don't want =
all the implementation boilerplate to deal with multiple evaluations and te=
mporaries bookkeeping.</span></div><div><span style=3D"color:rgb(34,34,34);=
font-family:arial,sans-serif;font-size:small;font-style:normal;font-weight:=
400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:n=
one;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);f=
loat:none;display:inline">Your solution makes this use case inefficient bec=
ause the callee won't know the lazy expression is as simple as that.<br=
></span></div><div><span style=3D"color:rgb(34,34,34);font-family:arial,san=
s-serif;font-size:small;font-style:normal;font-weight:400;letter-spacing:no=
rmal;text-align:start;text-indent:0px;text-transform:none;white-space:norma=
l;word-spacing:0px;background-color:rgb(255,255,255);float:none;display:inl=
ine">In the implementation I proposed, this is as fast as it could get with=
out inlining: just a call to a function returning the literal.<br></span></=
div></div>
<p></p>
-- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/5oUZysJB4HE/unsubscribe" rel=3D"noreferr=
er noreferrer" target=3D"_blank">https://groups.google.com/a/isocpp.org/d/t=
opic/std-proposals/5oUZysJB4HE/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org" rel=3D"noreferrer noreferr=
er" target=3D"_blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" rel=3D"noreferrer noreferrer" target=3D"_blank">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/ff30ffc4-f898-4b10-a26e-a6e9c2560642%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" rel=3D"noreferrer =
noreferrer" target=3D"_blank">https://groups.google.com/a/isocpp.org/d/msgi=
d/std-proposals/ff30ffc4-f898-4b10-a26e-a6e9c2560642%40isocpp.org</a>.<br>
</blockquote></div></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/CAJnLdObh9-Ysxm9awoc_-Ysz30GkwFjx8TYt=
%3DhzkXiw9Rxttug%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdObh9-Ysxm=
9awoc_-Ysz30GkwFjx8TYt%3DhzkXiw9Rxttug%40mail.gmail.com</a>.<br />
--000000000000eac3d6056dee82e7--
.
Author: "'Edward Catmur' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Thu, 14 Jun 2018 19:15:22 +0100
Raw View
--0000000000003ad332056e9e15d8
Content-Type: text/plain; charset="UTF-8"
On Thu, Jun 14, 2018 at 8:19 AM, Bengt Gustafsson <
bengt.gustafsson@beamways.com> wrote:
> I have been pondering this proposal and P0927 for a while to see if I
> could reconcile the two use cases of P0927 into one decent feature. I
> failed, and I think that they must be served by different features.
>
> The first use case is to avoid evaluating argument expressions if not
> needed, which may be a performance optimization such as in a logging case
> or semantically important as in a shortcut operator. The parameter of
> std::optional::value_or would also be a good use case if it wasn't too late
> for that. Here an important property is that the call site does not have to
> care whether the parameter is lazy and that the argument can be forwarded
> to another lazy parameter without problems. These two requirements mean
> that temporaries of the argument expression must be preserved until the
> callee returns and that the parameter must be allowed to be evaluatated
> more than once (or forwarding would be ridiculously useless).
>
I don't see it, why would forwarding require allowing evaluating the
parameter more than once?
--
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/CAJnLdObzvu%3DNOe59qvcVmEno-S%2B9h_XkM_kVO8D0_oJnhs7JNA%40mail.gmail.com.
--0000000000003ad332056e9e15d8
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Thu, Jun 14, 2018 at 8:19 AM, Bengt Gustafsson <span dir=3D"ltr"><=
;<a href=3D"mailto:bengt.gustafsson@beamways.com" target=3D"_blank">bengt.g=
ustafsson@beamways.com</a>></span> wrote:<br><blockquote class=3D"gmail_=
quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1=
ex"><div dir=3D"ltr">I have been pondering this proposal and P0927 for a wh=
ile to see if I could reconcile the two use cases of P0927 into one decent =
feature. I failed, and I think that they must be served by different featur=
es.<div><br></div><div>The first use case is to avoid evaluating argument e=
xpressions if not needed, which may be a performance optimization such as i=
n a logging case or semantically important as in a shortcut operator. The p=
arameter of std::optional::value_or would also be a good use case if it was=
n't too late for that. Here an important property is that the call site=
does not have to care whether the parameter is lazy and that the argument =
can be forwarded to another lazy parameter without problems. These two requ=
irements mean that temporaries of the argument expression must be preserved=
until the callee returns and that the parameter must be allowed to be eval=
uatated more than once (or forwarding would be ridiculously useless).</div>=
</div></blockquote><div><br></div><div>I don't see it, why would forwar=
ding require allowing evaluating the parameter more than once?</div></div><=
/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/CAJnLdObzvu%3DNOe59qvcVmEno-S%2B9h_Xk=
M_kVO8D0_oJnhs7JNA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJnLdObzvu%3=
DNOe59qvcVmEno-S%2B9h_XkM_kVO8D0_oJnhs7JNA%40mail.gmail.com</a>.<br />
--0000000000003ad332056e9e15d8--
.
Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Fri, 15 Jun 2018 03:21:39 -0700 (PDT)
Raw View
------=_Part_7000_97269334.1529058099610
Content-Type: multipart/alternative;
boundary="----=_Part_7001_1450987212.1529058099611"
------=_Part_7001_1450987212.1529058099611
Content-Type: text/plain; charset="UTF-8"
Den torsdag 14 juni 2018 kl. 20:15:25 UTC+2 skrev Edward Catmur:
>
>
>
> On Thu, Jun 14, 2018 at 8:19 AM, Bengt Gustafsson <
> bengt.gu...@beamways.com <javascript:>> wrote:
>
>> I have been pondering this proposal and P0927 for a while to see if I
>> could reconcile the two use cases of P0927 into one decent feature. I
>> failed, and I think that they must be served by different features.
>>
>> The first use case is to avoid evaluating argument expressions if not
>> needed, which may be a performance optimization such as in a logging case
>> or semantically important as in a shortcut operator. The parameter of
>> std::optional::value_or would also be a good use case if it wasn't too late
>> for that. Here an important property is that the call site does not have to
>> care whether the parameter is lazy and that the argument can be forwarded
>> to another lazy parameter without problems. These two requirements mean
>> that temporaries of the argument expression must be preserved until the
>> callee returns and that the parameter must be allowed to be evaluatated
>> more than once (or forwarding would be ridiculously useless).
>>
>
> I don't see it, why would forwarding require allowing evaluating the
> parameter more than once?
>
I understand that there was hard to see my conclusion here, but I showed an
example earlier in this thread where a shortcut operation, as part of its
implementation, logs the incoming parameter value by forwarding it to a
logging function that may, or may not, actually evaluate the parameter.
Thus when log returns, the main callee does not know if the parameter has
already been evaluated as it depend on whether logging is enabled. Thus if
it requires the parameter value it must be able to do so even if log() also
did.
bool andand([]->bool lhs, []->bool rhs)
{
Log("Performing andand on", lhs, " and ", rhs); // Variadic log with
lazy parameters only evaluated if logging is enabled.
return lhs() && rhs(); // This is UB if logging is enabled!
}
--
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/7b9e57c3-932a-4d7a-b476-97a7ac76e488%40isocpp.org.
------=_Part_7001_1450987212.1529058099611
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>Den torsdag 14 juni 2018 kl. 20:15:25 UTC+2 skrev =
Edward Catmur:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><br><div><br><div class=3D"gmail_quote">On Thu, Jun 14, 2018 at 8:19 AM, B=
engt Gustafsson <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_bl=
ank" gdf-obfuscated-mailto=3D"0nHL3-KeAgAJ" rel=3D"nofollow" onmousedown=3D=
"this.href=3D'javascript:';return true;" onclick=3D"this.href=3D=
9;javascript:';return true;">bengt.gu...@beamways.com</a><wbr>></spa=
n> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">I have been po=
ndering this proposal and P0927 for a while to see if I could reconcile the=
two use cases of P0927 into one decent feature. I failed, and I think that=
they must be served by different features.<div><br></div><div>The first us=
e case is to avoid evaluating argument expressions if not needed, which may=
be a performance optimization such as in a logging case or semantically im=
portant as in a shortcut operator. The parameter of std::optional::value_or=
would also be a good use case if it wasn't too late for that. Here an =
important property is that the call site does not have to care whether the =
parameter is lazy and that the argument can be forwarded to another lazy pa=
rameter without problems. These two requirements mean that temporaries of t=
he argument expression must be preserved until the callee returns and that =
the parameter must be allowed to be evaluatated more than once (or forwardi=
ng would be ridiculously useless).</div></div></blockquote><div><br></div><=
div>I don't see it, why would forwarding require allowing evaluating th=
e parameter more than once?</div></div></div></div></blockquote><div>I unde=
rstand that there was hard to see my conclusion here, but I showed an examp=
le earlier in this thread where a shortcut operation, as part of its implem=
entation, logs the incoming parameter value by forwarding it to a logging f=
unction that may, or may not, actually evaluate the parameter. Thus when lo=
g returns, the main callee does not know if the parameter has already been =
evaluated as it depend on whether logging is enabled. Thus if it requires t=
he parameter value it must be able to do so even if log() also did.</div><d=
iv><br></div><div><div style=3D"border-width: 1px; border-style: solid; bor=
der-color: rgb(187, 187, 187); background-color: rgb(250, 250, 250); word-w=
rap: break-word;"><code><span style=3D"color: rgb(0, 0, 136);">bool</span><=
span style=3D"color: rgb(0, 0, 0);">=C2=A0andand</span><span style=3D"color=
: rgb(102, 102, 0);">([]-></span><span style=3D"color: rgb(0, 0, 136);">=
bool</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0lhs</span><span style=
=3D"color: rgb(102, 102, 0);">,</span><span style=3D"color: rgb(0, 0, 0);">=
=C2=A0</span><span style=3D"color: rgb(102, 102, 0);">[]-></span><span s=
tyle=3D"color: rgb(0, 0, 136);">bool</span><span style=3D"color: rgb(0, 0, =
0);">=C2=A0rhs</span><span style=3D"color: rgb(102, 102, 0);">)</span><span=
style=3D"color: rgb(0, 0, 0);"><br></span><span style=3D"color: rgb(102, 1=
02, 0);">{</span><span style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0=C2=
=A0</span><span style=3D"color: rgb(102, 0, 102);">Log</span><span style=3D=
"color: rgb(102, 102, 0);">(</span><span style=3D"color: rgb(0, 136, 0);">&=
quot;Performing andand on"</span><span style=3D"color: rgb(102, 102, 0=
);">,</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0lhs</span><span styl=
e=3D"color: rgb(102, 102, 0);">,</span><span style=3D"color: rgb(0, 0, 0);"=
>=C2=A0</span><span style=3D"color: rgb(0, 136, 0);">" and "</spa=
n><span style=3D"color: rgb(102, 102, 0);">,</span><span style=3D"color: rg=
b(0, 0, 0);">=C2=A0rhs</span><span style=3D"color: rgb(102, 102, 0);">);</s=
pan><span style=3D"color: rgb(0, 0, 0);">=C2=A0=C2=A0=C2=A0</span><span sty=
le=3D"color: rgb(136, 0, 0);">// Variadic log with lazy parameters only eva=
luated if logging is enabled.</span><span style=3D"color: rgb(0, 0, 0);"><b=
r>=C2=A0 =C2=A0=C2=A0</span><span style=3D"color: rgb(0, 0, 136);">return</=
span><span style=3D"color: rgb(0, 0, 0);">=C2=A0lhs</span><span style=3D"co=
lor: rgb(102, 102, 0);">()</span><span style=3D"color: rgb(0, 0, 0);">=C2=
=A0</span><span style=3D"color: rgb(102, 102, 0);">&&</span><span s=
tyle=3D"color: rgb(0, 0, 0);">=C2=A0rhs</span><span style=3D"color: rgb(102=
, 102, 0);">();</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0=C2=A0 =C2=
=A0</span><span style=3D"color: rgb(136, 0, 0);">// This is UB if logging i=
s enabled!</span><span style=3D"color: rgb(0, 0, 0);"><br></span><span styl=
e=3D"color: rgb(102, 102, 0);">}</span><span style=3D"color: rgb(0, 0, 0);"=
><br><br></span></code></div></div><div><br></div><div>=C2=A0</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/7b9e57c3-932a-4d7a-b476-97a7ac76e488%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/7b9e57c3-932a-4d7a-b476-97a7ac76e488=
%40isocpp.org</a>.<br />
------=_Part_7001_1450987212.1529058099611--
------=_Part_7000_97269334.1529058099610--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 15 Jun 2018 06:25:18 -0700 (PDT)
Raw View
------=_Part_7755_1592135473.1529069118681
Content-Type: multipart/alternative;
boundary="----=_Part_7756_124915499.1529069118681"
------=_Part_7756_124915499.1529069118681
Content-Type: text/plain; charset="UTF-8"
On Friday, June 15, 2018 at 6:21:39 AM UTC-4, Bengt Gustafsson wrote:
>
> Den torsdag 14 juni 2018 kl. 20:15:25 UTC+2 skrev Edward Catmur:
>>
>>
>>
>> On Thu, Jun 14, 2018 at 8:19 AM, Bengt Gustafsson <
>> bengt.gu...@beamways.com> wrote:
>>
>>> I have been pondering this proposal and P0927 for a while to see if I
>>> could reconcile the two use cases of P0927 into one decent feature. I
>>> failed, and I think that they must be served by different features.
>>>
>>> The first use case is to avoid evaluating argument expressions if not
>>> needed, which may be a performance optimization such as in a logging case
>>> or semantically important as in a shortcut operator. The parameter of
>>> std::optional::value_or would also be a good use case if it wasn't too late
>>> for that. Here an important property is that the call site does not have to
>>> care whether the parameter is lazy and that the argument can be forwarded
>>> to another lazy parameter without problems. These two requirements mean
>>> that temporaries of the argument expression must be preserved until the
>>> callee returns and that the parameter must be allowed to be evaluatated
>>> more than once (or forwarding would be ridiculously useless).
>>>
>>
>> I don't see it, why would forwarding require allowing evaluating the
>> parameter more than once?
>>
> I understand that there was hard to see my conclusion here, but I showed
> an example earlier in this thread where a shortcut operation, as part of
> its implementation, logs the incoming parameter value by forwarding it to a
> logging function that may, or may not, actually evaluate the parameter.
> Thus when log returns, the main callee does not know if the parameter has
> already been evaluated as it depend on whether logging is enabled. Thus if
> it requires the parameter value it must be able to do so even if log() also
> did.
>
> bool andand([]->bool lhs, []->bool rhs)
> {
> Log("Performing andand on", lhs, " and ", rhs); // Variadic log
> with lazy parameters only evaluated if logging is enabled.
> return lhs() && rhs(); // This is UB if logging is enabled!
> }
>
>
I don't understand why this is a good idea. If logging is enabled, then
your program has substantially different behavior than if logging isn't
enabled. Presumably, the user is using `andand` because they *want* to
ensure that the rhs expression is only evaluated if the lhs expression is
true, right? So if `andand`'s logging is active, then `andand` has the
wrong behavior.
Remember: short-circuit evaluation usually is necessary because `rhs` is *undefined
behavior* if `lhs` is false. Think `andand(x != nullptr && x->foo())`.
--
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/66389f02-b4b8-4820-8a00-b82102a23865%40isocpp.org.
------=_Part_7756_124915499.1529069118681
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 15, 2018 at 6:21:39 AM UTC-4, Bengt Gustaf=
sson 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">De=
n torsdag 14 juni 2018 kl. 20:15:25 UTC+2 skrev Edward Catmur:<blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><br><div><br><div class=3D"gmai=
l_quote">On Thu, Jun 14, 2018 at 8:19 AM, Bengt Gustafsson <span dir=3D"ltr=
"><<a rel=3D"nofollow">bengt.gu...@beamways.com</a>></span> wrote:<br=
><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr">I have been pondering this=
proposal and P0927 for a while to see if I could reconcile the two use cas=
es of P0927 into one decent feature. I failed, and I think that they must b=
e served by different features.<div><br></div><div>The first use case is to=
avoid evaluating argument expressions if not needed, which may be a perfor=
mance optimization such as in a logging case or semantically important as i=
n a shortcut operator. The parameter of std::optional::value_or would also =
be a good use case if it wasn't too late for that. Here an important pr=
operty is that the call site does not have to care whether the parameter is=
lazy and that the argument can be forwarded to another lazy parameter with=
out problems. These two requirements mean that temporaries of the argument =
expression must be preserved until the callee returns and that the paramete=
r must be allowed to be evaluatated more than once (or forwarding would be =
ridiculously useless).</div></div></blockquote><div><br></div><div>I don=
9;t see it, why would forwarding require allowing evaluating the parameter =
more than once?</div></div></div></div></blockquote><div>I understand that =
there was hard to see my conclusion here, but I showed an example earlier i=
n this thread where a shortcut operation, as part of its implementation, lo=
gs the incoming parameter value by forwarding it to a logging function that=
may, or may not, actually evaluate the parameter. Thus when log returns, t=
he main callee does not know if the parameter has already been evaluated as=
it depend on whether logging is enabled. Thus if it requires the parameter=
value it must be able to do so even if log() also did.</div><div><br></div=
><div><div style=3D"border-width:1px;border-style:solid;border-color:rgb(18=
7,187,187);background-color:rgb(250,250,250);word-wrap:break-word"><code><s=
pan style=3D"color:rgb(0,0,136)">bool</span><span style=3D"color:rgb(0,0,0)=
">=C2=A0andand</span><span style=3D"color:rgb(102,102,0)">([]-></span><s=
pan style=3D"color:rgb(0,0,136)">bool</span><span style=3D"color:rgb(0,0,0)=
">=C2=A0lhs</span><span style=3D"color:rgb(102,102,0)">,</span><span style=
=3D"color:rgb(0,0,0)">=C2=A0</span><span style=3D"color:rgb(102,102,0)">[]-=
></span><span style=3D"color:rgb(0,0,136)"><wbr>bool</span><span style=
=3D"color:rgb(0,0,0)">=C2=A0rhs</span><span style=3D"color:rgb(102,102,0)">=
)</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rg=
b(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0=C2=
=A0</span><span style=3D"color:rgb(102,0,102)">Log</span><span style=3D"col=
or:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,136,0)">"Perform=
ing andand on"</span><span style=3D"color:rgb(102,102,0)">,</span><spa=
n style=3D"color:rgb(0,0,0)">=C2=A0lhs</span><span style=3D"color:rgb(102,1=
02,0)">,</span><span style=3D"color:rgb(0,0,0)">=C2=A0</span><span style=3D=
"color:rgb(0,136,0)">" and "</span><span style=3D"color:rgb(102,1=
02,0)">,</span><span style=3D"color:rgb(0,0,0)">=C2=A0rhs</span><span style=
=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)">=C2=A0=
=C2=A0=C2=A0</span><span style=3D"color:rgb(136,0,0)">// Variadic log with =
lazy parameters only evaluated if logging is enabled.</span><span style=3D"=
color:rgb(0,0,0)"><br>=C2=A0 =C2=A0=C2=A0</span><span style=3D"color:rgb(0,=
0,136)">return</span><span style=3D"color:rgb(0,0,0)">=C2=A0lhs</span><span=
style=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)">=
=C2=A0</span><span style=3D"color:rgb(102,102,0)">&&</span><span st=
yle=3D"color:rgb(0,0,0)">=C2=A0rhs</span><span style=3D"color:rgb(102,102,0=
)">();</span><span style=3D"color:rgb(0,0,0)">=C2=A0=C2=A0 =C2=A0</span><sp=
an style=3D"color:rgb(136,0,0)">// This is UB if logging is enabled!</span>=
<span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,10=
2,0)">}</span><span style=3D"color:rgb(0,0,0)"><br><br></span></code></div>=
</div><div></div></div></blockquote><div><br></div><div>I don't underst=
and why this is a good idea. If logging is enabled, then your program has s=
ubstantially different behavior than if logging isn't enabled. Presumab=
ly, the user is using `andand` because they <i>want</i> to ensure that the =
rhs expression is only evaluated if the lhs expression is true, right? So i=
f `andand`'s logging is active, then `andand` has the wrong behavior.</=
div><div><br></div><div>Remember: short-circuit evaluation usually is neces=
sary because `rhs` is <i>undefined behavior</i> if `lhs` is false. Think `a=
ndand(x !=3D nullptr && x->foo())`.<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/66389f02-b4b8-4820-8a00-b82102a23865%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/66389f02-b4b8-4820-8a00-b82102a23865=
%40isocpp.org</a>.<br />
------=_Part_7756_124915499.1529069118681--
------=_Part_7755_1592135473.1529069118681--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 15 Jun 2018 06:35:15 -0700 (PDT)
Raw View
------=_Part_7776_295731699.1529069715317
Content-Type: multipart/alternative;
boundary="----=_Part_7777_1736186821.1529069715318"
------=_Part_7777_1736186821.1529069715318
Content-Type: text/plain; charset="UTF-8"
On Friday, June 15, 2018 at 9:25:18 AM UTC-4, Nicol Bolas wrote:
>
> On Friday, June 15, 2018 at 6:21:39 AM UTC-4, Bengt Gustafsson wrote:
>>
>> Den torsdag 14 juni 2018 kl. 20:15:25 UTC+2 skrev Edward Catmur:
>>>
>>> On Thu, Jun 14, 2018 at 8:19 AM, Bengt Gustafsson <
>>> bengt.gu...@beamways.com> wrote:
>>>
>>>> I have been pondering this proposal and P0927 for a while to see if I
>>>> could reconcile the two use cases of P0927 into one decent feature. I
>>>> failed, and I think that they must be served by different features.
>>>>
>>>> The first use case is to avoid evaluating argument expressions if not
>>>> needed, which may be a performance optimization such as in a logging case
>>>> or semantically important as in a shortcut operator. The parameter of
>>>> std::optional::value_or would also be a good use case if it wasn't too late
>>>> for that. Here an important property is that the call site does not have to
>>>> care whether the parameter is lazy and that the argument can be forwarded
>>>> to another lazy parameter without problems. These two requirements mean
>>>> that temporaries of the argument expression must be preserved until the
>>>> callee returns and that the parameter must be allowed to be evaluatated
>>>> more than once (or forwarding would be ridiculously useless).
>>>>
>>>
>>> I don't see it, why would forwarding require allowing evaluating the
>>> parameter more than once?
>>>
>> I understand that there was hard to see my conclusion here, but I showed
>> an example earlier in this thread where a shortcut operation, as part of
>> its implementation, logs the incoming parameter value by forwarding it to a
>> logging function that may, or may not, actually evaluate the parameter.
>> Thus when log returns, the main callee does not know if the parameter has
>> already been evaluated as it depend on whether logging is enabled. Thus if
>> it requires the parameter value it must be able to do so even if log() also
>> did.
>>
>> bool andand([]->bool lhs, []->bool rhs)
>> {
>> Log("Performing andand on", lhs, " and ", rhs); // Variadic log
>> with lazy parameters only evaluated if logging is enabled.
>> return lhs() && rhs(); // This is UB if logging is enabled!
>> }
>>
>>
> I don't understand why this is a good idea. If logging is enabled, then
> your program has substantially different behavior than if logging isn't
> enabled. Presumably, the user is using `andand` because they *want* to
> ensure that the rhs expression is only evaluated if the lhs expression is
> true, right? So if `andand`'s logging is active, then `andand` has the
> wrong behavior.
>
> Remember: short-circuit evaluation usually is necessary because `rhs` is *undefined
> behavior* if `lhs` is false. Think `andand(x != nullptr && x->foo())`.
>
Sorry; I meant `andand(x != nullptr, x->foo()` at the end.
Also, if the idea with `andand` is not that we have short-circuit
evaluation... then why does it need to use lazy evaluation at all? Why
can't it just take 2 bools? Yes, there will be a few times when rhs *isn't*
evaluated, but that's merely an optimization, not an actual part of the
function's interface. And it's not an optimization that anyone will be
relying on, since the caller must provide an expression with well-defined
behavior.
So why is this important to be able to do?
--
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/c91b3d77-5797-4abf-84dc-a7e854dafb9b%40isocpp.org.
------=_Part_7777_1736186821.1529069715318
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, June 15, 2018 at 9:25:18 AM UTC-4, Nicol Bolas =
wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On Frid=
ay, June 15, 2018 at 6:21:39 AM UTC-4, Bengt Gustafsson wrote:<blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr">Den torsdag 14 juni 2018 kl. 20=
:15:25 UTC+2 skrev Edward Catmur:<blockquote class=3D"gmail_quote" style=3D=
"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr"><div><div class=3D"gmail_quote">On Thu, Jun 14, 2018 at 8:19=
AM, Bengt Gustafsson <span dir=3D"ltr"><<a rel=3D"nofollow">bengt.gu...=
@beamways.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div =
dir=3D"ltr">I have been pondering this proposal and P0927 for a while to se=
e if I could reconcile the two use cases of P0927 into one decent feature. =
I failed, and I think that they must be served by different features.<div><=
br></div><div>The first use case is to avoid evaluating argument expression=
s if not needed, which may be a performance optimization such as in a loggi=
ng case or semantically important as in a shortcut operator. The parameter =
of std::optional::value_or would also be a good use case if it wasn't t=
oo late for that. Here an important property is that the call site does not=
have to care whether the parameter is lazy and that the argument can be fo=
rwarded to another lazy parameter without problems. These two requirements =
mean that temporaries of the argument expression must be preserved until th=
e callee returns and that the parameter must be allowed to be evaluatated m=
ore than once (or forwarding would be ridiculously useless).</div></div></b=
lockquote><div><br></div><div>I don't see it, why would forwarding requ=
ire allowing evaluating the parameter more than once?</div></div></div></di=
v></blockquote><div>I understand that there was hard to see my conclusion h=
ere, but I showed an example earlier in this thread where a shortcut operat=
ion, as part of its implementation, logs the incoming parameter value by fo=
rwarding it to a logging function that may, or may not, actually evaluate t=
he parameter. Thus when log returns, the main callee does not know if the p=
arameter has already been evaluated as it depend on whether logging is enab=
led. Thus if it requires the parameter value it must be able to do so even =
if log() also did.</div><div><br></div><div><div style=3D"border-width:1px;=
border-style:solid;border-color:rgb(187,187,187);background-color:rgb(250,2=
50,250);word-wrap:break-word"><code><span style=3D"color:rgb(0,0,136)">bool=
</span><span style=3D"color:rgb(0,0,0)">=C2=A0andand</span><span style=3D"c=
olor:rgb(102,102,0)">([]-></span><span style=3D"color:rgb(0,0,136)">bool=
</span><span style=3D"color:rgb(0,0,0)">=C2=A0lhs</span><span style=3D"colo=
r:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)">=C2=A0</span><sp=
an style=3D"color:rgb(102,102,0)">[]-></span><span style=3D"color:rgb(0,=
0,136)"><wbr>bool</span><span style=3D"color:rgb(0,0,0)">=C2=A0rhs</span><s=
pan style=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0,0)"=
><br></span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"col=
or:rgb(0,0,0)"><br>=C2=A0 =C2=A0=C2=A0</span><span style=3D"color:rgb(102,0=
,102)">Log</span><span style=3D"color:rgb(102,102,0)">(</span><span style=
=3D"color:rgb(0,136,0)">"Performing andand on"</span><span style=
=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)">=C2=A0lh=
s</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:r=
gb(0,0,0)">=C2=A0</span><span style=3D"color:rgb(0,136,0)">" and "=
;</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:r=
gb(0,0,0)">=C2=A0rhs</span><span style=3D"color:rgb(102,102,0)">);</span><s=
pan style=3D"color:rgb(0,0,0)">=C2=A0=C2=A0=C2=A0</span><span style=3D"colo=
r:rgb(136,0,0)">// Variadic log with lazy parameters only evaluated if logg=
ing is enabled.</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0=C2=
=A0</span><span style=3D"color:rgb(0,0,136)">return</span><span style=3D"co=
lor:rgb(0,0,0)">=C2=A0lhs</span><span style=3D"color:rgb(102,102,0)">()</sp=
an><span style=3D"color:rgb(0,0,0)">=C2=A0</span><span style=3D"color:rgb(1=
02,102,0)">&&</span><span style=3D"color:rgb(0,0,0)">=C2=A0rhs</spa=
n><span style=3D"color:rgb(102,102,0)">();</span><span style=3D"color:rgb(0=
,0,0)">=C2=A0=C2=A0 =C2=A0</span><span style=3D"color:rgb(136,0,0)">// This=
is UB if logging is enabled!</span><span style=3D"color:rgb(0,0,0)"><br></=
span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"color:rgb(=
0,0,0)"><br><br></span></code></div></div><div></div></div></blockquote><di=
v><br></div><div>I don't understand why this is a good idea. If logging=
is enabled, then your program has substantially different behavior than if=
logging isn't enabled. Presumably, the user is using `andand` because =
they <i>want</i> to ensure that the rhs expression is only evaluated if the=
lhs expression is true, right? So if `andand`'s logging is active, the=
n `andand` has the wrong behavior.</div><div><br></div><div>Remember: short=
-circuit evaluation usually is necessary because `rhs` is <i>undefined beha=
vior</i> if `lhs` is false. Think `andand(x !=3D nullptr && x->f=
oo())`.<br></div></div></blockquote><div><br></div><div>Sorry; I meant `and=
and(x !=3D nullptr, x->foo()` at the end.</div><div><br></div><div>Also,=
if the idea with `andand` is not that we have short-circuit evaluation... =
then why does it need to use lazy evaluation at all? Why can't it just =
take 2 bools? Yes, there will be a few times when rhs <i>isn't</i> eval=
uated, but that's merely an optimization, not an actual part of the fun=
ction's interface. And it's not an optimization that anyone will be=
relying on, since the caller must provide an expression with well-defined =
behavior.</div><div><br></div><div>So why is this important to be able to d=
o?<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/c91b3d77-5797-4abf-84dc-a7e854dafb9b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/c91b3d77-5797-4abf-84dc-a7e854dafb9b=
%40isocpp.org</a>.<br />
------=_Part_7777_1736186821.1529069715318--
------=_Part_7776_295731699.1529069715317--
.
Author: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
Date: Fri, 12 Oct 2018 02:28:25 +0200
Raw View
Hi,
We also discussed laziness and "expression-parameters" in two more places:
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/jB5TIcRZeic/HV=
-y43WUAAAJ
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/x5ucKwQI7Bc/y6=
iFvtQUBwAJ
The way I see it is that lazy arguments (i.e. only evaluated once even
if they appear several times -- what P0927 describes) are simply a
sub-case of "expressions copy-pasting"/"macro-like" etc.; so less
flexible, and more complex to specify.
With actual expressions (rather than lazy arguments), we can get a
much simpler proposal (there is not much to specify: simply say that
it behaves as-if the expression was written in-place). Then, if you
want lazy arguments, you can "implement" them simply by assigning the
expression once, to a variable, e.g.
using log(using auto lazy_arg) {
if (level < warning) {
auto x =3D lazy_arg;
// use x as usual
}
}
This is the syntax of P1221's "using" parameters that Jason came up
with from my "expression-parameters" suggestion.
Now, you can free more things since now you are not forced to a single
evaluation. But what is more: the caller has more freedom to decide
how to call it. Take P0927's example:
void fn([] -> std::unique_ptr<int> i) { ... }; // assume fn()
evaluates twice i
This would be:
using fn(using auto i) { ... }; // assume fn() evaluates twice i
Then:
fn(make_unique<int>()); // a new object each time
fn(ptr); // some pointer possibly used twice
fn(std::move(ptr)); // the second time possibly nullptr
Having something like this would remove almost all the remaining uses
for macros + gives us lazy arguments too. And it is simpler to
understand for users, no new semantics, etc. The limitation, of
course, is that this is a compile-time thing only (no real functions
-- but if you need that, you can still pass normal lambdas).
Cheers,
Miguel
On Fri, Jun 15, 2018 at 3:35 PM Nicol Bolas <jmckesson@gmail.com> wrote:
>
> On Friday, June 15, 2018 at 9:25:18 AM UTC-4, Nicol Bolas wrote:
>>
>> On Friday, June 15, 2018 at 6:21:39 AM UTC-4, Bengt Gustafsson wrote:
>>>
>>> Den torsdag 14 juni 2018 kl. 20:15:25 UTC+2 skrev Edward Catmur:
>>>>
>>>> On Thu, Jun 14, 2018 at 8:19 AM, Bengt Gustafsson <bengt.gu...@beamway=
s.com> wrote:
>>>>>
>>>>> I have been pondering this proposal and P0927 for a while to see if I=
could reconcile the two use cases of P0927 into one decent feature. I fail=
ed, and I think that they must be served by different features.
>>>>>
>>>>> The first use case is to avoid evaluating argument expressions if not=
needed, which may be a performance optimization such as in a logging case =
or semantically important as in a shortcut operator. The parameter of std::=
optional::value_or would also be a good use case if it wasn't too late for =
that. Here an important property is that the call site does not have to car=
e whether the parameter is lazy and that the argument can be forwarded to a=
nother lazy parameter without problems. These two requirements mean that te=
mporaries of the argument expression must be preserved until the callee ret=
urns and that the parameter must be allowed to be evaluatated more than onc=
e (or forwarding would be ridiculously useless).
>>>>
>>>>
>>>> I don't see it, why would forwarding require allowing evaluating the p=
arameter more than once?
>>>
>>> I understand that there was hard to see my conclusion here, but I showe=
d an example earlier in this thread where a shortcut operation, as part of =
its implementation, logs the incoming parameter value by forwarding it to a=
logging function that may, or may not, actually evaluate the parameter. Th=
us when log returns, the main callee does not know if the parameter has alr=
eady been evaluated as it depend on whether logging is enabled. Thus if it =
requires the parameter value it must be able to do so even if log() also di=
d.
>>>
>>> bool andand([]->bool lhs, []->bool rhs)
>>> {
>>> Log("Performing andand on", lhs, " and ", rhs); // Variadic log w=
ith lazy parameters only evaluated if logging is enabled.
>>> return lhs() && rhs(); // This is UB if logging is enabled!
>>> }
>>>
>>
>> I don't understand why this is a good idea. If logging is enabled, then =
your program has substantially different behavior than if logging isn't ena=
bled. Presumably, the user is using `andand` because they want to ensure th=
at the rhs expression is only evaluated if the lhs expression is true, righ=
t? So if `andand`'s logging is active, then `andand` has the wrong behavior=
..
>>
>> Remember: short-circuit evaluation usually is necessary because `rhs` is=
undefined behavior if `lhs` is false. Think `andand(x !=3D nullptr && x->f=
oo())`.
>
>
> Sorry; I meant `andand(x !=3D nullptr, x->foo()` at the end.
>
> Also, if the idea with `andand` is not that we have short-circuit evaluat=
ion... then why does it need to use lazy evaluation at all? Why can't it ju=
st take 2 bools? Yes, there will be a few times when rhs isn't evaluated, b=
ut that's merely an optimization, not an actual part of the function's inte=
rface. And it's not an optimization that anyone will be relying on, since t=
he caller must provide an expression with well-defined behavior.
>
> So why is this important to be able to do?
>
> --
> 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/isoc=
pp.org/d/msgid/std-proposals/c91b3d77-5797-4abf-84dc-a7e854dafb9b%40isocpp.=
org.
--=20
Cheers,
Miguel
--=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/CANiq72nqM4XaYkG%2B4TNH5aem0B2%3DPVx-vRpzE7wfjQY=
dkG0yfQ%40mail.gmail.com.
.
Author: florian.csdt@gmail.com
Date: Fri, 12 Oct 2018 01:29:48 -0700 (PDT)
Raw View
------=_Part_571_159712939.1539332988567
Content-Type: multipart/alternative;
boundary="----=_Part_572_979425928.1539332988567"
------=_Part_572_979425928.1539332988567
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le vendredi 12 octobre 2018 02:28:40 UTC+2, Miguel Ojeda a =C3=A9crit :
>
> Hi,=20
>
> We also discussed laziness and "expression-parameters" in two more places=
:=20
>
> =20
> https://groups.google.com/a/isocpp.org/d/msg/std-proposals/jB5TIcRZeic/HV=
-y43WUAAAJ=20
> =20
> https://groups.google.com/a/isocpp.org/d/msg/std-proposals/x5ucKwQI7Bc/y6=
iFvtQUBwAJ=20
>
> The way I see it is that lazy arguments (i.e. only evaluated once even=20
> if they appear several times -- what P0927 describes) are simply a=20
> sub-case of "expressions copy-pasting"/"macro-like" etc.; so less=20
> flexible, and more complex to specify.=20
>
> With actual expressions (rather than lazy arguments), we can get a=20
> much simpler proposal (there is not much to specify: simply say that=20
> it behaves as-if the expression was written in-place). Then, if you=20
> want lazy arguments, you can "implement" them simply by assigning the=20
> expression once, to a variable, e.g.=20
>
> using log(using auto lazy_arg) {=20
> if (level < warning) {=20
> auto x =3D lazy_arg;=20
> // use x as usual=20
> }=20
> }=20
>
> This is the syntax of P1221's "using" parameters that Jason came up=20
> with from my "expression-parameters" suggestion.=20
>
> Now, you can free more things since now you are not forced to a single=20
> evaluation. But what is more: the caller has more freedom to decide=20
> how to call it. Take P0927's example:=20
>
> void fn([] -> std::unique_ptr<int> i) { ... }; // assume fn()=20
> evaluates twice i=20
>
> This would be:=20
>
> using fn(using auto i) { ... }; // assume fn() evaluates twice i=20
>
> Then:=20
>
> fn(make_unique<int>()); // a new object each time=20
> fn(ptr); // some pointer possibly used twice=20
> fn(std::move(ptr)); // the second time possibly nullptr=20
>
> Having something like this would remove almost all the remaining uses=20
> for macros + gives us lazy arguments too. And it is simpler to=20
> understand for users, no new semantics, etc. The limitation, of=20
> course, is that this is a compile-time thing only (no real functions=20
> -- but if you need that, you can still pass normal lambdas).=20
>
> Cheers,=20
> Miguel=20
>
>
Jason's proposal is interesting, and I also thought it could be used to=20
implement lazy parameters, but actually, some stuff are just not possible=
=20
with it.
The main thing I see is: the code must be visible where it is used.
With lazy parameters, you don't need to have the callee code visible from=
=20
the caller. It can be compiled within another Translation Unit.
This can seriously decrease binary size (the same way type erasure does).
Also, what about lifetime of temporaries?
As far as I understand, the lifetime of the temporary will be the same as=
=20
with a macro/code copy-pasted.
And this is something that is simply just not true with lazy parameters.
The lifetime of the lazy parameters is extended as-if it were normal=20
parameters (until the end of the caller expression).
So no surprise for the user.
(If you want more details, you can read the thread again, there are many=20
examples)
And if you want to integrate these lifetime rules within Jason's proposal,=
=20
then it would become much more complex (maybe more complex than lazy=20
parameters?).
A last point about multiple evaluation, this is tricky for the user on its=
=20
own, and it's not needed most of the time. So that's fine for "macro-like"=
=20
approach, but for lazy parameters, I don't think that's a good idea.
Currently in c++ (macros are not C++), there is no expression that could=20
lead to multiple evaluations of sub-expression. But there already are some=
=20
expression where sub-expressions can be discarded without being evaluated.
Jason's proposal is interesting on its own and has many use-cases, but I=20
think lazy parameters is not one of them.
That's why I think the two should be pursued independently.
--=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/c182f5e3-c0c3-46e0-a490-be8897e62cbe%40isocpp.or=
g.
------=_Part_572_979425928.1539332988567
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>Le vendredi 12 octobre 2018 02:28:40 UTC+2, Miguel Oje=
da a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Hi,
<br>
<br>We also discussed laziness and "expression-parameters" in two=
more places:
<br>
<br>=C2=A0 <a href=3D"https://groups.google.com/a/isocpp.org/d/msg/std-prop=
osals/jB5TIcRZeic/HV-y43WUAAAJ" target=3D"_blank" rel=3D"nofollow" onmoused=
own=3D"this.href=3D'https://groups.google.com/a/isocpp.org/d/msg/std-pr=
oposals/jB5TIcRZeic/HV-y43WUAAAJ';return true;" onclick=3D"this.href=3D=
'https://groups.google.com/a/isocpp.org/d/msg/std-proposals/jB5TIcRZeic=
/HV-y43WUAAAJ';return true;">https://groups.google.com/a/<wbr>isocpp.or=
g/d/msg/std-<wbr>proposals/jB5TIcRZeic/HV-<wbr>y43WUAAAJ</a>
<br>=C2=A0 <a href=3D"https://groups.google.com/a/isocpp.org/d/msg/std-prop=
osals/x5ucKwQI7Bc/y6iFvtQUBwAJ" target=3D"_blank" rel=3D"nofollow" onmoused=
own=3D"this.href=3D'https://groups.google.com/a/isocpp.org/d/msg/std-pr=
oposals/x5ucKwQI7Bc/y6iFvtQUBwAJ';return true;" onclick=3D"this.href=3D=
'https://groups.google.com/a/isocpp.org/d/msg/std-proposals/x5ucKwQI7Bc=
/y6iFvtQUBwAJ';return true;">https://groups.google.com/a/<wbr>isocpp.or=
g/d/msg/std-<wbr>proposals/x5ucKwQI7Bc/<wbr>y6iFvtQUBwAJ</a>
<br>
<br>The way I see it is that lazy arguments (i.e. only evaluated once even
<br>if they appear several times -- what P0927 describes) are simply a
<br>sub-case of "expressions copy-pasting"/"macro-like"=
etc.; so less
<br>flexible, and more complex to specify.
<br>
<br>With actual expressions (rather than lazy arguments), we can get a
<br>much simpler proposal (there is not much to specify: simply say that
<br>it behaves as-if the expression was written in-place). Then, if you
<br>want lazy arguments, you can "implement" them simply by assig=
ning the
<br>expression once, to a variable, e.g.
<br>
<br>using log(using auto lazy_arg) {
<br>=C2=A0 if (level < warning) {
<br>=C2=A0 =C2=A0 auto x =3D lazy_arg;
<br>=C2=A0 =C2=A0 // use x as usual
<br>=C2=A0 }
<br>}
<br>
<br>This is the syntax of P1221's "using" parameters that Jas=
on came up
<br>with from my "expression-parameters" suggestion.
<br>
<br>Now, you can free more things since now you are not forced to a single
<br>evaluation. But what is more: the caller has more freedom to decide
<br>how to call it. Take P0927's example:
<br>
<br>=C2=A0 void fn([] -> std::unique_ptr<int> i) { ... }; // assum=
e fn()
<br>evaluates twice i
<br>
<br>This would be:
<br>
<br>=C2=A0 using fn(using auto i) { ... }; // assume fn() evaluates twice i
<br>
<br>Then:
<br>
<br>=C2=A0 fn(make_unique<int>()); // a new object each time
<br>=C2=A0 fn(ptr); // some pointer possibly used twice
<br>=C2=A0 fn(std::move(ptr)); // the second time possibly nullptr
<br>
<br>Having something like this would remove almost all the remaining uses
<br>for macros + gives us lazy arguments too. And it is simpler to
<br>understand for users, no new semantics, etc. The limitation, of
<br>course, is that this is a compile-time thing only (no real functions
<br>-- but if you need that, you can still pass normal lambdas).
<br>
<br>Cheers,
<br>Miguel
<br><br></blockquote><div><br></div><div>Jason's proposal is interestin=
g, and I also thought it could be used to implement lazy parameters, but ac=
tually, some stuff are just not possible with it.</div><div>The main thing =
I see is: the code must be visible where it is used.</div><div>With lazy pa=
rameters, you don't need to have the callee code visible from the calle=
r. It can be compiled within another Translation Unit.</div><div>This can s=
eriously decrease binary size (the same way type erasure does).<br></div><d=
iv><br></div><div>Also, what about lifetime of temporaries?</div><div>As fa=
r as I understand, the lifetime of the temporary will be the same as with a=
macro/code copy-pasted.</div><div>And this is something that is simply jus=
t not true with lazy parameters.</div><div>The lifetime of the lazy paramet=
ers is extended as-if it were normal parameters (until the end of the calle=
r expression).</div><div>So no surprise for the user.</div><div>(If you wan=
t more details, you can read the thread again, there are many examples)</di=
v><div>And if you want to integrate these lifetime rules within Jason's=
proposal, then it would become much more complex (maybe more complex than =
lazy parameters?).</div><div><br></div><div>A last point about multiple eva=
luation, this is tricky for the user on its own, and it's not needed mo=
st of the time. So that's fine for "macro-like" approach, but=
for lazy parameters, I don't think that's a good idea.</div><div>C=
urrently in c++ (macros are not C++), there is no expression that could lea=
d to multiple evaluations of sub-expression. But there already are some exp=
ression where sub-expressions can be discarded without being evaluated.</di=
v><div><br></div><div>Jason's proposal is interesting on its own and ha=
s many use-cases, but I think lazy parameters is not one of them.</div><div=
>That's why I think the two should be pursued independently.<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/c182f5e3-c0c3-46e0-a490-be8897e62cbe%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/c182f5e3-c0c3-46e0-a490-be8897e62cbe=
%40isocpp.org</a>.<br />
------=_Part_572_979425928.1539332988567--
------=_Part_571_159712939.1539332988567--
.
Author: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
Date: Fri, 12 Oct 2018 12:03:43 +0200
Raw View
On Fri, Oct 12, 2018 at 10:29 AM <florian.csdt@gmail.com> wrote:
>
>
> Le vendredi 12 octobre 2018 02:28:40 UTC+2, Miguel Ojeda a =C3=A9crit :
>>
> Jason's proposal is interesting, and I also thought it could be used to i=
mplement lazy parameters, but actually, some stuff are just not possible wi=
th it.
> The main thing I see is: the code must be visible where it is used.
> With lazy parameters, you don't need to have the callee code visible from=
the caller. It can be compiled within another Translation Unit.
> This can seriously decrease binary size (the same way type erasure does).
Indeed, that is what I meant when I said:
>> The limitation, of
>> course, is that this is a compile-time thing only (no real functions
>> -- but if you need that, you can still pass normal lambdas).
In my view, macro-like expansion is something we are 100% missing from
the language (i.e. cannot be done except with macros); while lazy
parameters are something that you can approximate quite nicely today
(e.g. lambdas). Therefore, I value much more the former!
>
> Also, what about lifetime of temporaries?
> As far as I understand, the lifetime of the temporary will be the same as=
with a macro/code copy-pasted.
> And this is something that is simply just not true with lazy parameters.
> The lifetime of the lazy parameters is extended as-if it were normal para=
meters (until the end of the caller expression).
> So no surprise for the user.
> (If you want more details, you can read the thread again, there are many =
examples)
> And if you want to integrate these lifetime rules within Jason's proposal=
, then it would become much more complex (maybe more complex than lazy para=
meters?).
Yep, I did, and I am with Nicol here -- there is no point in
integrating "lifetime rules" for the macro-like approach, that is the
beauty of it.
>
> A last point about multiple evaluation, this is tricky for the user on it=
s own, and it's not needed most of the time.
It is tricky in the same ways as macros, so basically already known by
C programmers; i.e. it is an advantage w.r.t. introducing lazy
arguments (which requires a quite more complex proposal, as you said).
> So that's fine for "macro-like" approach, but for lazy parameters, I don'=
t think that's a good idea.
Agreed: I didn't say it was appropriate for the lazy-arguments approach.
> Currently in c++ (macros are not C++), there is no expression that could =
lead to multiple evaluations of sub-expression. But there already are some =
expression where sub-expressions can be discarded without being evaluated.
Macros are C++, what do you mean? We try to avoid them because they
are on their own phase of translation which gives them shortcomings --
but that is one of the points of the proposal(s): as we have done
previously many times in C++, we are trying to reduce reliance on
macros).
Now, I agree that it is worth discussing whether using this vs. a
macro would be beneficial or not (i.e. whether the proposal is worth
its disadvantages).
>
> Jason's proposal is interesting on its own and has many use-cases, but I =
think lazy parameters is not one of them.
> That's why I think the two should be pursued independently.
Isn't the only non-overlapping use case the ability to use declare
functions which use lazy arguments without a definition? (If I am
missing other significant use cases that cannot be provided by a
macro-like proposal, please let me know!).
Cheers,
Miguel
--=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/CANiq72mrFY7Af3pipGFEZ%3DXJpddwFmPUBJp%3D3VOJZqR=
UnaeNVg%40mail.gmail.com.
.
Author: florian.csdt@gmail.com
Date: Fri, 12 Oct 2018 03:43:23 -0700 (PDT)
Raw View
------=_Part_695_1396704429.1539341003807
Content-Type: multipart/alternative;
boundary="----=_Part_696_1782313318.1539341003807"
------=_Part_696_1782313318.1539341003807
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le vendredi 12 octobre 2018 12:03:57 UTC+2, Miguel Ojeda a =C3=A9crit :
>
> On Fri, Oct 12, 2018 at 10:29 AM <floria...@gmail.com <javascript:>>=20
> wrote:=20
> >=20
> >=20
> > Le vendredi 12 octobre 2018 02:28:40 UTC+2, Miguel Ojeda a =C3=A9crit :=
=20
> >>=20
> > Jason's proposal is interesting, and I also thought it could be used to=
=20
> implement lazy parameters, but actually, some stuff are just not possible=
=20
> with it.=20
> > The main thing I see is: the code must be visible where it is used.=20
> > With lazy parameters, you don't need to have the callee code visible=20
> from the caller. It can be compiled within another Translation Unit.=20
> > This can seriously decrease binary size (the same way type erasure=20
> does).=20
>
> Indeed, that is what I meant when I said:=20
>
> >> The limitation, of=20
> >> course, is that this is a compile-time thing only (no real functions=
=20
> >> -- but if you need that, you can still pass normal lambdas).=20
>
> In my view, macro-like expansion is something we are 100% missing from=20
> the language (i.e. cannot be done except with macros); while lazy=20
> parameters are something that you can approximate quite nicely today=20
> (e.g. lambdas). Therefore, I value much more the former!=20
>
And I agree on that. (I wouldn't say lambdas are a *nice* approximation of=
=20
lazy parameters though)
=20
>
> >=20
> > Also, what about lifetime of temporaries?=20
> > As far as I understand, the lifetime of the temporary will be the same=
=20
> as with a macro/code copy-pasted.=20
> > And this is something that is simply just not true with lazy parameters=
..=20
> > The lifetime of the lazy parameters is extended as-if it were normal=20
> parameters (until the end of the caller expression).=20
> > So no surprise for the user.=20
> > (If you want more details, you can read the thread again, there are man=
y=20
> examples)=20
> > And if you want to integrate these lifetime rules within Jason's=20
> proposal, then it would become much more complex (maybe more complex than=
=20
> lazy parameters?).=20
>
> Yep, I did, and I am with Nicol here -- there is no point in=20
> integrating "lifetime rules" for the macro-like approach, that is the=20
> beauty of it.=20
>
>
I agree: there is no point in integrating special lifetime rules for a=20
macro approach.
But we want those extra lifetime rules for lazy parameters (reread the=20
thread if you want to know why).
=20
> >=20
> > A last point about multiple evaluation, this is tricky for the user on=
=20
> its own, and it's not needed most of the time.=20
>
> It is tricky in the same ways as macros, so basically already known by=20
> C programmers; i.e. it is an advantage w.r.t. introducing lazy=20
> arguments (which requires a quite more complex proposal, as you said).=20
>
Even the most experienced C programmer can be tricked by multiple=20
evaluations within macros: either because they didn't realize it was a=20
macro, or more subtle because experienced programmers write macros in such=
=20
a way that parameters are not evaluated more than once (for safety reasons)=
..
=20
>
> > So that's fine for "macro-like" approach, but for lazy parameters, I=20
> don't think that's a good idea.=20
>
> Agreed: I didn't say it was appropriate for the lazy-arguments approach.=
=20
>
> > Currently in c++ (macros are not C++), there is no expression that coul=
d=20
> lead to multiple evaluations of sub-expression. But there already are som=
e=20
> expression where sub-expressions can be discarded without being evaluated=
..=20
>
> Macros are C++, what do you mean? We try to avoid them because they=20
> are on their own phase of translation which gives them shortcomings --=20
> but that is one of the points of the proposal(s): as we have done=20
> previously many times in C++, we are trying to reduce reliance on=20
> macros).=20
>
(No, the preprocessor is not part of C++. C++ acknowledges the existence of=
=20
the preprocessor, but not really more. But that's just being picky...).
Anyway: I completely understand and agree with Jason's proposal.
Even more: I encourage it.
But I say that lazy parameters should be something else, not related to the=
=20
"macro-like" approach of Jason.
=20
>
> Now, I agree that it is worth discussing whether using this vs. a=20
> macro would be beneficial or not (i.e. whether the proposal is worth=20
> its disadvantages).=20
>
> >=20
> > Jason's proposal is interesting on its own and has many use-cases, but =
I=20
> think lazy parameters is not one of them.=20
> > That's why I think the two should be pursued independently.=20
>
> Isn't the only non-overlapping use case the ability to use declare=20
> functions which use lazy arguments without a definition? (If I am=20
> missing other significant use cases that cannot be provided by a=20
> macro-like proposal, please let me know!).=20
>
You miss the lifetime rules. Those are crucial.
And the binary size reduction (implied by the defintion not being=20
required), but that's marginal I would say.
All in all, I think you misunderstood me:
I'm all for Jason's proposal. But I think it is not adapted to implement=20
lazy parameters because of the lifetime issues (and the "forced inline"=20
policy).
And the 2 are compatible with each other: if you have one, you can have the=
=20
other later.
--=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/f422a837-1b63-4a05-94dc-81aa1f1eb54d%40isocpp.or=
g.
------=_Part_696_1782313318.1539341003807
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>Le vendredi 12 octobre 2018 12:03:57 UTC+2, Miguel Oje=
da a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Fri, =
Oct 12, 2018 at 10:29 AM <<a href=3D"javascript:" target=3D"_blank" gdf-=
obfuscated-mailto=3D"etIn4ntgAwAJ" rel=3D"nofollow" onmousedown=3D"this.hre=
f=3D'javascript:';return true;" onclick=3D"this.href=3D'javascr=
ipt:';return true;">floria...@gmail.com</a>> wrote:
<br>>
<br>>
<br>> Le vendredi 12 octobre 2018 02:28:40 UTC+2, Miguel Ojeda a =C3=A9c=
rit :
<br>>>
<br>> Jason's proposal is interesting, and I also thought it could b=
e used to implement lazy parameters, but actually, some stuff are just not =
possible with it.
<br>> The main thing I see is: the code must be visible where it is used=
..
<br>> With lazy parameters, you don't need to have the callee code v=
isible from the caller. It can be compiled within another Translation Unit.
<br>> This can seriously decrease binary size (the same way type erasure=
does).
<br>
<br>Indeed, that is what I meant when I said:
<br>
<br>>> The limitation, of
<br>>> course, is that this is a compile-time thing only (no real fun=
ctions
<br>>> -- but if you need that, you can still pass normal lambdas).
<br>
<br>In my view, macro-like expansion is something we are 100% missing from
<br>the language (i.e. cannot be done except with macros); while lazy
<br>parameters are something that you can approximate quite nicely today
<br>(e.g. lambdas). Therefore, I value much more the former!
<br></blockquote><div><br></div><div>And I agree on that. (I wouldn't s=
ay lambdas are a <i>nice</i> approximation of lazy parameters though)</div>=
<div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>>
<br>> Also, what about lifetime of temporaries?
<br>> As far as I understand, the lifetime of the temporary will be the =
same as with a macro/code copy-pasted.
<br>> And this is something that is simply just not true with lazy param=
eters.
<br>> The lifetime of the lazy parameters is extended as-if it were norm=
al parameters (until the end of the caller expression).
<br>> So no surprise for the user.
<br>> (If you want more details, you can read the thread again, there ar=
e many examples)
<br>> And if you want to integrate these lifetime rules within Jason'=
;s proposal, then it would become much more complex (maybe more complex tha=
n lazy parameters?).
<br>
<br>Yep, I did, and I am with Nicol here -- there is no point in
<br>integrating "lifetime rules" for the macro-like approach, tha=
t is the
<br>beauty of it.
<br>
<br></blockquote><div><br></div><div>I agree: there is no point in integrat=
ing special lifetime rules for a macro approach.</div><div>But we want thos=
e extra lifetime rules for lazy parameters (reread the thread if you want t=
o know why).</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;">>
<br>> A last point about multiple evaluation, this is tricky for the use=
r on its own, and it's not needed most of the time.
<br>
<br>It is tricky in the same ways as macros, so basically already known by
<br>C programmers; i.e. it is an advantage w.r.t. introducing lazy
<br>arguments (which requires a quite more complex proposal, as you said).
<br></blockquote><div><br></div><div>Even the most experienced C programmer=
can be tricked by multiple evaluations within macros: either because they =
didn't realize it was a macro, or more subtle because experienced progr=
ammers write macros in such a way that parameters are not evaluated more th=
an once (for safety reasons).<br></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;">
<br>> So that's fine for "macro-like" approach, but for la=
zy parameters, I don't think that's a good idea.
<br>
<br>Agreed: I didn't say it was appropriate for the lazy-arguments appr=
oach.
<br>
<br>> Currently in c++ (macros are not C++), there is no expression that=
could lead to multiple evaluations of sub-expression. But there already ar=
e some expression where sub-expressions can be discarded without being eval=
uated.
<br>
<br>Macros are C++, what do you mean? We try to avoid them because they
<br>are on their own phase of translation which gives them shortcomings --
<br>but that is one of the points of the proposal(s): as we have done
<br>previously many times in C++, we are trying to reduce reliance on
<br>macros).
<br></blockquote><div><br></div><div>(No, the preprocessor is not part of C=
++. C++ acknowledges the existence of the preprocessor, but not really more=
.. But that's just being picky...).</div><div>Anyway: I completely under=
stand and agree with Jason's proposal.</div><div>Even more: I encourage=
it.</div><div>But I say that lazy parameters should be something else, not=
related to the "macro-like" approach of Jason.<br></div><div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>Now, I agree that it is worth discussing whether using this vs. a
<br>macro would be beneficial or not (i.e. whether the proposal is worth
<br>its disadvantages).
<br>
<br>>
<br>> Jason's proposal is interesting on its own and has many use-ca=
ses, but I think lazy parameters is not one of them.
<br>> That's why I think the two should be pursued independently.
<br>
<br>Isn't the only non-overlapping use case the ability to use declare
<br>functions which use lazy arguments without a definition? (If I am
<br>missing other significant use cases that cannot be provided by a
<br>macro-like proposal, please let me know!).
<br></blockquote><div><br></div><div>You miss the lifetime rules. Those are=
crucial.</div><div>And the binary size reduction (implied by the defintion=
not being required), but that's marginal I would say.<br></div><div><b=
r></div><div>All in all, I think you misunderstood me:</div><div>I'm al=
l for Jason's proposal. But I think it is not adapted to implement lazy=
parameters because of the lifetime issues (and the "forced inline&quo=
t; policy).</div><div>And the 2 are compatible with each other: if you have=
one, you can have the other later.<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/f422a837-1b63-4a05-94dc-81aa1f1eb54d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/f422a837-1b63-4a05-94dc-81aa1f1eb54d=
%40isocpp.org</a>.<br />
------=_Part_696_1782313318.1539341003807--
------=_Part_695_1396704429.1539341003807--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Fri, 12 Oct 2018 13:50:44 +0300
Raw View
On Fri, 12 Oct 2018 at 13:43, <florian.csdt@gmail.com> wrote:
>> > Currently in c++ (macros are not C++), there is no expression that could lead to multiple evaluations of sub-expression. But there already are some expression where sub-expressions can be discarded without being evaluated.
>>
>> Macros are C++, what do you mean? We try to avoid them because they
>> are on their own phase of translation which gives them shortcomings --
>> but that is one of the points of the proposal(s): as we have done
>> previously many times in C++, we are trying to reduce reliance on
>> macros).
>
>
> (No, the preprocessor is not part of C++. C++ acknowledges the existence of the preprocessor, but not really more. But that's just being picky...).
That's not correct; preprocessing is a phase of translation specified
in the C++ standard. Macros are C++, and so is the preprocessor.
--
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/CAFk2RUaJDPqHUiPSoJn_gnDJoVxOn1SNGHDrhhUEksDVp40OCg%40mail.gmail.com.
.
Author: florian.csdt@gmail.com
Date: Fri, 12 Oct 2018 04:26:16 -0700 (PDT)
Raw View
------=_Part_735_230250593.1539343577068
Content-Type: multipart/alternative;
boundary="----=_Part_736_796591185.1539343577069"
------=_Part_736_796591185.1539343577069
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le vendredi 12 octobre 2018 12:50:59 UTC+2, Ville Voutilainen a =C3=A9crit =
:
>
> On Fri, 12 Oct 2018 at 13:43, <floria...@gmail.com <javascript:>> wrote:=
=20
> >> > Currently in c++ (macros are not C++), there is no expression that=
=20
> could lead to multiple evaluations of sub-expression. But there already a=
re=20
> some expression where sub-expressions can be discarded without being=20
> evaluated.=20
> >>=20
> >> Macros are C++, what do you mean? We try to avoid them because they=20
> >> are on their own phase of translation which gives them shortcomings --=
=20
> >> but that is one of the points of the proposal(s): as we have done=20
> >> previously many times in C++, we are trying to reduce reliance on=20
> >> macros).=20
> >=20
> >=20
> > (No, the preprocessor is not part of C++. C++ acknowledges the existenc=
e=20
> of the preprocessor, but not really more. But that's just being picky...)=
..=20
>
> That's not correct; preprocessing is a phase of translation specified=20
> in the C++ standard. Macros are C++, and so is the preprocessor.=20
>
I always thought it was not part of C++ standard, but you're actually right=
..
--=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/09332a59-9efa-4584-9d5e-e7930705ce7c%40isocpp.or=
g.
------=_Part_736_796591185.1539343577069
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Le vendredi 12 octobre 2018 12:50:59 UTC+2, Ville Voutilai=
nen a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Fri,=
12 Oct 2018 at 13:43, <<a href=3D"javascript:" target=3D"_blank" gdf-ob=
fuscated-mailto=3D"9h7B0QxjAwAJ" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'javascript:';return true;" onclick=3D"this.href=3D'javascri=
pt:';return true;">floria...@gmail.com</a>> wrote:
<br>>> > Currently in c++ (macros are not C++), there is no expres=
sion that could lead to multiple evaluations of sub-expression. But there a=
lready are some expression where sub-expressions can be discarded without b=
eing evaluated.
<br>>>
<br>>> Macros are C++, what do you mean? We try to avoid them because=
they
<br>>> are on their own phase of translation which gives them shortco=
mings --
<br>>> but that is one of the points of the proposal(s): as we have d=
one
<br>>> previously many times in C++, we are trying to reduce reliance=
on
<br>>> macros).
<br>>
<br>>
<br>> (No, the preprocessor is not part of C++. C++ acknowledges the exi=
stence of the preprocessor, but not really more. But that's just being =
picky...).
<br>
<br>That's not correct; preprocessing is a phase of translation specifi=
ed
<br>in the C++ standard. Macros are C++, and so is the preprocessor.
<br></blockquote><div><br></div><div>I always thought it was not part of C+=
+ standard, but you're actually right.</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/09332a59-9efa-4584-9d5e-e7930705ce7c%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/09332a59-9efa-4584-9d5e-e7930705ce7c=
%40isocpp.org</a>.<br />
------=_Part_736_796591185.1539343577069--
------=_Part_735_230250593.1539343577068--
.
Author: Corentin <corentin.jabot@gmail.com>
Date: Fri, 12 Oct 2018 13:52:02 +0200
Raw View
--000000000000e662a4057806b708
Content-Type: text/plain; charset="UTF-8"
I do not see the value of a language feature for lazy evaluation.
Any solution would ultimately look a lot like a lambda, maybe with a
shorter syntax but it would essentially look and behave the same, so there
would be a little gain.
A more generic solution for that particular use case would be to simplify
lambda everywhere (see for example
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0573r2.html )
However, I do think that superseding all or part of the pre-processor
macros (token soup injection), by a language level feature is something
that would be incredibly powerful,
And as such, Jason proposal is a much better solution overall.
But I think it's important to think about what we want.
- That language feature results in visible AST-nodes
- Scoped names - that seems evident but it's one of the issues with
C-macro
- The definition should be checked
- The parameters should be checked - All expressions have the nice
property of having a type, so parametric expression should be able to
constrain on type/concepts
I think it's important to keep in mind that what Jason proposes and similar
proposals never call anything or return anything, regarding of whether we
end up on a solution building on top of code injection/expression
reflection or not, the result is basically the same: shifting ast-nodes
around so name lookup etc is a non-issue - but you can never escape the
scope.
(Having the injectee/parametric expression being able to see in each other
scope would probably be of little value and a pretty big nightmare)
A code-injection based system can be extended to be able to inject
statements in the current scope.
So it would be possible to have sanitary language-level macros that have
expressions
as parameters and expand to one or several statements.
Herb and Andrew also demonstrated ways to construct identifiers and
typename at compile time and all of these pieces can fit nicely together.
However, that does not, unfortunately, replaces all macro use cases.
Namely, I have no idea how to inject partial statements, which is something
a lot of test frameworks do, for example
There is no one unique replacement for macros but instead a multitude of
solutions.
And I don't think it would be a bad thing to have a gradient of solutions
(function, constexpr functions, constexpr parameters, parametric
expressions, something else in the future) as long as the whole is cohesive.
My 2 cents
On Fri, 12 Oct 2018 at 12:50 Ville Voutilainen <ville.voutilainen@gmail.com>
wrote:
> On Fri, 12 Oct 2018 at 13:43, <florian.csdt@gmail.com> wrote:
> >> > Currently in c++ (macros are not C++), there is no expression that
> could lead to multiple evaluations of sub-expression. But there already are
> some expression where sub-expressions can be discarded without being
> evaluated.
> >>
> >> Macros are C++, what do you mean? We try to avoid them because they
> >> are on their own phase of translation which gives them shortcomings --
> >> but that is one of the points of the proposal(s): as we have done
> >> previously many times in C++, we are trying to reduce reliance on
> >> macros).
> >
> >
> > (No, the preprocessor is not part of C++. C++ acknowledges the existence
> of the preprocessor, but not really more. But that's just being picky...).
>
> That's not correct; preprocessing is a phase of translation specified
> in the C++ standard. Macros are C++, and so is the preprocessor.
>
> --
> 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/CAFk2RUaJDPqHUiPSoJn_gnDJoVxOn1SNGHDrhhUEksDVp40OCg%40mail.gmail.com
> .
>
--
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/CA%2BOm%2BSjp2Z0rNXt6NaC5OWPC_X6WYvhSbee5YqinNtvu2AnTeQ%40mail.gmail.com.
--000000000000e662a4057806b708
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I do not see the value of a language feature for lazy eval=
uation.=C2=A0<div>Any solution would ultimately look a lot like a lambda, m=
aybe with a shorter syntax but it would essentially look and behave the sam=
e, so there would be a little gain.</div><div>A more generic solution for t=
hat particular use case would be to simplify lambda everywhere (see for exa=
mple=C2=A0<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/201=
7/p0573r2.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p05=
73r2.html</a>=C2=A0)</div><div><br></div><div><br></div><div>However, I do =
think that=C2=A0superseding all or part of the pre-processor macros (token =
soup injection), by a language level feature is something=C2=A0 that would =
be incredibly powerful,</div><div>And as such, Jason proposal is a much bet=
ter solution overall.</div><div><br></div><div>But I think it's importa=
nt to think about what we want.</div><div><ul><li><font size=3D"2">That lan=
guage feature results in visible AST-nodes</font></li><li><font size=3D"2">=
Scoped names - that seems evident but it's one of the issues with C-mac=
ro</font></li><li><font size=3D"2">The definition should be checked</font><=
/li><li><font size=3D"2">The parameters should=C2=A0be checked - All expres=
sions have the nice property of having a type, so parametric expression sho=
uld be able to constrain on type/concepts</font></li></ul><div><font size=
=3D"2">I think it's important to keep in mind that what Jason=C2=A0prop=
oses and similar proposals never call anything or return anything, regardin=
g of whether we end up on a solution building on top of=C2=A0 code injectio=
n/expression reflection or not, the result is basically the same: shifting =
ast-nodes around so name=C2=A0lookup etc is a non-issue - but you can never=
escape the scope.</font></div></div><div><font size=3D"2"><br></font></div=
><div><font size=3D"2">(Having the injectee/parametric expression being abl=
e to see in each other scope would probably be of little value and a pretty=
big nightmare)=C2=A0</font></div><div><font size=3D"2"><br></font></div><d=
iv><span style=3D"font-size:small">A code-injection based system can be ext=
ended to be able to inject statements in the current scope.</span></div><di=
v><span style=3D"font-size:small">So it would be possible to have sanitary =
language-level macros that have expressions=C2=A0</span><br></div><div><fon=
t size=3D"2">as parameters and expand to one or several statements.</font><=
/div><div><font size=3D"2">Herb and Andrew also demonstrated ways to constr=
uct=C2=A0identifiers and typename at compile time and all of these pieces c=
an fit nicely together.</font></div><div><br></div><div><font size=3D"2">Ho=
wever, that does not, unfortunately, replaces all macro use cases.</font></=
div><div><font size=3D"2">Namely, I have no idea how to inject partial stat=
ements, which is something a lot of test frameworks do, for example</font><=
/div><div><font size=3D"2"><br></font></div><div><font size=3D"2">There is =
no one unique replacement for macros but instead a multitude of solutions.<=
/font></div><div><font size=3D"2">And I don't think it would be a bad t=
hing to have a gradient of solutions (function, constexpr functions, conste=
xpr parameters, parametric expressions, something else in the future) as lo=
ng as the whole is cohesive.</font></div><div><font size=3D"2"><br></font><=
/div><div><br></div><div>My 2 cents<br></div><div><br></div></div><br><div =
class=3D"gmail_quote"><div dir=3D"ltr">On Fri, 12 Oct 2018 at 12:50 Ville V=
outilainen <<a href=3D"mailto:ville.voutilainen@gmail.com">ville.voutila=
inen@gmail.com</a>> wrote:<br></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Fr=
i, 12 Oct 2018 at 13:43, <<a href=3D"mailto:florian.csdt@gmail.com" targ=
et=3D"_blank">florian.csdt@gmail.com</a>> wrote:<br>
>> > Currently in c++ (macros are not C++), there is no expression=
that could lead to multiple evaluations of sub-expression. But there alrea=
dy are some expression where sub-expressions can be discarded without being=
evaluated.<br>
>><br>
>> Macros are C++, what do you mean? We try to avoid them because the=
y<br>
>> are on their own phase of translation which gives them shortcoming=
s --<br>
>> but that is one of the points of the proposal(s): as we have done<=
br>
>> previously many times in C++, we are trying to reduce reliance on<=
br>
>> macros).<br>
><br>
><br>
> (No, the preprocessor is not part of C++. C++ acknowledges the existen=
ce of the preprocessor, but not really more. But that's just being pick=
y...).<br>
<br>
That's not correct; preprocessing is a phase of translation specified<b=
r>
in the C++ standard. Macros are C++, and so is the preprocessor.<br>
<br>
-- <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%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">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/CAFk2RUaJDPqHUiPSoJn_gnDJoVxOn1SNGHDr=
hhUEksDVp40OCg%40mail.gmail.com" rel=3D"noreferrer" target=3D"_blank">https=
://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUaJDPqHUiPSoJ=
n_gnDJoVxOn1SNGHDrhhUEksDVp40OCg%40mail.gmail.com</a>.<br>
</blockquote></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/CA%2BOm%2BSjp2Z0rNXt6NaC5OWPC_X6WYvhS=
bee5YqinNtvu2AnTeQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BOm%2BSjp=
2Z0rNXt6NaC5OWPC_X6WYvhSbee5YqinNtvu2AnTeQ%40mail.gmail.com</a>.<br />
--000000000000e662a4057806b708--
.
Author: florian.csdt@gmail.com
Date: Fri, 12 Oct 2018 05:13:25 -0700 (PDT)
Raw View
------=_Part_713_1866995899.1539346405232
Content-Type: multipart/alternative;
boundary="----=_Part_714_584115058.1539346405233"
------=_Part_714_584115058.1539346405233
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le vendredi 12 octobre 2018 13:52:16 UTC+2, Corentin a =C3=A9crit :
>
> I do not see the value of a language feature for lazy evaluation.=20
> Any solution would ultimately look a lot like a lambda, maybe with a=20
> shorter syntax but it would essentially look and behave the same, so ther=
e=20
> would be a little gain.
> A more generic solution for that particular use case would be to simplify=
=20
> lambda everywhere (see for example=20
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0573r2.html )
>
This point has already been debated many times on this thread. And the=20
point is: we need lazy evaluation, meaning a way for a function to take=20
something "callable" without any syntax overhead on the call site.
P0573r2 is not about that. But it remains interesting in a world where lazy=
=20
parameters exist.
The two are orthogonal and independant.
=20
>
>
> However, I do think that superseding all or part of the pre-processor=20
> macros (token soup injection), by a language level feature is something =
=20
> that would be incredibly powerful,
> And as such, Jason proposal is a much better solution overall.
>
Yes, I also do want to prioritize Jason's proposal (or any well thought=20
alternative) over lazy parameters.
But Jason's proposal is not good enough for proper lazy parameters. So I=20
also want lazy parameters *in addition*.
And again, those proposals are also orthogonal and independant.
=20
>
> But I think it's important to think about what we want.
>
> - That language feature results in visible AST-nodes
> - Scoped names - that seems evident but it's one of the issues with=20
> C-macro
> - The definition should be checked
> - The parameters should be checked - All expressions have the nice=20
> property of having a type, so parametric expression should be able to=
=20
> constrain on type/concepts
>
> I think it's important to keep in mind that what Jason proposes and=20
> similar proposals never call anything or return anything, regarding of=20
> whether we end up on a solution building on top of code=20
> injection/expression reflection or not, the result is basically the same:=
=20
> shifting ast-nodes around so name lookup etc is a non-issue - but you can=
=20
> never escape the scope.
>
And this scope problem is why "macro-like" approach is not enough for=20
proper lazy parameters: we want temporary objects from the lazy expression=
=20
to outlive the callee.
=20
>
> (Having the injectee/parametric expression being able to see in each othe=
r=20
> scope would probably be of little value and a pretty big nightmare)=20
>
> A code-injection based system can be extended to be able to inject=20
> statements in the current scope.
> So it would be possible to have sanitary language-level macros that have=
=20
> expressions=20
> as parameters and expand to one or several statements.
> Herb and Andrew also demonstrated ways to construct identifiers and=20
> typename at compile time and all of these pieces can fit nicely together.
>
> However, that does not, unfortunately, replaces all macro use cases.
> Namely, I have no idea how to inject partial statements, which is=20
> something a lot of test frameworks do, for example
>
> There is no one unique replacement for macros but instead a multitude of=
=20
> solutions.
> And I don't think it would be a bad thing to have a gradient of solutions=
=20
> (function, constexpr functions, constexpr parameters, parametric=20
> expressions, something else in the future) as long as the whole is cohesi=
ve.
>
>
You've just said it: there is no ONE solution. And lazy parameter cannot be=
=20
solved properly by parametric expressions. That's why we need something=20
else for that.
But we don't need to wait for lazy parameters in order to standardize=20
parametric expressions. Those are orthogonal and can be standardized=20
independently.
--=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/58d6ae1e-3734-452f-b490-231b1a921c10%40isocpp.or=
g.
------=_Part_714_584115058.1539346405233
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Le vendredi 12 octobre 2018 13:52:16 UTC+2, Corentin a =C3=
=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
>I do not see the value of a language feature for lazy evaluation.=C2=A0<di=
v>Any solution would ultimately look a lot like a lambda, maybe with a shor=
ter syntax but it would essentially look and behave the same, so there woul=
d be a little gain.</div><div>A more generic solution for that particular u=
se case would be to simplify lambda everywhere (see for example=C2=A0<a hre=
f=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0573r2.html" =
target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://w=
ww.google.com/url?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2=
Fdocs%2Fpapers%2F2017%2Fp0573r2.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQj=
CNGvF-zq2Myh8mGZg9Uh8p12wVGlhg';return true;" onclick=3D"this.href=3D&#=
39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc=
22%2Fwg21%2Fdocs%2Fpapers%2F2017%2Fp0573r2.html\x26sa\x3dD\x26sntz\x3d1\x26=
usg\x3dAFQjCNGvF-zq2Myh8mGZg9Uh8p12wVGlhg';return true;">http://www.ope=
n-std.<wbr>org/jtc1/sc22/wg21/docs/<wbr>papers/2017/p0573r2.html</a>=C2=A0)=
</div></div></blockquote><div><br></div><div>This point has already been de=
bated many times on this thread. And the point is: we need lazy evaluation,=
meaning a way for a function to take something "callable" withou=
t any syntax overhead on the call site.</div><div>P0573r2 is not about that=
.. But it remains interesting in a world where lazy parameters exist.</div><=
div>The two are orthogonal and independant.<br></div><div>=C2=A0</div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><di=
v><br></div><div>However, I do think that=C2=A0superseding all or part of t=
he pre-processor macros (token soup injection), by a language level feature=
is something=C2=A0 that would be incredibly powerful,</div><div>And as suc=
h, Jason proposal is a much better solution overall.</div></div></blockquot=
e><div><br></div><div>Yes, I also do want to prioritize Jason's proposa=
l (or any well thought alternative) over lazy parameters.</div><div>But Jas=
on's proposal is not good enough for proper lazy parameters. So I also =
want lazy parameters <i>in addition</i>.</div><div>And again, those proposa=
ls are also orthogonal and independant.<br></div><div>=C2=A0</div><blockquo=
te 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><br></div><div>Bu=
t I think it's important to think about what we want.</div><div><ul><li=
><font size=3D"2">That language feature results in visible AST-nodes</font>=
</li><li><font size=3D"2">Scoped names - that seems evident but it's on=
e of the issues with C-macro</font></li><li><font size=3D"2">The definition=
should be checked</font></li><li><font size=3D"2">The parameters should=C2=
=A0be checked - All expressions have the nice property of having a type, so=
parametric expression should be able to constrain on type/concepts</font><=
/li></ul><div><font size=3D"2">I think it's important to keep in mind t=
hat what Jason=C2=A0proposes and similar proposals never call anything or r=
eturn anything, regarding of whether we end up on a solution building on to=
p of=C2=A0 code injection/expression reflection or not, the result is basic=
ally the same: shifting ast-nodes around so name=C2=A0lookup etc is a non-i=
ssue - but you can never escape the scope.</font></div></div></div></blockq=
uote><div><br></div><div>And this scope problem is why "macro-like&quo=
t; approach is not enough for proper lazy parameters: we want temporary obj=
ects from the lazy expression to outlive the callee.<br></div><div>=C2=A0</=
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><fon=
t size=3D"2"><br></font></div><div><font size=3D"2">(Having the injectee/pa=
rametric expression being able to see in each other scope would probably be=
of little value and a pretty big nightmare)=C2=A0</font></div><div><font s=
ize=3D"2"><br></font></div><div><span style=3D"font-size:small">A code-inje=
ction based system can be extended to be able to inject statements in the c=
urrent scope.</span></div><div><span style=3D"font-size:small">So it would =
be possible to have sanitary language-level macros that have expressions=C2=
=A0</span><br></div><div><font size=3D"2">as parameters and expand to one o=
r several statements.</font></div><div><font size=3D"2">Herb and Andrew als=
o demonstrated ways to construct=C2=A0identifiers and typename at compile t=
ime and all of these pieces can fit nicely together.</font></div><div><br><=
/div><div><font size=3D"2">However, that does not, unfortunately, replaces =
all macro use cases.</font></div><div><font size=3D"2">Namely, I have no id=
ea how to inject partial statements, which is something a lot of test frame=
works do, for example</font></div><div><font size=3D"2"><br></font></div><d=
iv><font size=3D"2">There is no one unique replacement for macros but inste=
ad a multitude of solutions.</font></div><div><font size=3D"2">And I don=
9;t think it would be a bad thing to have a gradient of solutions (function=
, constexpr functions, constexpr parameters, parametric expressions, someth=
ing else in the future) as long as the whole is cohesive.</font></div><div>=
<font size=3D"2"><br></font></div></div></blockquote><div><br></div><div>Yo=
u've just said it: there is no ONE solution. And lazy parameter cannot =
be solved properly by parametric expressions. That's why we need someth=
ing else for that.</div><div>But we don't need to wait for lazy paramet=
ers in order to standardize parametric expressions. Those are orthogonal an=
d can be standardized independently.<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/58d6ae1e-3734-452f-b490-231b1a921c10%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/58d6ae1e-3734-452f-b490-231b1a921c10=
%40isocpp.org</a>.<br />
------=_Part_714_584115058.1539346405233--
------=_Part_713_1866995899.1539346405232--
.
Author: Corentin <corentin.jabot@gmail.com>
Date: Fri, 12 Oct 2018 14:46:56 +0200
Raw View
--00000000000039b4a60578077c64
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
I'm not sure no marking at the call site would be a good idea.
You most likely want some syntax notifying "This thing that you think is
evaluating may in fact, not be evaluated"
There is a value in being explicit, and not giving the same syntax to
multiple constructs
function_call( [x, y] =3D> x + y);
Similarly, I think we probably want some syntax for jason's proposal to
distinguish "this is evaluating the parameters and invoking a function"
from "this expands to some more code"
Rust has the `!` syntax for this reason (printn!("I am a macro"))
On Fri, 12 Oct 2018 at 14:13 <florian.csdt@gmail.com> wrote:
> Le vendredi 12 octobre 2018 13:52:16 UTC+2, Corentin a =C3=A9crit :
>>
>> I do not see the value of a language feature for lazy evaluation.
>> Any solution would ultimately look a lot like a lambda, maybe with a
>> shorter syntax but it would essentially look and behave the same, so the=
re
>> would be a little gain.
>> A more generic solution for that particular use case would be to simplif=
y
>> lambda everywhere (see for example
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0573r2.html )
>>
>
> This point has already been debated many times on this thread. And the
> point is: we need lazy evaluation, meaning a way for a function to take
> something "callable" without any syntax overhead on the call site.
> P0573r2 is not about that. But it remains interesting in a world where
> lazy parameters exist.
> The two are orthogonal and independant.
>
>
>>
>>
>> However, I do think that superseding all or part of the pre-processor
>> macros (token soup injection), by a language level feature is something
>> that would be incredibly powerful,
>> And as such, Jason proposal is a much better solution overall.
>>
>
> Yes, I also do want to prioritize Jason's proposal (or any well thought
> alternative) over lazy parameters.
> But Jason's proposal is not good enough for proper lazy parameters. So I
> also want lazy parameters *in addition*.
> And again, those proposals are also orthogonal and independant.
>
>
>>
>> But I think it's important to think about what we want.
>>
>> - That language feature results in visible AST-nodes
>> - Scoped names - that seems evident but it's one of the issues with
>> C-macro
>> - The definition should be checked
>> - The parameters should be checked - All expressions have the nice
>> property of having a type, so parametric expression should be able to
>> constrain on type/concepts
>>
>> I think it's important to keep in mind that what Jason proposes and
>> similar proposals never call anything or return anything, regarding of
>> whether we end up on a solution building on top of code
>> injection/expression reflection or not, the result is basically the same=
:
>> shifting ast-nodes around so name lookup etc is a non-issue - but you ca=
n
>> never escape the scope.
>>
>
> And this scope problem is why "macro-like" approach is not enough for
> proper lazy parameters: we want temporary objects from the lazy expressio=
n
> to outlive the callee.
>
>
>>
>> (Having the injectee/parametric expression being able to see in each
>> other scope would probably be of little value and a pretty big nightmare=
)
>>
>> A code-injection based system can be extended to be able to inject
>> statements in the current scope.
>> So it would be possible to have sanitary language-level macros that have
>> expressions
>> as parameters and expand to one or several statements.
>> Herb and Andrew also demonstrated ways to construct identifiers and
>> typename at compile time and all of these pieces can fit nicely together=
..
>>
>> However, that does not, unfortunately, replaces all macro use cases.
>> Namely, I have no idea how to inject partial statements, which is
>> something a lot of test frameworks do, for example
>>
>> There is no one unique replacement for macros but instead a multitude of
>> solutions.
>> And I don't think it would be a bad thing to have a gradient of solution=
s
>> (function, constexpr functions, constexpr parameters, parametric
>> expressions, something else in the future) as long as the whole is cohes=
ive.
>>
>>
> You've just said it: there is no ONE solution. And lazy parameter cannot
> be solved properly by parametric expressions. That's why we need somethin=
g
> else for that.
> But we don't need to wait for lazy parameters in order to standardize
> parametric expressions. Those are orthogonal and can be standardized
> independently.
>
> --
> 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/58d6ae1e-373=
4-452f-b490-231b1a921c10%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/58d6ae1e-37=
34-452f-b490-231b1a921c10%40isocpp.org?utm_medium=3Demail&utm_source=3Dfoot=
er>
> .
>
--=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/CA%2BOm%2BSix3LA9-6W%2Bg2gmXYzS26erpLNsp9VeH9p2q=
bWm%3DdZaTQ%40mail.gmail.com.
--00000000000039b4a60578077c64
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I'm not sure no marking at the call site would be a go=
od idea.<div>You most likely want some syntax notifying "This thing th=
at you think is evaluating may in fact, not be evaluated"</div><div>Th=
ere is a value in being explicit, and not giving the same syntax to multipl=
e constructs=C2=A0</div><div><br></div><div>function_call( [x, y] =3D>=
=C2=A0 x=C2=A0+ y);=C2=A0 =C2=A0<br></div><div><br></div><div>Similarly, I =
think we probably want some syntax for jason's proposal=C2=A0 to distin=
guish "this is evaluating the parameters and invoking a function"=
from "this expands to some more code"</div><div>Rust has the `!`=
syntax for this reason (printn!("I am a macro"))</div><div><br><=
/div></div><br><div class=3D"gmail_quote"><div dir=3D"ltr">On Fri, 12 Oct 2=
018 at 14:13 <<a href=3D"mailto:florian.csdt@gmail.com">florian.csdt@gma=
il.com</a>> wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"m=
argin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"l=
tr">Le vendredi 12 octobre 2018 13:52:16 UTC+2, Corentin a =C3=A9crit=C2=A0=
:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">I do not see the =
value of a language feature for lazy evaluation.=C2=A0<div>Any solution wou=
ld ultimately look a lot like a lambda, maybe with a shorter syntax but it =
would essentially look and behave the same, so there would be a little gain=
..</div><div>A more generic solution for that particular use case would be t=
o simplify lambda everywhere (see for example=C2=A0<a href=3D"http://www.op=
en-std.org/jtc1/sc22/wg21/docs/papers/2017/p0573r2.html" rel=3D"nofollow" t=
arget=3D"_blank">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0=
573r2.html</a>=C2=A0)</div></div></blockquote><div><br></div></div><div dir=
=3D"ltr"><div>This point has already been debated many times on this thread=
.. And the point is: we need lazy evaluation, meaning a way for a function t=
o take something "callable" without any syntax overhead on the ca=
ll site.</div><div>P0573r2 is not about that. But it remains interesting in=
a world where lazy parameters exist.</div><div>The two are orthogonal and =
independant.<br></div></div><div dir=3D"ltr"><div>=C2=A0</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><div><br></div><div><br></div><=
div>However, I do think that=C2=A0superseding all or part of the pre-proces=
sor macros (token soup injection), by a language level feature is something=
=C2=A0 that would be incredibly powerful,</div><div>And as such, Jason prop=
osal is a much better solution overall.</div></div></blockquote><div><br></=
div></div><div dir=3D"ltr"><div>Yes, I also do want to prioritize Jason'=
;s proposal (or any well thought alternative) over lazy parameters.</div><d=
iv>But Jason's proposal is not good enough for proper lazy parameters. =
So I also want lazy parameters <i>in addition</i>.</div><div>And again, tho=
se proposals are also orthogonal and independant.<br></div></div><div dir=
=3D"ltr"><div>=C2=A0</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><br></div><div>But I think it's important to think about =
what we want.</div><div><ul><li><font size=3D"2">That language feature resu=
lts in visible AST-nodes</font></li><li><font size=3D"2">Scoped names - tha=
t seems evident but it's one of the issues with C-macro</font></li><li>=
<font size=3D"2">The definition should be checked</font></li><li><font size=
=3D"2">The parameters should=C2=A0be checked - All expressions have the nic=
e property of having a type, so parametric expression should be able to con=
strain on type/concepts</font></li></ul><div><font size=3D"2">I think it=
9;s important to keep in mind that what Jason=C2=A0proposes and similar pro=
posals never call anything or return anything, regarding of whether we end =
up on a solution building on top of=C2=A0 code injection/expression reflect=
ion or not, the result is basically the same: shifting ast-nodes around so =
name=C2=A0lookup etc is a non-issue - but you can never escape the scope.</=
font></div></div></div></blockquote><div><br></div></div><div dir=3D"ltr"><=
div>And this scope problem is why "macro-like" approach is not en=
ough for proper lazy parameters: we want temporary objects from the lazy ex=
pression to outlive the callee.<br></div></div><div dir=3D"ltr"><div>=C2=A0=
</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 s=
ize=3D"2"><br></font></div><div><font size=3D"2">(Having the injectee/param=
etric expression being able to see in each other scope would probably be of=
little value and a pretty big nightmare)=C2=A0</font></div><div><font size=
=3D"2"><br></font></div><div><span style=3D"font-size:small">A code-injecti=
on based system can be extended to be able to inject statements in the curr=
ent scope.</span></div><div><span style=3D"font-size:small">So it would be =
possible to have sanitary language-level macros that have expressions=C2=A0=
</span><br></div><div><font size=3D"2">as parameters and expand to one or s=
everal statements.</font></div><div><font size=3D"2">Herb and Andrew also d=
emonstrated ways to construct=C2=A0identifiers and typename at compile time=
and all of these pieces can fit nicely together.</font></div><div><br></di=
v><div><font size=3D"2">However, that does not, unfortunately, replaces all=
macro use cases.</font></div><div><font size=3D"2">Namely, I have no idea =
how to inject partial statements, which is something a lot of test framewor=
ks do, for example</font></div><div><font size=3D"2"><br></font></div><div>=
<font size=3D"2">There is no one unique replacement for macros but instead =
a multitude of solutions.</font></div><div><font size=3D"2">And I don't=
think it would be a bad thing to have a gradient of solutions (function, c=
onstexpr functions, constexpr parameters, parametric expressions, something=
else in the future) as long as the whole is cohesive.</font></div><div><fo=
nt size=3D"2"><br></font></div></div></blockquote><div><br></div></div><div=
dir=3D"ltr"><div>You've just said it: there is no ONE solution. And la=
zy parameter cannot be solved properly by parametric expressions. That'=
s why we need something else for that.</div><div>But we don't need to w=
ait for lazy parameters in order to standardize parametric expressions. Tho=
se are orthogonal and can be standardized independently.<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" target=3D"_=
blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">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/58d6ae1e-3734-452f-b490-231b1a921c10%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank">=
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/58d6ae1e-3734-=
452f-b490-231b1a921c10%40isocpp.org</a>.<br>
</blockquote></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/CA%2BOm%2BSix3LA9-6W%2Bg2gmXYzS26erpL=
Nsp9VeH9p2qbWm%3DdZaTQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoo=
ter">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BOm%2=
BSix3LA9-6W%2Bg2gmXYzS26erpLNsp9VeH9p2qbWm%3DdZaTQ%40mail.gmail.com</a>.<br=
/>
--00000000000039b4a60578077c64--
.
Author: florian.csdt@gmail.com
Date: Fri, 12 Oct 2018 05:55:45 -0700 (PDT)
Raw View
------=_Part_682_1484371099.1539348945378
Content-Type: multipart/alternative;
boundary="----=_Part_683_942548622.1539348945378"
------=_Part_683_942548622.1539348945378
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le vendredi 12 octobre 2018 14:47:10 UTC+2, Corentin a =C3=A9crit :
>
> I'm not sure no marking at the call site would be a good idea.
> You most likely want some syntax notifying "This thing that you think is=
=20
> evaluating may in fact, not be evaluated"
> There is a value in being explicit, and not giving the same syntax to=20
> multiple constructs=20
>
> function_call( [x, y] =3D> x + y); =20
>
This has also already been discussed here.
One reason we want no syntax overhead at call site is to have=20
shortcircuiting || && operators on custom types (and also ?: )
=20
>
> Similarly, I think we probably want some syntax for jason's proposal to=
=20
> distinguish "this is evaluating the parameters and invoking a function"=
=20
> from "this expands to some more code"
> Rust has the `!` syntax for this reason (printn!("I am a macro"))
>
>
That is debatable...=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 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/f828bf31-1842-4651-9f92-9565f1166024%40isocpp.or=
g.
------=_Part_683_942548622.1539348945378
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>Le vendredi 12 octobre 2018 14:47:10 UTC+2, Corentin a=
=C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"=
ltr">I'm not sure no marking at the call site would be a good idea.<div=
>You most likely want some syntax notifying "This thing that you think=
is evaluating may in fact, not be evaluated"</div><div>There is a val=
ue in being explicit, and not giving the same syntax to multiple constructs=
=C2=A0</div><div><br></div><div>function_call( [x, y] =3D>=C2=A0 x=C2=A0=
+ y);=C2=A0 =C2=A0<br></div></div></blockquote><div><br></div><div>This has=
also already been discussed here.</div><div>One reason we want no syntax o=
verhead at call site is to have shortcircuiting || && operators on =
custom types (and also ?: )<br></div><div>=C2=A0</div><blockquote class=3D"=
gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc so=
lid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><div><br></div><div>Sim=
ilarly, I think we probably want some syntax for jason's proposal=C2=A0=
to distinguish "this is evaluating the parameters and invoking a func=
tion" from "this expands to some more code"</div><div>Rust h=
as the `!` syntax for this reason (printn!("I am a macro"))</div>=
<br></div></blockquote><div><br></div><div>That is debatable... <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/f828bf31-1842-4651-9f92-9565f1166024%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/f828bf31-1842-4651-9f92-9565f1166024=
%40isocpp.org</a>.<br />
------=_Part_683_942548622.1539348945378--
------=_Part_682_1484371099.1539348945378--
.
Author: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
Date: Fri, 12 Oct 2018 17:51:15 +0200
Raw View
On Fri, Oct 12, 2018 at 12:43 PM <florian.csdt@gmail.com> wrote:
>
> Le vendredi 12 octobre 2018 12:03:57 UTC+2, Miguel Ojeda a =C3=A9crit :
>>
>> On Fri, Oct 12, 2018 at 10:29 AM <floria...@gmail.com> wrote:
>>
>> It is tricky in the same ways as macros, so basically already known by
>> C programmers; i.e. it is an advantage w.r.t. introducing lazy
>> arguments (which requires a quite more complex proposal, as you said).
>
>
> Even the most experienced C programmer can be tricked by multiple evaluat=
ions within macros: either because they didn't realize it was a macro, or m=
ore subtle because experienced programmers write macros in such a way that =
parameters are not evaluated more than once (for safety reasons).
>
Anyone can make mistakes with any feature, that is not the really
point... Macros are already understood by all C++ (and C) programmers.
They are not *that* tricky, compared to other C++ features.
>> Macros are C++, what do you mean? We try to avoid them because they
>> are on their own phase of translation which gives them shortcomings --
>> but that is one of the points of the proposal(s): as we have done
>> previously many times in C++, we are trying to reduce reliance on
>> macros).
>
>
> (No, the preprocessor is not part of C++. C++ acknowledges the existence =
of the preprocessor, but not really more. But that's just being picky...).
No. Please refer to [cpp] or [lex] in the standard.
>> Isn't the only non-overlapping use case the ability to use declare
>> functions which use lazy arguments without a definition? (If I am
>> missing other significant use cases that cannot be provided by a
>> macro-like proposal, please let me know!).
>
>
> You miss the lifetime rules. Those are crucial.
I don't see what the lifetime rules buys you that the macro-like
approach doesn't. Please provide an example.
Cheers,
Miguel
--=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/CANiq72nnOU5ihx%3DtSZ57XizxzN-q_up-MxvXQtN40DCuc=
-4qpA%40mail.gmail.com.
.
Author: Corentin <corentin.jabot@gmail.com>
Date: Fri, 12 Oct 2018 18:41:25 +0200
Raw View
--000000000000d2a47505780ac205
Content-Type: text/plain; charset="UTF-8"
the thing we must be careful with is to keep in mind that some usages for
macros are _not_ worth replacing
On Fri, 12 Oct 2018 at 17:11 Matthew Woehlke <mwoehlke.floss@gmail.com>
wrote:
> On 12/10/2018 07.52, Corentin wrote:
> > However, that does not, unfortunately, replaces all macro use cases.
> > Namely, I have no idea how to inject partial statements, which is
> something
> > a lot of test frameworks do, for example
>
> Indeed, and I was just thinking about this very same issue.
>
> Other things for which we don't currently have a replacement:
>
> #define call(x, ...) log(#x, x, __VA_ARGS__) // ?
>
This could be possible, and I think it's important indeed.
But if reflection on type give you the type's name, it seems reasonable to
expect
that reflecting on expressions could give you its string representation.
hopefully, as in the source code.
> #define signal protected
>
Ok, this does not sounds like a legitimate use case ( sorry Qt )
This is needed for moc, but the ultimate goal is is a moc-less Qt.
And indeed this causes actual bug in software if for example you use Qt
along boost::signal
A better solution would be [[qt::signal]] void my signal.
I think means to defining dialects should be specifically a non-goal in
this problem space
> #define with(x) if(x; true)
>
Yes, this is the big problem.
I'm trying to determine whether is worth caring about it to begin with
because that falls into
the "defining dialect" category.
But as you point out, it's kinda required by test frameworks.
But if we manage to only need macros in test code, it would already be a
big win !
>
> I'm not *entirely* certain if it's possible with reflection to implement
> the first as a non-macro. Even if *that* case is possible, I'd have to
> question if all possible uses of stringifying can be replaced,
> especially those that stringify entire expressions (again, something
> often found in test frameworks).
>
> For the second, I doubt any replacement is forthcoming.
>
> For the third, in particular, I'm thinking of macros that expand to a
> statement which opens a scope, i.e. `if`, `while`, `for`, ... where the
> macro is followed by a statement or an open brace which is associated
> with the macro. I suppose we could define a way to make "new control
> statements" that would always have this property (in fact, that might
> even be a very interesting feature, especially if it incorporates
> mechanisms to execute code at the end of the scope and possibly to
> decide if the scope should be repeated like a loop). However AFAIK the
> current "parametric expressions" proposal would not cover these cases.
>
> --
> Matthew
>
> --
> 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/c4905596-60a8-cbc1-1e03-2cb811a3543c%40gmail.com
> .
>
--
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/CA%2BOm%2BSg8Md0PkOa0HL_0%3D21fkjLQErZqRw9sbAFnqyuQPhVuBQ%40mail.gmail.com.
--000000000000d2a47505780ac205
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">the thing we must be careful with is to keep in mind that =
some usages for macros are _not_ worth replacing<br><br><div class=3D"gmail=
_quote"><div dir=3D"ltr">On Fri, 12 Oct 2018 at 17:11 Matthew Woehlke <<=
a href=3D"mailto:mwoehlke.floss@gmail.com">mwoehlke.floss@gmail.com</a>>=
wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8=
ex;border-left:1px #ccc solid;padding-left:1ex">On 12/10/2018 07.52, Corent=
in wrote:<br>
> However, that does not, unfortunately, replaces all macro use cases.<b=
r>
> Namely, I have no idea how to inject partial statements, which is some=
thing<br>
> a lot of test frameworks do, for example<br>
<br>
Indeed, and I was just thinking about this very same issue.<br>
<br>
Other things for which we don't currently have a replacement:<br>
<br>
=C2=A0 #define call(x, ...) log(#x, x, __VA_ARGS__) // ?<br></blockquote><d=
iv><br></div><div>This could be possible, and I think it's important in=
deed.</div><div>But if reflection on type give you the type's name, it =
seems reasonable to expect</div><div>that reflecting on expressions could g=
ive you its string representation. hopefully, as in the source code.</div><=
div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8e=
x;border-left:1px #ccc solid;padding-left:1ex">
=C2=A0 #define signal protected<br></blockquote><div><br></div><div>Ok, thi=
s does not sounds like a legitimate use case ( sorry Qt )</div><div>This is=
needed for moc, but the ultimate goal is is a moc-less Qt.</div><div>And i=
ndeed this causes actual bug in software if for example you use Qt along bo=
ost::signal</div><div><br></div><div>A better solution would be [[qt::signa=
l]] void my signal.</div><div><br></div><div>I think means to defining dial=
ects should be specifically a non-goal in this problem space</div><div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;borde=
r-left:1px #ccc solid;padding-left:1ex">
=C2=A0 #define with(x) if(x; true)<br></blockquote><div><br></div><div>Yes,=
this is the big problem.</div><div>I'm trying to determine whether is =
worth caring about it to begin with because that falls into</div><div>the &=
quot;defining dialect" category.</div><div>But as you point out, it=
9;s kinda required by test frameworks.</div><div><br></div><div>But if we m=
anage to only need macros in test code, it would already be a big win !</di=
v><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 =
..8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
I'm not *entirely* certain if it's possible with reflection to impl=
ement<br>
the first as a non-macro. Even if *that* case is possible, I'd have to<=
br>
question if all possible uses of stringifying can be replaced,<br>
especially those that stringify entire expressions (again, something<br>
often found in test frameworks).<br>
<br>
For the second, I doubt any replacement is forthcoming.<br>
<br>
For the third, in particular, I'm thinking of macros that expand to a<b=
r>
statement which opens a scope, i.e. `if`, `while`, `for`, ... where the<br>
macro is followed by a statement or an open brace which is associated<br>
with the macro. I suppose we could define a way to make "new control<b=
r>
statements" that would always have this property (in fact, that might<=
br>
even be a very interesting feature, especially if it incorporates<br>
mechanisms to execute code at the end of the scope and possibly to<br>
decide if the scope should be repeated like a loop). However AFAIK the<br>
current "parametric expressions" proposal would not cover these c=
ases.<br>
<br>
-- <br>
Matthew<br>
<br>
-- <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%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">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/c4905596-60a8-cbc1-1e03-2cb811a3543c%=
40gmail.com" rel=3D"noreferrer" target=3D"_blank">https://groups.google.com=
/a/isocpp.org/d/msgid/std-proposals/c4905596-60a8-cbc1-1e03-2cb811a3543c%40=
gmail.com</a>.<br>
</blockquote></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/CA%2BOm%2BSg8Md0PkOa0HL_0%3D21fkjLQEr=
ZqRw9sbAFnqyuQPhVuBQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BOm%2BS=
g8Md0PkOa0HL_0%3D21fkjLQErZqRw9sbAFnqyuQPhVuBQ%40mail.gmail.com</a>.<br />
--000000000000d2a47505780ac205--
.
Author: florian.csdt@gmail.com
Date: Mon, 15 Oct 2018 03:15:27 -0700 (PDT)
Raw View
------=_Part_1476_2121552074.1539598527698
Content-Type: multipart/alternative;
boundary="----=_Part_1477_1766234486.1539598527699"
------=_Part_1477_1766234486.1539598527699
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le vendredi 12 octobre 2018 17:51:29 UTC+2, Miguel Ojeda a =C3=A9crit :
>
> On Fri, Oct 12, 2018 at 12:43 PM <floria...@gmail.com <javascript:>>=20
> wrote:=20
> >=20
> > Le vendredi 12 octobre 2018 12:03:57 UTC+2, Miguel Ojeda a =C3=A9crit :=
=20
> >>=20
> >> On Fri, Oct 12, 2018 at 10:29 AM <floria...@gmail.com> wrote:=20
> >>=20
> >> It is tricky in the same ways as macros, so basically already known by=
=20
> >> C programmers; i.e. it is an advantage w.r.t. introducing lazy=20
> >> arguments (which requires a quite more complex proposal, as you said).=
=20
> >=20
> >=20
> > Even the most experienced C programmer can be tricked by multiple=20
> evaluations within macros: either because they didn't realize it was a=20
> macro, or more subtle because experienced programmers write macros in suc=
h=20
> a way that parameters are not evaluated more than once (for safety=20
> reasons).=20
> >=20
>
> Anyone can make mistakes with any feature, that is not the really=20
> point... Macros are already understood by all C++ (and C) programmers.=20
> They are not *that* tricky, compared to other C++ features. =20
> >> Macros are C++, what do you mean? We try to avoid them because they=20
> >> are on their own phase of translation which gives them shortcomings --=
=20
> >> but that is one of the points of the proposal(s): as we have done=20
> >> previously many times in C++, we are trying to reduce reliance on=20
> >> macros).=20
> >=20
> >=20
> > (No, the preprocessor is not part of C++. C++ acknowledges the existenc=
e=20
> of the preprocessor, but not really more. But that's just being picky...)=
..=20
>
> No. Please refer to [cpp] or [lex] in the standard.=20
>
You're right. I was fooled by the fact that the preprocessor really looks=
=20
like a separate language on its own.
But that doesn't really change my point (because the preprocessor looks=20
like a separate language on its own).
=20
>
> >> Isn't the only non-overlapping use case the ability to use declare=20
> >> functions which use lazy arguments without a definition? (If I am=20
> >> missing other significant use cases that cannot be provided by a=20
> >> macro-like proposal, please let me know!).=20
> >=20
> >=20
> > You miss the lifetime rules. Those are crucial.=20
>
> I don't see what the lifetime rules buys you that the macro-like=20
> approach doesn't. Please provide an example.=20
>
This example was already provided previously in this thread; but here it is=
=20
(updated):
void print(std::string_view sv) { std::cout << sv << std::endl; }
std::string_view eager(const std::string & s) {
std::string_view sv{s};
return sv;
}
std::string_view lazy([] -> std::string s) {
std::string_view sv{s};
return sv;
}
std::string_view call(std::function<std::string()> f) {
std::string_view sv{f()};
return sv;
}
using macro(auto s) {
std::string_view sv{s};
return sv;
}
print(eager(std::string("hello world!"))); // here is fine
print(call([]{ return std::string("hello world!");})); // here,=20
`std::string("hello world")` will be destroyed before calling `print`
print(lazy(std::string("hello world!"))); // here, we want it to have the=
=20
same lifetime as for `eager`
print(macro(std::string("hello world!"))); // what here ?
Here, with eager parameters, the std::string("hello world!") lifetime ends=
=20
after the call to print.
The same example with a callable does not work as the string is destroyed=
=20
before the call to print (so before the string_view is actually used).
In the lazy case, we want the string to also be destroyed after the call to=
=20
print as in the eager case.
I already showed previously in this thread how to implement such lifetimes=
=20
with lazy parameters with no overhead on the cases where it is not needed.
Now, what's the lifetime of the std::string in the macro case?
I can think of 2 cases: The string will be destroyed just after the=20
string_view is constructed (so before it is returned).
Or the string is detroyed when the string_view is returned (so before the=
=20
call to print).
That's the kind of lifetime issues lazy parameters should solve and=20
macro-like approach does not handle (AFAIU).
We can imagine to apply the same special rules we imagined for lazy=20
parameters to the parametric expressions, but as you said, it is probably=
=20
not worth.
If I misunderstood the lifetime in the parametric expression case, please=
=20
enlight me.
Cheers,
Florian
--=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/8663ade8-7fcf-4bf8-b6be-4304d7e01c7f%40isocpp.or=
g.
------=_Part_1477_1766234486.1539598527699
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>Le vendredi 12 octobre 2018 17:51:29 UTC+2, Miguel Oje=
da a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Fri, =
Oct 12, 2018 at 12:43 PM <<a href=3D"javascript:" target=3D"_blank" gdf-=
obfuscated-mailto=3D"1goh0nJzAwAJ" rel=3D"nofollow" onmousedown=3D"this.hre=
f=3D'javascript:';return true;" onclick=3D"this.href=3D'javascr=
ipt:';return true;">floria...@gmail.com</a>> wrote:
<br>>
<br>> Le vendredi 12 octobre 2018 12:03:57 UTC+2, Miguel Ojeda a =C3=A9c=
rit :
<br>>>
<br>>> On Fri, Oct 12, 2018 at 10:29 AM <<a>floria...@gmail.com</a=
>> wrote:
<br>>>
<br>>> It is tricky in the same ways as macros, so basically already =
known by
<br>>> C programmers; i.e. it is an advantage w.r.t. introducing lazy
<br>>> arguments (which requires a quite more complex proposal, as yo=
u said).
<br>>
<br>>
<br>> Even the most experienced C programmer can be tricked by multiple =
evaluations within macros: either because they didn't realize it was a =
macro, or more subtle because experienced programmers write macros in such =
a way that parameters are not evaluated more than once (for safety reasons)=
..
<br>>
<br>
<br>Anyone can make mistakes with any feature, that is not the really
<br>point... Macros are already understood by all C++ (and C) programmers.
<br>They are not *that* tricky, compared to other C++ features.
=C2=A0</blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>>> Macros are C++, what do you mean? We try to avoid them because=
they
<br>>> are on their own phase of translation which gives them shortco=
mings --
<br>>> but that is one of the points of the proposal(s): as we have d=
one
<br>>> previously many times in C++, we are trying to reduce reliance=
on
<br>>> macros).
<br>>
<br>>
<br>> (No, the preprocessor is not part of C++. C++ acknowledges the exi=
stence of the preprocessor, but not really more. But that's just being =
picky...).
<br>
<br>No. Please refer to [cpp] or [lex] in the standard.
<br></blockquote><div><br></div><div>You're right. I was fooled by the =
fact that the preprocessor really looks like a separate language on its own=
..</div><div>But that doesn't really change my point (because the prepro=
cessor looks like a separate language on its own).<br></div><div>=C2=A0</di=
v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;">
<br>>> Isn't the only non-overlapping use case the ability to use=
declare
<br>>> functions which use lazy arguments without a definition? (If I=
am
<br>>> missing other significant use cases that cannot be provided by=
a
<br>>> macro-like proposal, please let me know!).
<br>>
<br>>
<br>> You miss the lifetime rules. Those are crucial.
<br>
<br>I don't see what the lifetime rules buys you that the macro-like
<br>approach doesn't. Please provide an example.
<br></blockquote><div><br></div><div>This example was already provided prev=
iously in this thread; but here it is (updated):</div><div><div style=3D"ba=
ckground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); borde=
r-style: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"pre=
ttyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">void</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">print</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">std</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">string_view sv</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">cout </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify"><<</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> sv </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify"><<</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">endl</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>std</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify">string_view eager</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">const</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">string</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"> s</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">)</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 std</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">string_view sv</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">s</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 </span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">return</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> sv</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-prett=
ify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">string_view laz=
y</span><span style=3D"color: #660;" class=3D"styled-by-prettify">([]</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">-></span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">string</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> s</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </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 std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">string_v=
iew sv</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">s</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 </span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> sv</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>std</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">string_view call</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
>std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">function</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify">std</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">string</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">()></span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> f</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 std</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">string_=
view sv</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">f</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">()};</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> sv</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">using</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> macro</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> s</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;" cla=
ss=3D"styled-by-prettify"><br>=C2=A0 std</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">string_view sv</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">s</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 </span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">return</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
sv</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">}</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br><br></span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">print</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">eager</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">std</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">::</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
string</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</s=
pan><span style=3D"color: #080;" class=3D"styled-by-prettify">"hello w=
orld!"</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>)));</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #800;" class=3D"styled-by-prettify">// here is fin=
e</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">print</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">call</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;" cla=
ss=3D"styled-by-prettify">return</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">::</span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">string</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">(</span><span style=3D"color: #080;" class=3D"styled-by-prettify">&qu=
ot;hello world!"</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">//=
here, `std::string("hello world")` will be destroyed before call=
ing `print`</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">print=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">lazy</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">std</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">::</span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">string</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #080;" class=3D"style=
d-by-prettify">"hello world!"</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"style=
d-by-prettify">// here, we want it to have the same lifetime as for `eager`=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">print</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">macro</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">std</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">::</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">string</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">(</span><span style=3D"color: #080;" class=3D"styled-by-prett=
ify">"hello world!"</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">)));</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-pretti=
fy">// what here ?</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br></span></div></code></div><br> Here, with eager parameters, the=
std::string("hello world!") lifetime ends after the call to prin=
t.</div><div>The same example with a callable does not work as the string i=
s destroyed before the call to print (so before the string_view is actually=
used).</div><div><br></div><div>In the lazy case, we want the string to al=
so be destroyed after the call to print as in the eager case.</div><div>I a=
lready showed previously in this thread how to implement such lifetimes wit=
h lazy parameters with no overhead on the cases where it is not needed.</di=
v><div><br></div><div>Now, what's the lifetime of the std::string in th=
e macro case?</div><div>I can think of 2 cases: The string will be destroye=
d just after the string_view is constructed (so before it is returned).</di=
v><div>Or the string is detroyed when the string_view is returned (so befor=
e the call to print).</div><div><br></div><div>That's the kind of lifet=
ime issues lazy parameters should solve and macro-like approach does not ha=
ndle (AFAIU).</div><div>We can imagine to apply the same special rules we i=
magined for lazy parameters to the parametric expressions, but as you said,=
it is probably not worth.</div><div><br></div><div>If I misunderstood the =
lifetime in the parametric expression case, please enlight me.</div><div><b=
r></div><div>Cheers,</div><div>Florian<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/8663ade8-7fcf-4bf8-b6be-4304d7e01c7f%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/8663ade8-7fcf-4bf8-b6be-4304d7e01c7f=
%40isocpp.org</a>.<br />
------=_Part_1477_1766234486.1539598527699--
------=_Part_1476_2121552074.1539598527698--
.
Author: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
Date: Mon, 15 Oct 2018 14:20:24 +0200
Raw View
On Mon, Oct 15, 2018 at 12:15 PM <florian.csdt@gmail.com> wrote:
>
>
> Le vendredi 12 octobre 2018 17:51:29 UTC+2, Miguel Ojeda a =C3=A9crit :
>>
>> No. Please refer to [cpp] or [lex] in the standard.
>
>
> You're right. I was fooled by the fact that the preprocessor really looks=
like a separate language on its own.
No worries! It is understandable (and no -sane- person knows all the standa=
rd ;)
> But that doesn't really change my point (because the preprocessor looks l=
ike a separate language on its own).
Well, even then, I could argue that there are actually many
"sub-languages" or "styles" (C-like, OOP-like, TMP...) inside C++, or
even "realms of computation" (as Boost.Hana/Louis Dionne called them:
runtime, constexpr, type...).
>>
>> I don't see what the lifetime rules buys you that the macro-like
>> approach doesn't. Please provide an example.
>
>
> This example was already provided previously in this thread; but here it =
is (updated):
> void print(std::string_view sv) { std::cout << sv << std::endl; }
>
> std::string_view eager(const std::string & s) {
> std::string_view sv{s};
> return sv;
> }
> std::string_view lazy([] -> std::string s) {
> std::string_view sv{s};
> return sv;
> }
> std::string_view call(std::function<std::string()> f) {
> std::string_view sv{f()};
> return sv;
> }
> using macro(auto s) {
> std::string_view sv{s};
> return sv;
> }
>
> print(eager(std::string("hello world!"))); // here is fine
> print(call([]{ return std::string("hello world!");})); // here, `std::str=
ing("hello world")` will be destroyed before calling `print`
> print(lazy(std::string("hello world!"))); // here, we want it to have the=
same lifetime as for `eager`
> print(macro(std::string("hello world!"))); // what here ?
>
> Here, with eager parameters, the std::string("hello world!") lifetime end=
s after the call to print.
> The same example with a callable does not work as the string is destroyed=
before the call to print (so before the string_view is actually used).
>
> In the lazy case, we want the string to also be destroyed after the call =
to print as in the eager case.
> I already showed previously in this thread how to implement such lifetime=
s with lazy parameters with no overhead on the cases where it is not needed=
..
>
> Now, what's the lifetime of the std::string in the macro case?
> I can think of 2 cases: The string will be destroyed just after the strin=
g_view is constructed (so before it is returned).
> Or the string is detroyed when the string_view is returned (so before the=
call to print).
>
> That's the kind of lifetime issues lazy parameters should solve and macro=
-like approach does not handle (AFAIU).
> We can imagine to apply the same special rules we imagined for lazy param=
eters to the parametric expressions, but as you said, it is probably not wo=
rth.
>
> If I misunderstood the lifetime in the parametric expression case, please=
enlight me.
If we are discussing the macro-like case, you need to use the "using"
parameters, i.e.
using macro(using auto s) {
std::string_view sv{s};
return sv;
}
Which means that would expand into something like:
print(({std::string_view sv{std::string("hello world!")}; sv;}));
Which would mean the temporary is destroyed, as usual, at the end of
the "std::string_view sv{std::string("hello world!")};" statement.
Simple, no? And, of course, it wouldn't work.
If you are talking about the "normal" parametric expressions, i.e.
without "using", it would expand into something like:
print(({ auto&& s =3D std::string("hello world!"); std::string_view
sv{s}; sv; }));
So, in this case, we have a local variable. Here, it depends on the
rules you define for the temporaries. For instance, if follow GNU's
extension rules for statement expressions
(https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html), then:
"""
In a statement expression, any temporaries created within a
statement are destroyed at that statement=E2=80=99s end. This makes stateme=
nt
expressions inside macros slightly different from function calls. In
the latter case temporaries introduced during argument evaluation are
destroyed at the end of the statement that includes the function call.
In the statement expression case they are destroyed during the
statement expression. For instance,
#define macro(a) ({__typeof__(a) b =3D (a); b + 3; })
template<typename T> T function(T a) { T b =3D a; return b + 3; }
void foo ()
{
macro (X ());
function (X ());
}
has different places where temporaries are destroyed. For the macro
case, the temporary X is destroyed just after the initialization of b.
In the function case that temporary is destroyed when the function
returns.
"""
....it would mean that "s" is destroyed before "print" is called.
Simple as well; and again, it wouldn't work either. This would make it
different to a normal function call, where the argument would live
until the end of the "outer" statement, i.e. after the print.
So, the lifetime rules do not seem complex to understand. The
confusion comes, I think, because you are trying to use the parametric
expressions as if it was a "lazy" argument; while what you would have
to do is code the "print" itself as the parametric expression. In
other words, you wouldn't write "macro" and "print". Instead, you
write "print" as a P.E. itself. For instance, the typical use case for
the "using" parameters would be:
using warn(using auto expr) {
if (level >=3D warning)
std::cout << expr << std::endl;
}
i.e. when you write:
warn(very_expensive_function());
very_expensive_function() would only be called whenever we are going
to actually call it.
Cheers,
Miguel
--=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/CANiq72kmyc50c%2BrfSCZAqv%3DLm03sW85qccRHnOWkp5%=
3D3vF_w-g%40mail.gmail.com.
.
Author: florian.csdt@gmail.com
Date: Mon, 15 Oct 2018 06:17:33 -0700 (PDT)
Raw View
------=_Part_1569_1247871532.1539609453436
Content-Type: multipart/alternative;
boundary="----=_Part_1570_528641020.1539609453437"
------=_Part_1570_528641020.1539609453437
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le lundi 15 octobre 2018 14:20:38 UTC+2, Miguel Ojeda a =C3=A9crit :
>
> On Mon, Oct 15, 2018 at 12:15 PM <floria...@gmail.com <javascript:>>=20
> wrote:=20
> >=20
> >=20
> > Le vendredi 12 octobre 2018 17:51:29 UTC+2, Miguel Ojeda a =C3=A9crit :=
=20
> >>=20
> >> No. Please refer to [cpp] or [lex] in the standard.=20
> >=20
> >=20
> > You're right. I was fooled by the fact that the preprocessor really=20
> looks like a separate language on its own.=20
>
> No worries! It is understandable (and no -sane- person knows all the=20
> standard ;)=20
>
> > But that doesn't really change my point (because the preprocessor looks=
=20
> like a separate language on its own).=20
>
> Well, even then, I could argue that there are actually many=20
> "sub-languages" or "styles" (C-like, OOP-like, TMP...) inside C++, or=20
> even "realms of computation" (as Boost.Hana/Louis Dionne called them:=20
> runtime, constexpr, type...).=20
>
> >>=20
> >> I don't see what the lifetime rules buys you that the macro-like=20
> >> approach doesn't. Please provide an example.=20
> >=20
> >=20
> > This example was already provided previously in this thread; but here i=
t=20
> is (updated):=20
> > void print(std::string_view sv) { std::cout << sv << std::endl; }=20
> >=20
> > std::string_view eager(const std::string & s) {=20
> > std::string_view sv{s};=20
> > return sv;=20
> > }=20
> > std::string_view lazy([] -> std::string s) {=20
> > std::string_view sv{s};=20
> > return sv;=20
> > }=20
> > std::string_view call(std::function<std::string()> f) {=20
> > std::string_view sv{f()};=20
> > return sv;=20
> > }=20
> > using macro(auto s) {=20
> > std::string_view sv{s};=20
> > return sv;=20
> > }=20
> >=20
> > print(eager(std::string("hello world!"))); // here is fine=20
> > print(call([]{ return std::string("hello world!");})); // here,=20
> `std::string("hello world")` will be destroyed before calling `print`=20
> > print(lazy(std::string("hello world!"))); // here, we want it to have=
=20
> the same lifetime as for `eager`=20
> > print(macro(std::string("hello world!"))); // what here ?=20
> >=20
> > Here, with eager parameters, the std::string("hello world!") lifetime=
=20
> ends after the call to print.=20
> > The same example with a callable does not work as the string is=20
> destroyed before the call to print (so before the string_view is actually=
=20
> used).=20
> >=20
> > In the lazy case, we want the string to also be destroyed after the cal=
l=20
> to print as in the eager case.=20
> > I already showed previously in this thread how to implement such=20
> lifetimes with lazy parameters with no overhead on the cases where it is=
=20
> not needed.=20
> >=20
> > Now, what's the lifetime of the std::string in the macro case?=20
> > I can think of 2 cases: The string will be destroyed just after the=20
> string_view is constructed (so before it is returned).=20
> > Or the string is detroyed when the string_view is returned (so before=
=20
> the call to print).=20
> >=20
> > That's the kind of lifetime issues lazy parameters should solve and=20
> macro-like approach does not handle (AFAIU).=20
> > We can imagine to apply the same special rules we imagined for lazy=20
> parameters to the parametric expressions, but as you said, it is probably=
=20
> not worth.=20
> >=20
> > If I misunderstood the lifetime in the parametric expression case,=20
> please enlight me.=20
>
> If we are discussing the macro-like case, you need to use the "using"=20
> parameters, i.e.=20
>
> using macro(using auto s) {=20
> std::string_view sv{s};=20
> return sv;=20
> }=20
>
> Which means that would expand into something like:=20
>
> print(({std::string_view sv{std::string("hello world!")}; sv;}));=20
>
> Which would mean the temporary is destroyed, as usual, at the end of=20
> the "std::string_view sv{std::string("hello world!")};" statement.=20
> Simple, no? And, of course, it wouldn't work.=20
>
> If you are talking about the "normal" parametric expressions, i.e.=20
> without "using", it would expand into something like:=20
>
> print(({ auto&& s =3D std::string("hello world!"); std::string_view=20
> sv{s}; sv; }));=20
>
> So, in this case, we have a local variable. Here, it depends on the=20
> rules you define for the temporaries. For instance, if follow GNU's=20
> extension rules for statement expressions=20
> (https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html), then:=20
>
> """=20
> In a statement expression, any temporaries created within a=20
> statement are destroyed at that statement=E2=80=99s end. This makes state=
ment=20
> expressions inside macros slightly different from function calls. In=20
> the latter case temporaries introduced during argument evaluation are=20
> destroyed at the end of the statement that includes the function call.=20
> In the statement expression case they are destroyed during the=20
> statement expression. For instance,=20
> #define macro(a) ({__typeof__(a) b =3D (a); b + 3; })=20
> template<typename T> T function(T a) { T b =3D a; return b + 3; }=20
>
> void foo ()=20
> {=20
> macro (X ());=20
> function (X ());=20
> }=20
>
> has different places where temporaries are destroyed. For the macro=20
> case, the temporary X is destroyed just after the initialization of b.=20
> In the function case that temporary is destroyed when the function=20
> returns.=20
> """=20
>
> ...it would mean that "s" is destroyed before "print" is called.=20
> Simple as well; and again, it wouldn't work either. This would make it=20
> different to a normal function call, where the argument would live=20
> until the end of the "outer" statement, i.e. after the print.=20
>
> So, the lifetime rules do not seem complex to understand. The=20
> confusion comes, I think, because you are trying to use the parametric=20
> expressions as if it was a "lazy" argument;
Yes, that's exactly what I'm trying to do, in order to show you that the=20
rules of parametric expressions are not enough to implement properly lazy=
=20
parameters.
=20
> while what you would have=20
> to do is code the "print" itself as the parametric expression.=20
With this example, yes. But this example is here only to show what kind of=
=20
lifetime problems we can have with lazy parameters.
Those problems are solvable with the current lazy parameter design, but not=
=20
with parametric expressions.
That's why I consider lazy parameters is an independent proposal that=20
should be pursued on its own, even if parametric expressions were already=
=20
part of the language.
=20
> In other words, you wouldn't write "macro" and "print". Instead, you=20
> write "print" as a P.E. itself. For instance, the typical use case for=20
> the "using" parameters would be:=20
>
> using warn(using auto expr) {=20
> if (level >=3D warning)=20
> std::cout << expr << std::endl;=20
> }=20
>
> i.e. when you write:=20
>
> warn(very_expensive_function());=20
>
> very_expensive_function() would only be called whenever we are going=20
> to actually call it.=20
>
As I said, this example is not about how to implement a lazy print with=20
either lazy parameters or parametric expressions,
but is a simple example showing what kind of lifetime issues we can=20
encounter and we want to avoid (or not).
An implementation of lazy parameters should address these lifetime issues.
Also, I remembered another issue that lazy parameters solve and cannot be=
=20
solve with parametric expressions:
struct Foo {
int a, b, c;
};
std::vector<Foo> v;
v.lazy_push_back({1, 2, 3});
v.macro_push_back(Foo{1, 2, 3});
With parametric expressions, you would need to specify Foo at the call=20
site, while the lazy parameter doesn't need it at the call site.
Lazy parameters don't work with expressions but with initializers.
--=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/5c5403f0-c6c6-4777-a27e-79270569dcff%40isocpp.or=
g.
------=_Part_1570_528641020.1539609453437
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>Le lundi 15 octobre 2018 14:20:38 UTC+2, Miguel Ojeda =
a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Mon, Oct=
15, 2018 at 12:15 PM <<a href=3D"javascript:" target=3D"_blank" gdf-obf=
uscated-mailto=3D"no3LJ69TBAAJ" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'javascript:';return true;" onclick=3D"this.href=3D'javascri=
pt:';return true;">floria...@gmail.com</a>> wrote:
<br>>
<br>>
<br>> Le vendredi 12 octobre 2018 17:51:29 UTC+2, Miguel Ojeda a =C3=A9c=
rit :
<br>>>
<br>>> No. Please refer to [cpp] or [lex] in the standard.
<br>>
<br>>
<br>> You're right. I was fooled by the fact that the preprocessor r=
eally looks like a separate language on its own.
<br>
<br>No worries! It is understandable (and no -sane- person knows all the st=
andard ;)
<br>
<br>> But that doesn't really change my point (because the preproces=
sor looks like a separate language on its own).
<br>
<br>Well, even then, I could argue that there are actually many
<br>"sub-languages" or "styles" (C-like, OOP-like, TMP.=
...) inside C++, or
<br>even "realms of computation" (as Boost.Hana/Louis Dionne call=
ed them:
<br>runtime, constexpr, type...).
<br>
<br>>>
<br>>> I don't see what the lifetime rules buys you that the macr=
o-like
<br>>> approach doesn't. Please provide an example.
<br>>
<br>>
<br>> This example was already provided previously in this thread; but h=
ere it is (updated):
<br>> void print(std::string_view sv) { std::cout << sv << s=
td::endl; }
<br>>
<br>> std::string_view eager(const std::string & s) {
<br>> =C2=A0 std::string_view sv{s};
<br>> =C2=A0 return sv;
<br>> }
<br>> std::string_view lazy([] -> std::string s) {
<br>> =C2=A0 std::string_view sv{s};
<br>> =C2=A0 return sv;
<br>> }
<br>> std::string_view call(std::function<std::<wbr>string()> f) {
<br>> =C2=A0 std::string_view sv{f()};
<br>> =C2=A0 return sv;
<br>> }
<br>> using macro(auto s) {
<br>> =C2=A0 std::string_view sv{s};
<br>> =C2=A0 return sv;
<br>> }
<br>>
<br>> print(eager(std::string("hello world!"))); // here is fi=
ne
<br>> print(call([]{ return std::string("hello world!");})); /=
/ here, `std::string("hello world")` will be destroyed before cal=
ling `print`
<br>> print(lazy(std::string("hello world!"))); // here, we wa=
nt it to have the same lifetime as for `eager`
<br>> print(macro(std::string("hello world!"))); // what here =
?
<br>>
<br>> Here, with eager parameters, the std::string("hello world!&qu=
ot;) lifetime ends after the call to print.
<br>> The same example with a callable does not work as the string is de=
stroyed before the call to print (so before the string_view is actually use=
d).
<br>>
<br>> In the lazy case, we want the string to also be destroyed after th=
e call to print as in the eager case.
<br>> I already showed previously in this thread how to implement such l=
ifetimes with lazy parameters with no overhead on the cases where it is not=
needed.
<br>>
<br>> Now, what's the lifetime of the std::string in the macro case?
<br>> I can think of 2 cases: The string will be destroyed just after th=
e string_view is constructed (so before it is returned).
<br>> Or the string is detroyed when the string_view is returned (so bef=
ore the call to print).
<br>>
<br>> That's the kind of lifetime issues lazy parameters should solv=
e and macro-like approach does not handle (AFAIU).
<br>> We can imagine to apply the same special rules we imagined for laz=
y parameters to the parametric expressions, but as you said, it is probably=
not worth.
<br>>
<br>> If I misunderstood the lifetime in the parametric expression case,=
please enlight me.
<br>
<br>If we are discussing the macro-like case, you need to use the "usi=
ng"
<br>parameters, i.e.
<br>
<br>=C2=A0 using macro(using auto s) {
<br>=C2=A0 =C2=A0 std::string_view sv{s};
<br>=C2=A0 =C2=A0 return sv;
<br>=C2=A0 }
<br>
<br>Which means that would expand into something like:
<br>
<br>=C2=A0 print(({std::string_view sv{std::string("hello world!"=
)}; sv;}));
<br>
<br>Which would mean the temporary is destroyed, as usual, at the end of
<br>the "std::string_view sv{std::string("hello world!")};&q=
uot; statement.
<br>Simple, no? And, of course, it wouldn't work.
<br>
<br>If you are talking about the "normal" parametric expressions,=
i.e.
<br>without "using", it would expand into something like:
<br>
<br>=C2=A0 print(({ auto&& s =3D std::string("hello world!&quo=
t;); std::string_view
<br>sv{s}; sv; }));
<br>
<br>So, in this case, we have a local variable. Here, it depends on the
<br>rules you define for the temporaries. For instance, if follow GNU's
<br>extension rules for statement expressions
<br>(<a href=3D"https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html" ta=
rget=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'https://ww=
w.google.com/url?q\x3dhttps%3A%2F%2Fgcc.gnu.org%2Fonlinedocs%2Fgcc%2FStatem=
ent-Exprs.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFeEkwZYJk3HMqDHmVizd=
1_6WnSeA';return true;" onclick=3D"this.href=3D'https://www.google.=
com/url?q\x3dhttps%3A%2F%2Fgcc.gnu.org%2Fonlinedocs%2Fgcc%2FStatement-Exprs=
..html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFeEkwZYJk3HMqDHmVizd1_6WnSeA&=
#39;;return true;">https://gcc.gnu.org/<wbr>onlinedocs/gcc/Statement-<wbr>E=
xprs.html</a>), then:
<br>
<br>=C2=A0 """
<br>=C2=A0 In a statement expression, any temporaries created within a
<br>statement are destroyed at that statement=E2=80=99s end. This makes sta=
tement
<br>expressions inside macros slightly different from function calls. In
<br>the latter case temporaries introduced during argument evaluation are
<br>destroyed at the end of the statement that includes the function call.
<br>In the statement expression case they are destroyed during the
<br>statement expression. For instance,
<br>=C2=A0 #define macro(a) =C2=A0({__typeof__(a) b =3D (a); b + 3; })
<br>=C2=A0 template<typename T> T function(T a) { T b =3D a; return b=
+ 3; }
<br>
<br>=C2=A0 void foo ()
<br>=C2=A0 {
<br>=C2=A0 =C2=A0 macro (X ());
<br>=C2=A0 =C2=A0 function (X ());
<br>=C2=A0 }
<br>
<br>=C2=A0 has different places where temporaries are destroyed. For the ma=
cro
<br>case, the temporary X is destroyed just after the initialization of b.
<br>In the function case that temporary is destroyed when the function
<br>returns.
<br>=C2=A0 """
<br>
<br>...it would mean that "s" is destroyed before "print&quo=
t; is called.
<br>Simple as well; and again, it wouldn't work either. This would make=
it
<br>different to a normal function call, where the argument would live
<br>until the end of the "outer" statement, i.e. after the print.
<br>
<br>So, the lifetime rules do not seem complex to understand. The
<br>confusion comes, I think, because you are trying to use the parametric
<br>expressions as if it was a "lazy" argument;</blockquote><div>=
<br></div><div>Yes, that's exactly what I'm trying to do, in order =
to show you that the rules of parametric expressions are not enough to impl=
ement properly lazy parameters.</div><div>=C2=A0</div><blockquote class=3D"=
gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc so=
lid;padding-left: 1ex;"> while what you would have
<br>to do is code the "print" itself as the parametric expression=
.. </blockquote><div><br></div><div>With this example, yes. But this example=
is here only to show what kind of lifetime problems we can have with lazy =
parameters.</div><div>Those problems are solvable with the current lazy par=
ameter design, but not with parametric expressions.</div><div>That's wh=
y I consider lazy parameters is an independent proposal that should be purs=
ued on its own, even if parametric expressions were already part of the lan=
guage.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D=
"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex=
;">In
other words, you wouldn't write "macro" and "print"=
.. Instead, you
<br>write "print" as a P.E. itself. For instance, the typical use=
case for
<br>the "using" parameters would be:
<br>
<br>=C2=A0 =C2=A0 using warn(using auto expr) {
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (level >=3D warning)
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 std::cout << expr <&=
lt; std::endl;
<br>=C2=A0 =C2=A0 }
<br>
<br>i.e. when you write:
<br>
<br>=C2=A0 =C2=A0 warn(very_expensive_function()<wbr>);
<br>
<br>very_expensive_function() would only be called whenever we are going
<br>to actually call it.
<br></blockquote><div><br></div><div>As I said, this example is not about h=
ow to implement a lazy print with either lazy parameters or parametric expr=
essions,</div><div>but is a simple example showing what kind of lifetime is=
sues we can encounter and we want to avoid (or not).</div><div>An implement=
ation of lazy parameters should address these lifetime issues.</div><div><b=
r></div><div>Also, I remembered another issue that lazy parameters solve an=
d cannot be solve with parametric expressions:</div><div><div style=3D"back=
ground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-=
style: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"prett=
yprint"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">Foo</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"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> a</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>,</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 st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> c</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">};</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br><br>std</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">vector</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify"><</span><span style=3D"color: #606;" 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"> v</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br><br>v</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">lazy_push_back</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">({</span><span style=3D"color: #0=
66;" class=3D"styled-by-prettify">1</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-pre=
ttify">2</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #066;" class=3D"styled-by-prettify">3</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">});</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br>v</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">macro_push_back</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">(</span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">{</span><span style=3D"color: #066;" class=3D"styled-by-pr=
ettify">1</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #066;" class=3D"styled-by-prettify">2</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"styled-by-prettify">3</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>With parametric expressions,=
you would need to specify Foo at the call site, while the lazy parameter d=
oesn't need it at the call site.</div><div>Lazy parameters don't wo=
rk with expressions but with initializers.<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/5c5403f0-c6c6-4777-a27e-79270569dcff%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5c5403f0-c6c6-4777-a27e-79270569dcff=
%40isocpp.org</a>.<br />
------=_Part_1570_528641020.1539609453437--
------=_Part_1569_1247871532.1539609453436--
.
Author: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
Date: Mon, 15 Oct 2018 15:52:11 +0200
Raw View
On Mon, Oct 15, 2018 at 3:17 PM <florian.csdt@gmail.com> wrote:
>
>
> Le lundi 15 octobre 2018 14:20:38 UTC+2, Miguel Ojeda a =C3=A9crit :
>>
>> If we are discussing the macro-like case, you need to use the "using"
>> parameters, i.e.
>>
>> using macro(using auto s) {
>> std::string_view sv{s};
>> return sv;
>> }
>>
>> Which means that would expand into something like:
>>
>> print(({std::string_view sv{std::string("hello world!")}; sv;}));
>>
>> Which would mean the temporary is destroyed, as usual, at the end of
>> the "std::string_view sv{std::string("hello world!")};" statement.
>> Simple, no? And, of course, it wouldn't work.
>>
>> If you are talking about the "normal" parametric expressions, i.e.
>> without "using", it would expand into something like:
>>
>> print(({ auto&& s =3D std::string("hello world!"); std::string_view
>> sv{s}; sv; }));
>>
>> So, in this case, we have a local variable. Here, it depends on the
>> rules you define for the temporaries. For instance, if follow GNU's
>> extension rules for statement expressions
>> (https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html), then:
>>
>> """
>> In a statement expression, any temporaries created within a
>> statement are destroyed at that statement=E2=80=99s end. This makes stat=
ement
>> expressions inside macros slightly different from function calls. In
>> the latter case temporaries introduced during argument evaluation are
>> destroyed at the end of the statement that includes the function call.
>> In the statement expression case they are destroyed during the
>> statement expression. For instance,
>> #define macro(a) ({__typeof__(a) b =3D (a); b + 3; })
>> template<typename T> T function(T a) { T b =3D a; return b + 3; }
>>
>> void foo ()
>> {
>> macro (X ());
>> function (X ());
>> }
>>
>> has different places where temporaries are destroyed. For the macro
>> case, the temporary X is destroyed just after the initialization of b.
>> In the function case that temporary is destroyed when the function
>> returns.
>> """
>>
>> ...it would mean that "s" is destroyed before "print" is called.
>> Simple as well; and again, it wouldn't work either. This would make it
>> different to a normal function call, where the argument would live
>> until the end of the "outer" statement, i.e. after the print.
>>
>> So, the lifetime rules do not seem complex to understand. The
>> confusion comes, I think, because you are trying to use the parametric
>> expressions as if it was a "lazy" argument;
>
>
> Yes, that's exactly what I'm trying to do, in order to show you that the =
rules of parametric expressions are not enough to implement properly lazy p=
arameters.
>
I am not sure how you reach that conclusion. I am confused now.
>>
>> while what you would have
>> to do is code the "print" itself as the parametric expression.
>
>
> With this example, yes. But this example is here only to show what kind o=
f lifetime problems we can have with lazy parameters.
> Those problems are solvable with the current lazy parameter design, but n=
ot with parametric expressions.
Which problem? Parametric expressions cannot be used like in your
"macro" example: you cannot return references to destroyed
temporaries; same as in "normal" code. I am unsure what is the problem
here. That does not mean they cannot be used to implement lazy
parameters (or similar stuff).
> That's why I consider lazy parameters is an independent proposal that sho=
uld be pursued on its own, even if parametric expressions were already part=
of the language.
>
>>
>> In other words, you wouldn't write "macro" and "print". Instead, you
>> write "print" as a P.E. itself. For instance, the typical use case for
>> the "using" parameters would be:
>>
>> using warn(using auto expr) {
>> if (level >=3D warning)
>> std::cout << expr << std::endl;
>> }
>>
>> i.e. when you write:
>>
>> warn(very_expensive_function());
>>
>> very_expensive_function() would only be called whenever we are going
>> to actually call it.
>
>
> As I said, this example is not about how to implement a lazy print with e=
ither lazy parameters or parametric expressions,
> but is a simple example showing what kind of lifetime issues we can encou=
nter and we want to avoid (or not).
> An implementation of lazy parameters should address these lifetime issues=
..
>
But what I asked was an example of what you cannot implement with
PEs/macros that you can with lazy parameters. As shown, you can
implement the "print with lazy parameter" using the PEs/macros, so I
don't think that example is valid for this.
> Also, I remembered another issue that lazy parameters solve and cannot be=
solve with parametric expressions:
> struct Foo {
> int a, b, c;
> };
>
> std::vector<Foo> v;
>
> v.lazy_push_back({1, 2, 3});
> v.macro_push_back(Foo{1, 2, 3});
>
> With parametric expressions, you would need to specify Foo at the call si=
te, while the lazy parameter doesn't need it at the call site.
> Lazy parameters don't work with expressions but with initializers.
Why? You can do "v.macro_push_back({1, 2, 3});" and use the expression
to initialize a Foo inside; with both the PE or the macro-like PE
approaches. I am not sure I understand. Even if it was not possible,
you could simply allow for non-auto parameters in the PE proposal
(i.e. allow to constraint the types of the parameters).
Anyway, even if it was impossible to accomplish and we had to write
"Foo", I don't see how it is an issue. It is still the case that the
"macro-like PEs" are more general than lazy parameters (assuming
access to the definition).
Again, I am not saying lazy parameters are undesirable, or that PEs
solve everything. What I am saying is that, as a concept, lazy
parameters can be implemented easily using macro-like "expression
forwarding". Regardless of how we implement each of the them, that is
still true. Which is why, if we could get "expression forwarding", we
have already solved the lazy parameter problem; so I think it is worth
considering if "expression forwarding" can be done first.
Cheers,
Miguel
--=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/CANiq72%3Dq7%3Dp1aTTn71dsnZt7HrJ3%2BED8o6Hz3%3DT=
yjjvmUVOVng%40mail.gmail.com.
.
Author: florian.csdt@gmail.com
Date: Mon, 15 Oct 2018 07:27:42 -0700 (PDT)
Raw View
------=_Part_1526_632308035.1539613662156
Content-Type: multipart/alternative;
boundary="----=_Part_1527_830733094.1539613662157"
------=_Part_1527_830733094.1539613662157
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le lundi 15 octobre 2018 15:52:24 UTC+2, Miguel Ojeda a =C3=A9crit :
>
> On Mon, Oct 15, 2018 at 3:17 PM <floria...@gmail.com <javascript:>>=20
> wrote:=20
> >=20
> >=20
> > Le lundi 15 octobre 2018 14:20:38 UTC+2, Miguel Ojeda a =C3=A9crit :=20
> >>=20
> >> If we are discussing the macro-like case, you need to use the "using"=
=20
> >> parameters, i.e.=20
> >>=20
> >> using macro(using auto s) {=20
> >> std::string_view sv{s};=20
> >> return sv;=20
> >> }=20
> >>=20
> >> Which means that would expand into something like:=20
> >>=20
> >> print(({std::string_view sv{std::string("hello world!")}; sv;}));=20
> >>=20
> >> Which would mean the temporary is destroyed, as usual, at the end of=
=20
> >> the "std::string_view sv{std::string("hello world!")};" statement.=20
> >> Simple, no? And, of course, it wouldn't work.=20
> >>=20
> >> If you are talking about the "normal" parametric expressions, i.e.=20
> >> without "using", it would expand into something like:=20
> >>=20
> >> print(({ auto&& s =3D std::string("hello world!"); std::string_view=
=20
> >> sv{s}; sv; }));=20
> >>=20
> >> So, in this case, we have a local variable. Here, it depends on the=20
> >> rules you define for the temporaries. For instance, if follow GNU's=20
> >> extension rules for statement expressions=20
> >> (https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html), then:=20
> >>=20
> >> """=20
> >> In a statement expression, any temporaries created within a=20
> >> statement are destroyed at that statement=E2=80=99s end. This makes st=
atement=20
> >> expressions inside macros slightly different from function calls. In=
=20
> >> the latter case temporaries introduced during argument evaluation are=
=20
> >> destroyed at the end of the statement that includes the function call.=
=20
> >> In the statement expression case they are destroyed during the=20
> >> statement expression. For instance,=20
> >> #define macro(a) ({__typeof__(a) b =3D (a); b + 3; })=20
> >> template<typename T> T function(T a) { T b =3D a; return b + 3; }=20
> >>=20
> >> void foo ()=20
> >> {=20
> >> macro (X ());=20
> >> function (X ());=20
> >> }=20
> >>=20
> >> has different places where temporaries are destroyed. For the macro=
=20
> >> case, the temporary X is destroyed just after the initialization of b.=
=20
> >> In the function case that temporary is destroyed when the function=20
> >> returns.=20
> >> """=20
> >>=20
> >> ...it would mean that "s" is destroyed before "print" is called.=20
> >> Simple as well; and again, it wouldn't work either. This would make it=
=20
> >> different to a normal function call, where the argument would live=20
> >> until the end of the "outer" statement, i.e. after the print.=20
> >>=20
> >> So, the lifetime rules do not seem complex to understand. The=20
> >> confusion comes, I think, because you are trying to use the parametric=
=20
> >> expressions as if it was a "lazy" argument;=20
> >=20
> >=20
> > Yes, that's exactly what I'm trying to do, in order to show you that th=
e=20
> rules of parametric expressions are not enough to implement properly lazy=
=20
> parameters.=20
> >=20
>
> I am not sure how you reach that conclusion. I am confused now.=20
>
> >>=20
> >> while what you would have=20
> >> to do is code the "print" itself as the parametric expression.=20
> >=20
> >=20
> > With this example, yes. But this example is here only to show what kind=
=20
> of lifetime problems we can have with lazy parameters.=20
> > Those problems are solvable with the current lazy parameter design, but=
=20
> not with parametric expressions.=20
>
> Which problem? Parametric expressions cannot be used like in your=20
> "macro" example: you cannot return references to destroyed=20
> temporaries; same as in "normal" code. I am unsure what is the problem=20
> here. That does not mean they cannot be used to implement lazy=20
> parameters (or similar stuff).=20
>
Look at the example again: with the eager function (no lambda, no lazy=20
parameter, no marcro), there is no dangling reference.
The lifetime of the string is extended until the end of the print function.
We want the same behavior with the lazy parameter variant (and it is=20
possible as I explained way before in this thread).
But this is not possible with parametric expressions (nor lambdas).
That's what I try to show you from the very start.
=20
>
> > That's why I consider lazy parameters is an independent proposal that=
=20
> should be pursued on its own, even if parametric expressions were already=
=20
> part of the language.=20
> >=20
> >>=20
> >> In other words, you wouldn't write "macro" and "print". Instead, you=
=20
> >> write "print" as a P.E. itself. For instance, the typical use case for=
=20
> >> the "using" parameters would be:=20
> >>=20
> >> using warn(using auto expr) {=20
> >> if (level >=3D warning)=20
> >> std::cout << expr << std::endl;=20
> >> }=20
> >>=20
> >> i.e. when you write:=20
> >>=20
> >> warn(very_expensive_function());=20
> >>=20
> >> very_expensive_function() would only be called whenever we are going=
=20
> >> to actually call it.=20
> >=20
> >=20
> > As I said, this example is not about how to implement a lazy print with=
=20
> either lazy parameters or parametric expressions,=20
> > but is a simple example showing what kind of lifetime issues we can=20
> encounter and we want to avoid (or not).=20
> > An implementation of lazy parameters should address these lifetime=20
> issues.=20
> >=20
>
> But what I asked was an example of what you cannot implement with=20
> PEs/macros that you can with lazy parameters.
My example is such an example (but it is a toy example).
If this toy example does not work as expected, then users will end up=20
unexpectidly with dangling references.
=20
> As shown, you can=20
> implement the "print with lazy parameter" using the PEs/macros, so I=20
> don't think that example is valid for this.=20
>
The problem is not with one function, but when you start chaining multiple=
=20
functions.
And that is exactly what this example shows.
=20
>
> > Also, I remembered another issue that lazy parameters solve and cannot=
=20
> be solve with parametric expressions:=20
> > struct Foo {=20
> > int a, b, c;=20
> > };=20
> >=20
> > std::vector<Foo> v;=20
> >=20
> > v.lazy_push_back({1, 2, 3});=20
> > v.macro_push_back(Foo{1, 2, 3});=20
> >=20
> > With parametric expressions, you would need to specify Foo at the call=
=20
> site, while the lazy parameter doesn't need it at the call site.=20
> > Lazy parameters don't work with expressions but with initializers.=20
>
> Why? You can do "v.macro_push_back({1, 2, 3});" and use the expression=20
> to initialize a Foo inside; with both the PE or the macro-like PE=20
> approaches. I am not sure I understand. Even if it was not possible,=20
> you could simply allow for non-auto parameters in the PE proposal=20
> (i.e. allow to constraint the types of the parameters).=20
>
{1, 2, 3} is not an expression and does not work with parametric=20
expressions (because it is not an expression).
But it does work with lazy parameters as it is an initializer.
However, this last point might be fixable for parametric expressions, but=
=20
I'm not sure...
=20
>
> Anyway, even if it was impossible to accomplish and we had to write=20
> "Foo", I don't see how it is an issue.=20
Here it is fine to explicitly write the type name, but when the type name=
=20
is super long or even not known by the user, how do you do?
It is the same problem solved by auto.
=20
> It is still the case that the=20
> "macro-like PEs" are more general than lazy parameters (assuming=20
> access to the definition).=20
>
They are not more general, they are orthogonal.
You cannot implement every feature of lazy parameters with parametric=20
expressions as I showed.
There is a non-null intersection of features, I agree. But the interesting=
=20
bits are the non-overlapping features.
=20
>
> Again, I am not saying lazy parameters are undesirable, or that PEs=20
> solve everything. What I am saying is that, as a concept, lazy=20
> parameters can be implemented easily using macro-like "expression=20
> forwarding".
Yes, but it would be a poor implementation of lazy parameters that lacks=20
the important points I showed you.
=20
> Regardless of how we implement each of the them, that is=20
> still true. Which is why, if we could get "expression forwarding", we=20
> have already solved the lazy parameter problem; so I think it is worth=20
> considering if "expression forwarding" can be done first.=20
>
No, as I showed you, "expression forwarding" is not enough to properly=20
implement lazy parameters as it does not extend the lifetime of the=20
temporaries to match the lifetime of temporaries with regular parameters.
This is a crucial point.
--=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/86264f55-8474-4c43-8658-5331a58eb62d%40isocpp.or=
g.
------=_Part_1527_830733094.1539613662157
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>Le lundi 15 octobre 2018 15:52:24 UTC+2, Miguel Ojeda =
a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"> On Mon, Oc=
t 15, 2018 at 3:17 PM <<a href=3D"javascript:" target=3D"_blank" gdf-obf=
uscated-mailto=3D"k-zGJbFYBAAJ" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'javascript:';return true;" onclick=3D"this.href=3D'javascri=
pt:';return true;">floria...@gmail.com</a>> wrote:
<br>>
<br>>
<br>> Le lundi 15 octobre 2018 14:20:38 UTC+2, Miguel Ojeda a =C3=A9crit=
:
<br>>>
<br>>> If we are discussing the macro-like case, you need to use the =
"using"
<br>>> parameters, i.e.
<br>>>
<br>>> =C2=A0 using macro(using auto s) {
<br>>> =C2=A0 =C2=A0 std::string_view sv{s};
<br>>> =C2=A0 =C2=A0 return sv;
<br>>> =C2=A0 }
<br>>>
<br>>> Which means that would expand into something like:
<br>>>
<br>>> =C2=A0 print(({std::string_view sv{std::string("hello wor=
ld!")}; sv;}));
<br>>>
<br>>> Which would mean the temporary is destroyed, as usual, at the =
end of
<br>>> the "std::string_view sv{std::string("hello world!&q=
uot;)};" statement.
<br>>> Simple, no? And, of course, it wouldn't work.
<br>>>
<br>>> If you are talking about the "normal" parametric exp=
ressions, i.e.
<br>>> without "using", it would expand into something like=
:
<br>>>
<br>>> =C2=A0 print(({ auto&& s =3D std::string("hello w=
orld!"); std::string_view
<br>>> sv{s}; sv; }));
<br>>>
<br>>> So, in this case, we have a local variable. Here, it depends o=
n the
<br>>> rules you define for the temporaries. For instance, if follow =
GNU's
<br>>> extension rules for statement expressions
<br>>> (<a href=3D"https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs=
..html" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'h=
ttps://www.google.com/url?q\x3dhttps%3A%2F%2Fgcc.gnu.org%2Fonlinedocs%2Fgcc=
%2FStatement-Exprs.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFeEkwZYJk3H=
MqDHmVizd1_6WnSeA';return true;" onclick=3D"this.href=3D'https://ww=
w.google.com/url?q\x3dhttps%3A%2F%2Fgcc.gnu.org%2Fonlinedocs%2Fgcc%2FStatem=
ent-Exprs.html\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFeEkwZYJk3HMqDHmVizd=
1_6WnSeA';return true;">https://gcc.gnu.org/<wbr>onlinedocs/gcc/Stateme=
nt-<wbr>Exprs.html</a>), then:
<br>>>
<br>>> =C2=A0 """
<br>>> =C2=A0 In a statement expression, any temporaries created with=
in a
<br>>> statement are destroyed at that statement=E2=80=99s end. This =
makes statement
<br>>> expressions inside macros slightly different from function cal=
ls. In
<br>>> the latter case temporaries introduced during argument evaluat=
ion are
<br>>> destroyed at the end of the statement that includes the functi=
on call.
<br>>> In the statement expression case they are destroyed during the
<br>>> statement expression. For instance,
<br>>> =C2=A0 #define macro(a) =C2=A0({__typeof__(a) b =3D (a); b + 3=
; })
<br>>> =C2=A0 template<typename T> T function(T a) { T b =3D a;=
return b + 3; }
<br>>>
<br>>> =C2=A0 void foo ()
<br>>> =C2=A0 {
<br>>> =C2=A0 =C2=A0 macro (X ());
<br>>> =C2=A0 =C2=A0 function (X ());
<br>>> =C2=A0 }
<br>>>
<br>>> =C2=A0 has different places where temporaries are destroyed. F=
or the macro
<br>>> case, the temporary X is destroyed just after the initializati=
on of b.
<br>>> In the function case that temporary is destroyed when the func=
tion
<br>>> returns.
<br>>> =C2=A0 """
<br>>>
<br>>> ...it would mean that "s" is destroyed before "=
print" is called.
<br>>> Simple as well; and again, it wouldn't work either. This w=
ould make it
<br>>> different to a normal function call, where the argument would =
live
<br>>> until the end of the "outer" statement, i.e. after t=
he print.
<br>>>
<br>>> So, the lifetime rules do not seem complex to understand. The
<br>>> confusion comes, I think, because you are trying to use the pa=
rametric
<br>>> expressions as if it was a "lazy" argument;
<br>>
<br>>
<br>> Yes, that's exactly what I'm trying to do, in order to sho=
w you that the rules of parametric expressions are not enough to implement =
properly lazy parameters.
<br>>
<br>
<br>I am not sure how you reach that conclusion. I am confused now.
<br>
<br>>>
<br>>> while what you would have
<br>>> to do is code the "print" itself as the parametric e=
xpression.
<br>>
<br>>
<br>> With this example, yes. But this example is here only to show what=
kind of lifetime problems we can have with lazy parameters.
<br>> Those problems are solvable with the current lazy parameter design=
, but not with parametric expressions.
<br>
<br>Which problem? Parametric expressions cannot be used like in your
<br>"macro" example: you cannot return references to destroyed
<br>temporaries; same as in "normal" code. I am unsure what is th=
e problem
<br>here. That does not mean they cannot be used to implement lazy
<br>parameters (or similar stuff).
<br></blockquote><div><br></div><div>Look at the example again: with the ea=
ger function (no lambda, no lazy parameter, no marcro), there is no danglin=
g reference.</div><div>The lifetime of the string is extended until the end=
of the print function.</div><div>We want the same behavior with the lazy p=
arameter variant (and it is possible as I explained way before in this thre=
ad).</div><div>But this is not possible with parametric expressions (nor la=
mbdas).<br></div><div>That's what I try to show you from the very start=
..<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>> That's why I consider lazy parameters is an independent propos=
al that should be pursued on its own, even if parametric expressions were a=
lready part of the language.
<br>>
<br>>>
<br>>> In other words, you wouldn't write "macro" and &=
quot;print". Instead, you
<br>>> write "print" as a P.E. itself. For instance, the ty=
pical use case for
<br>>> the "using" parameters would be:
<br>>>
<br>>> =C2=A0 =C2=A0 using warn(using auto expr) {
<br>>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (level >=3D warning)
<br>>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 std::cout << e=
xpr << std::endl;
<br>>> =C2=A0 =C2=A0 }
<br>>>
<br>>> i.e. when you write:
<br>>>
<br>>> =C2=A0 =C2=A0 warn(very_expensive_function()<wbr>);
<br>>>
<br>>> very_expensive_function() would only be called whenever we are=
going
<br>>> to actually call it.
<br>>
<br>>
<br>> As I said, this example is not about how to implement a lazy print=
with either lazy parameters or parametric expressions,
<br>> but is a simple example showing what kind of lifetime issues we ca=
n encounter and we want to avoid (or not).
<br>> An implementation of lazy parameters should address these lifetime=
issues.
<br>>
<br>
<br>But what I asked was an example of what you cannot implement with
<br>PEs/macros that you can with lazy parameters.</blockquote><div><br></di=
v><div>My example is such an example (but it is a toy example).</div><div>I=
f this toy example does not work as expected, then users will end up unexpe=
ctidly with dangling references.<br></div><div>=C2=A0</div><blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #c=
cc solid;padding-left: 1ex;">As shown, you can
<br>implement the "print with lazy parameter" using the PEs/macro=
s, so I
<br>don't think that example is valid for this.
<br></blockquote><div><br></div><div>The problem is not with one function, =
but when you start chaining multiple functions.</div><div>And that is exact=
ly what this example shows.<br></div><div>=C2=A0</div><blockquote class=3D"=
gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc so=
lid;padding-left: 1ex;">
<br>> Also, I remembered another issue that lazy parameters solve and ca=
nnot be solve with parametric expressions:
<br>> struct Foo {
<br>> =C2=A0 int a, b, c;
<br>> };
<br>>
<br>> std::vector<Foo> v;
<br>>
<br>> v.lazy_push_back({1, 2, 3});
<br>> v.macro_push_back(Foo{1, 2, 3});
<br>>
<br>> With parametric expressions, you would need to specify Foo at the =
call site, while the lazy parameter doesn't need it at the call site.
<br>> Lazy parameters don't work with expressions but with initializ=
ers.
<br>
<br>Why? You can do "v.macro_push_back({1, 2, 3});" and use the e=
xpression
<br>to initialize a Foo inside; with both the PE or the macro-like PE
<br>approaches. I am not sure I understand. Even if it was not possible,
<br>you could simply allow for non-auto parameters in the PE proposal
<br>(i.e. allow to constraint the types of the parameters).
<br></blockquote><div><br></div><div>=C2=A0{1, 2, 3} is not an expression a=
nd does not work with parametric expressions (because it is not an expressi=
on).</div><div>But it does work with lazy parameters as it is an initialize=
r.</div><div><br></div><div>However, this last point might be fixable for p=
arametric expressions, but I'm not sure...<br></div><div>=C2=A0</div><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;">
<br>Anyway, even if it was impossible to accomplish and we had to write
<br>"Foo", I don't see how it is an issue. </blockquote><div>=
<br></div><div>Here it is fine to explicitly write the type name, but when =
the type name is super long or even not known by the user, how do you do?<b=
r></div><div>It is the same problem solved by auto.<br></div><div>=C2=A0</d=
iv><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;">It is still the case that t=
he
<br>"macro-like PEs" are more general than lazy parameters (assum=
ing
<br>access to the definition).
<br></blockquote><div><br></div><div>They are not more general, they are or=
thogonal.</div><div>You cannot implement every feature of lazy parameters w=
ith parametric expressions as I showed.</div><div>There is a non-null inter=
section of features, I agree. But the interesting bits are the non-overlapp=
ing features.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-le=
ft: 1ex;">
<br>Again, I am not saying lazy parameters are undesirable, or that PEs
<br>solve everything. What I am saying is that, as a concept, lazy
<br>parameters can be implemented easily using macro-like "expression
<br>forwarding".</blockquote><div><br></div><div>Yes, but it would be =
a poor implementation of lazy parameters that lacks the important points I =
showed you.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;">Regardless of how we implement each of the them, that is
<br>still true. Which is why, if we could get "expression forwarding&q=
uot;, we
<br>have already solved the lazy parameter problem; so I think it is worth
<br>considering if "expression forwarding" can be done first.
<br></blockquote><div><br></div><div>No, as I showed you, "expression =
forwarding" is not enough to properly implement lazy parameters as it =
does not extend the lifetime of the temporaries to match the lifetime of te=
mporaries with regular parameters.</div><div>This is a crucial point.<br></=
div><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/86264f55-8474-4c43-8658-5331a58eb62d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/86264f55-8474-4c43-8658-5331a58eb62d=
%40isocpp.org</a>.<br />
------=_Part_1527_830733094.1539613662157--
------=_Part_1526_632308035.1539613662156--
.
Author: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
Date: Mon, 15 Oct 2018 17:26:02 +0200
Raw View
On Mon, Oct 15, 2018 at 4:27 PM <florian.csdt@gmail.com> wrote:
>
> Le lundi 15 octobre 2018 15:52:24 UTC+2, Miguel Ojeda a =C3=A9crit :
>>
>> Which problem? Parametric expressions cannot be used like in your
>> "macro" example: you cannot return references to destroyed
>> temporaries; same as in "normal" code. I am unsure what is the problem
>> here. That does not mean they cannot be used to implement lazy
>> parameters (or similar stuff).
>
> Look at the example again: with the eager function (no lambda, no lazy pa=
rameter, no marcro), there is no dangling reference.
> The lifetime of the string is extended until the end of the print functio=
n.
Yes, because C++ guarantees that.
> We want the same behavior with the lazy parameter variant (and it is poss=
ible as I explained way before in this thread).
> But this is not possible with parametric expressions (nor lambdas).
My example picked GCC's expression statement rules as an example only.
You could say all temporaries live until the end of the full
expression.
>> But what I asked was an example of what you cannot implement with
>> PEs/macros that you can with lazy parameters.
>
>
> My example is such an example (but it is a toy example).
No, it isn't. Your example compares lazy arguments to a misuse of PEs.
That does not prove that PEs/macros cannot be used to emulate lazy
parameters.
> If this toy example does not work as expected, then users will end up une=
xpectidly with dangling references.
Why? This is the same as using a function that returns a reference to
a local variable.
>> As shown, you can
>> implement the "print with lazy parameter" using the PEs/macros, so I
>> don't think that example is valid for this.
>
>
> The problem is not with one function, but when you start chaining multipl=
e functions.
> And that is exactly what this example shows.
But what is the problem? AFAIK, we have not defined where temporaries
die yet in PEs.
>> Why? You can do "v.macro_push_back({1, 2, 3});" and use the expression
>> to initialize a Foo inside; with both the PE or the macro-like PE
>> approaches. I am not sure I understand. Even if it was not possible,
>> you could simply allow for non-auto parameters in the PE proposal
>> (i.e. allow to constraint the types of the parameters).
>
>
> {1, 2, 3} is not an expression and does not work with parametric express=
ions (because it is not an expression).
> But it does work with lazy parameters as it is an initializer.
>
> However, this last point might be fixable for parametric expressions, but=
I'm not sure...
I am simply trying to discuss the idea of forwarding expressions vs.
lazy parameters, not a single proposal. You could say you allow
expr-or-braced-init-list there, for instance, or whatever is required.
Even if the grammar wouldn't allow for it, it does not mean you want
to have both lazy arguments and PEs just to be able to do every single
thing possible. That only leads to an even more complex language.
>> It is still the case that the
>> "macro-like PEs" are more general than lazy parameters (assuming
>> access to the definition).
>
>
> They are not more general, they are orthogonal.
> You cannot implement every feature of lazy parameters with parametric exp=
ressions as I showed.
I still have not seen a compelling example, sorry. Chaining functions
may be it, but we would need to see where we would use such a thing,
and how it cannot be done with PEs properly.
> There is a non-null intersection of features, I agree. But the interestin=
g bits are the non-overlapping features.
Maybe, but again, one has to balance language complexity vs.
usefulness. On top of that, let's not forget that we have already
lambdas.
>> Again, I am not saying lazy parameters are undesirable, or that PEs
>> solve everything. What I am saying is that, as a concept, lazy
>> parameters can be implemented easily using macro-like "expression
>> forwarding".
>
>
> Yes, but it would be a poor implementation of lazy parameters that lacks =
the important points I showed you.
Depends on your definition of "poor". If you can write a compelling
example for chaining calls with lazy parameters; then we can try to
see if it is possible (or not) to do it with PEs properly.
>
>>
>> Regardless of how we implement each of the them, that is
>> still true. Which is why, if we could get "expression forwarding", we
>> have already solved the lazy parameter problem; so I think it is worth
>> considering if "expression forwarding" can be done first.
>
>
> No, as I showed you, "expression forwarding" is not enough to properly im=
plement lazy parameters as it does not extend the lifetime of the temporari=
es to match the lifetime of temporaries with regular parameters.
> This is a crucial point.
I have shown you how to implement lazy parameters using expression
forwarding: temporaries there are not an issue (for this case, but
maybe you can show a chaining example where it is an issue indeed).
Cheers,
Miguel
--=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/CANiq72%3DwtwEyvE8uaXA26FC%3DNvujkAgSXMYYc83YHN7=
OkJjZmQ%40mail.gmail.com.
.
Author: florian.csdt@gmail.com
Date: Mon, 15 Oct 2018 09:17:14 -0700 (PDT)
Raw View
------=_Part_1652_1607796260.1539620234921
Content-Type: multipart/alternative;
boundary="----=_Part_1653_1384530189.1539620234921"
------=_Part_1653_1384530189.1539620234921
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le lundi 15 octobre 2018 17:26:16 UTC+2, Miguel Ojeda a =C3=A9crit :
>
> On Mon, Oct 15, 2018 at 4:27 PM <floria...@gmail.com <javascript:>>=20
> wrote:=20
> >=20
> > Le lundi 15 octobre 2018 15:52:24 UTC+2, Miguel Ojeda a =C3=A9crit :=20
> >>=20
> >> Which problem? Parametric expressions cannot be used like in your=20
> >> "macro" example: you cannot return references to destroyed=20
> >> temporaries; same as in "normal" code. I am unsure what is the problem=
=20
> >> here. That does not mean they cannot be used to implement lazy=20
> >> parameters (or similar stuff).=20
> >=20
> > Look at the example again: with the eager function (no lambda, no lazy=
=20
> parameter, no marcro), there is no dangling reference.=20
> > The lifetime of the string is extended until the end of the print=20
> function.=20
>
> Yes, because C++ guarantees that.=20
>
And that's exactly the kind of guarantees I want for lazy parameters.
=20
>
> > We want the same behavior with the lazy parameter variant (and it is=20
> possible as I explained way before in this thread).=20
> > But this is not possible with parametric expressions (nor lambdas).=20
>
> My example picked GCC's expression statement rules as an example only.=20
> You could say all temporaries live until the end of the full=20
> expression.=20
>
Indeed, we could make all the temporaries live until the end of the full=20
expression. And that's a possibilty I already expressed.
But you explicitly said that we don't need it for "macros".
Either you say we don't have special lifetime rules for "macros"; or you=20
say we can have such special rules.
If "macros" can have such special rules, then my biggest problem with=20
implemeting lazy parameters with parametric expressions would be lifted.
=20
>
> >> But what I asked was an example of what you cannot implement with=20
> >> PEs/macros that you can with lazy parameters.=20
> >=20
> >=20
> > My example is such an example (but it is a toy example).=20
>
> No, it isn't. Your example compares lazy arguments to a misuse of PEs.=20
> That does not prove that PEs/macros cannot be used to emulate lazy=20
> parameters.=20
>
std::string get_pattern(); // expensive
std::string_view pattern(bool use_pattern, [] -> std::string pattern) {
if (use_pattern) return pattern();
return " "; // empty pattern
}
std::string text =3D /* ... */;
bool use_pattern =3D /* ... */;
bool found =3D text.find(pattern(use_pattern, get_pattern())) !=3D std::str=
ing::
npos;
Is this example more realistic for you?
If that's the case, then you will see it has the same lifetime issues as=20
the previous one.
Also note that it might be desirable to put the definition of pattern in=20
another translation unit if the processing required when use_pattern is=20
false is expensive. Or maybe the computation of the condition is expensive.
=20
>
> > If this toy example does not work as expected, then users will end up=
=20
> unexpectidly with dangling references.=20
>
> Why? This is the same as using a function that returns a reference to=20
> a local variable.=20
>
Why? Because it works with non-lazy parameters. (and it can be made to work=
=20
with lay ones)
=20
>
> >> As shown, you can=20
> >> implement the "print with lazy parameter" using the PEs/macros, so I=
=20
> >> don't think that example is valid for this.=20
> >=20
> >=20
> > The problem is not with one function, but when you start chaining=20
> multiple functions.=20
> > And that is exactly what this example shows.=20
>
> But what is the problem? AFAIK, we have not defined where temporaries=20
> die yet in PEs.=20
>
Then why did you say that this example doesn't work with PEs?
=20
>
> >> Why? You can do "v.macro_push_back({1, 2, 3});" and use the expression=
=20
> >> to initialize a Foo inside; with both the PE or the macro-like PE=20
> >> approaches. I am not sure I understand. Even if it was not possible,=
=20
> >> you could simply allow for non-auto parameters in the PE proposal=20
> >> (i.e. allow to constraint the types of the parameters).=20
> >=20
> >=20
> > {1, 2, 3} is not an expression and does not work with parametric=20
> expressions (because it is not an expression).=20
> > But it does work with lazy parameters as it is an initializer.=20
> >=20
> > However, this last point might be fixable for parametric expressions,=
=20
> but I'm not sure...=20
>
> I am simply trying to discuss the idea of forwarding expressions vs.=20
> lazy parameters, not a single proposal. You could say you allow=20
> expr-or-braced-init-list there, for instance, or whatever is required.=20
>
Yes, but this part is not in PE proposal.
You asked me what are the features of lazy parameters that are not=20
implementable with PEs, this is your answer.
=20
> Even if the grammar wouldn't allow for it, it does not mean you want=20
> to have both lazy arguments and PEs just to be able to do every single=20
> thing possible. That only leads to an even more complex language.=20
>
You still need to consider all the possibilities to know if it is good to=
=20
omit some use cases.
And that's exactly what I'm trying to do here: to show you what is not=20
possible (yet?) with PE but would be beneficial on their own.
=20
>
> >> It is still the case that the=20
> >> "macro-like PEs" are more general than lazy parameters (assuming=20
> >> access to the definition).=20
> >=20
> >=20
> > They are not more general, they are orthogonal.=20
> > You cannot implement every feature of lazy parameters with parametric=
=20
> expressions as I showed.=20
>
> I still have not seen a compelling example, sorry. Chaining functions=20
> may be it, but we would need to see where we would use such a thing,=20
> and how it cannot be done with PEs properly.=20
>
Those examples will come naturally when people will use those features.=20
Because they will compose macro-like code with regular code.
=20
>
> > There is a non-null intersection of features, I agree. But the=20
> interesting bits are the non-overlapping features.=20
>
> Maybe, but again, one has to balance language complexity vs.=20
> usefulness.
Then, why do you ask what cannot be implemented with PE?
This balance question comes after you have identified the differences.
=20
> On top of that, let's not forget that we have already=20
> lambdas.=20
>
Lambdas are nowhere good to implement lazy parameters. First, they don't=20
have these desirable lifetime rules (and never will).
Then they lead to code bloat.
They have more problems detailed in the=20
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0927r2.pdf
=20
>
> >> Again, I am not saying lazy parameters are undesirable, or that PEs=20
> >> solve everything. What I am saying is that, as a concept, lazy=20
> >> parameters can be implemented easily using macro-like "expression=20
> >> forwarding".=20
> >=20
> >=20
> > Yes, but it would be a poor implementation of lazy parameters that lack=
s=20
> the important points I showed you.=20
>
> Depends on your definition of "poor". If you can write a compelling=20
> example for chaining calls with lazy parameters; then we can try to=20
> see if it is possible (or not) to do it with PEs properly.=20
>
See the example above.
=20
>
> >=20
> >>=20
> >> Regardless of how we implement each of the them, that is=20
> >> still true. Which is why, if we could get "expression forwarding", we=
=20
> >> have already solved the lazy parameter problem; so I think it is worth=
=20
> >> considering if "expression forwarding" can be done first.=20
> >=20
> >=20
> > No, as I showed you, "expression forwarding" is not enough to properly=
=20
> implement lazy parameters as it does not extend the lifetime of the=20
> temporaries to match the lifetime of temporaries with regular parameters.=
=20
> > This is a crucial point.=20
>
> I have shown you how to implement lazy parameters using expression=20
> forwarding: temporaries there are not an issue (for this case, but=20
> maybe you can show a chaining example where it is an issue indeed).=20
>
>
Those issues will arise with people using the feature. Because they will=20
try to use it like if it behaves like non-lazy ones.
It is easy to tell someone that the lazy argument might not be evaluated,=
=20
but it will be much more difficult to tell them that if it is evaluated, it=
=20
might have dangling references while the non-lazy doesn't.
--=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/296c7f67-fc11-4c18-92d1-f1f9c360a45c%40isocpp.or=
g.
------=_Part_1653_1384530189.1539620234921
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Le lundi 15 octobre 2018 17:26:16 UTC+2, Miguel Ojeda a =
=C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Mon, Oct 1=
5, 2018 at 4:27 PM <<a href=3D"javascript:" target=3D"_blank" gdf-obfusc=
ated-mailto=3D"hY3kPtBdBAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D&#=
39;javascript:';return true;" onclick=3D"this.href=3D'javascript:&#=
39;;return true;">floria...@gmail.com</a>> wrote:
<br>>
<br>> Le lundi 15 octobre 2018 15:52:24 UTC+2, Miguel Ojeda a =C3=A9crit=
:
<br>>>
<br>>> Which problem? Parametric expressions cannot be used like in y=
our
<br>>> "macro" example: you cannot return references to des=
troyed
<br>>> temporaries; same as in "normal" code. I am unsure w=
hat is the problem
<br>>> here. That does not mean they cannot be used to implement lazy
<br>>> parameters (or similar stuff).
<br>>
<br>> Look at the example again: with the eager function (no lambda, no =
lazy parameter, no marcro), there is no dangling reference.
<br>> The lifetime of the string is extended until the end of the print =
function.
<br>
<br>Yes, because C++ guarantees that.
<br></blockquote><div><br></div><div>And that's exactly the kind of gua=
rantees I want for lazy parameters.<br></div><div>=C2=A0</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
#ccc solid;padding-left: 1ex;">
<br>> We want the same behavior with the lazy parameter variant (and it =
is possible as I explained way before in this thread).
<br>> But this is not possible with parametric expressions (nor lambdas)=
..
<br>
<br>My example picked GCC's expression statement rules as an example on=
ly.
<br>You could say all temporaries live until the end of the full
<br>expression.
<br></blockquote><div><br></div><div>Indeed, we could make all the temporar=
ies live until the end of the full expression. And that's a possibilty =
I already expressed.</div><div>But you explicitly said that we don't ne=
ed it for "macros".</div><div>Either you say we don't have sp=
ecial lifetime rules for "macros"; or you say we can have such sp=
ecial rules.</div><div>If "macros" can have such special rules, t=
hen my biggest problem with implemeting lazy parameters with parametric exp=
ressions would be lifted.<br></div><div>=C2=A0</div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;">
<br>>> But what I asked was an example of what you cannot implement w=
ith
<br>>> PEs/macros that you can with lazy parameters.
<br>>
<br>>
<br>> My example is such an example (but it is a toy example).
<br>
<br>No, it isn't. Your example compares lazy arguments to a misuse of P=
Es.
<br>That does not prove that PEs/macros cannot be used to emulate lazy
<br>parameters.
<br></blockquote><div><br></div><div><div style=3D"background-color: rgb(25=
0, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; border=
-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><code class=
=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #000;"=
class=3D"styled-by-prettify">std</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">::</span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">string</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> get_pattern</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">//=
expensive</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br>std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">string_view=
pattern</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">bool</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> use_pattern</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">[]</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"> std</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">::</span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">string</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> pattern</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 styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">if</span><span style=3D"co=
lor: #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">use_pattern</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">return</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> pattern</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 </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=
><span style=3D"color: #080;" class=3D"styled-by-prettify">" "</s=
pan><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">// empty pattern</span><span st=
yle=3D"color: #000;" class=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><br>std</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">string</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> text </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-pretti=
fy">/* ... */</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">bool</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> use_pattern </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #800;" class=3D"styled-by-prettify">/* ... */</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br><br></span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">bool</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> found </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> text</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">find</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">pattern</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">use_pattern</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> get_pattern</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">()))</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">!=3D</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">::</span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">string</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
npos</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></di=
v></code></div><br>Is this example more realistic for you?</div><div>If tha=
t's the case, then you will see it has the same lifetime issues as the =
previous one.</div><div><br></div><div>Also note that it might be desirable=
to put the definition of pattern in another translation unit if the proces=
sing required when use_pattern is false is expensive. Or maybe the computat=
ion of the condition is expensive.<br></div><div>=C2=A0</div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px =
#ccc solid;padding-left: 1ex;">
<br>> If this toy example does not work as expected, then users will end=
up unexpectidly with dangling references.
<br>
<br>Why? This is the same as using a function that returns a reference to
<br>a local variable.
<br></blockquote><div><br></div><div>Why? Because it works with non-lazy pa=
rameters. (and it can be made to work with lay ones)</div><div>=C2=A0</div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;">
<br>>> As shown, you can
<br>>> implement the "print with lazy parameter" using the =
PEs/macros, so I
<br>>> don't think that example is valid for this.
<br>>
<br>>
<br>> The problem is not with one function, but when you start chaining =
multiple functions.
<br>> And that is exactly what this example shows.
<br>
<br>But what is the problem? AFAIK, we have not defined where temporaries
<br>die yet in PEs.
<br></blockquote><div><br></div><div>Then why did you say that this example=
doesn't work with PEs?<br></div><div>=C2=A0</div><blockquote class=3D"=
gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc so=
lid;padding-left: 1ex;">
<br>>> Why? You can do "v.macro_push_back({1, 2, 3});" and =
use the expression
<br>>> to initialize a Foo inside; with both the PE or the macro-like=
PE
<br>>> approaches. I am not sure I understand. Even if it was not pos=
sible,
<br>>> you could simply allow for non-auto parameters in the PE propo=
sal
<br>>> (i.e. allow to constraint the types of the parameters).
<br>>
<br>>
<br>> =C2=A0{1, 2, 3} is not an expression and does not work with parame=
tric expressions (because it is not an expression).
<br>> But it does work with lazy parameters as it is an initializer.
<br>>
<br>> However, this last point might be fixable for parametric expressio=
ns, but I'm not sure...
<br>
<br>I am simply trying to discuss the idea of forwarding expressions vs.
<br>lazy parameters, not a single proposal. You could say you allow
<br>expr-or-braced-init-list there, for instance, or whatever is required.
<br></blockquote><div><br></div><div>Yes, but this part is not in PE propos=
al.</div><div>You asked me what are the features of lazy parameters that ar=
e not implementable with PEs, this is your answer.</div><div>=C2=A0</div><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;">Even if the grammar wouldn't=
allow for it, it does not mean you want
<br>to have both lazy arguments and PEs just to be able to do every single
<br>thing possible. That only leads to an even more complex language.
<br></blockquote><div><br></div><div>You still need to consider all the pos=
sibilities to know if it is good to omit some use cases.</div><div>And that=
's exactly what I'm trying to do here: to show you what is not poss=
ible (yet?) with PE but would be beneficial on their own.<br></div><div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>>> It is still the case that the
<br>>> "macro-like PEs" are more general than lazy paramete=
rs (assuming
<br>>> access to the definition).
<br>>
<br>>
<br>> They are not more general, they are orthogonal.
<br>> You cannot implement every feature of lazy parameters with paramet=
ric expressions as I showed.
<br>
<br>I still have not seen a compelling example, sorry. Chaining functions
<br>may be it, but we would need to see where we would use such a thing,
<br>and how it cannot be done with PEs properly.
<br></blockquote><div><br></div><div>Those examples will come naturally whe=
n people will use those features. Because they will compose macro-like code=
with regular code.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;">
<br>> There is a non-null intersection of features, I agree. But the int=
eresting bits are the non-overlapping features.
<br>
<br>Maybe, but again, one has to balance language complexity vs.
<br>usefulness.</blockquote><div><br></div><div>Then, why do you ask what c=
annot be implemented with PE?</div><div>This balance question comes after y=
ou have identified the differences.<br></div><div>=C2=A0</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
#ccc solid;padding-left: 1ex;">On top of that, let's not forget that w=
e have already
<br>lambdas.
<br></blockquote><div><br></div><div>Lambdas are nowhere good to implement =
lazy parameters. First, they don't have these desirable lifetime rules =
(and never will).</div><div>Then they lead to code bloat.</div><div>They ha=
ve more problems detailed in the <a href=3D"http://www.open-std.org/jtc1/sc=
22/wg21/docs/papers/2018/p0927r2.pdf">http://www.open-std.org/jtc1/sc22/wg2=
1/docs/papers/2018/p0927r2.pdf</a></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;">
<br>>> Again, I am not saying lazy parameters are undesirable, or tha=
t PEs
<br>>> solve everything. What I am saying is that, as a concept, lazy
<br>>> parameters can be implemented easily using macro-like "ex=
pression
<br>>> forwarding".
<br>>
<br>>
<br>> Yes, but it would be a poor implementation of lazy parameters that=
lacks the important points I showed you.
<br>
<br>Depends on your definition of "poor". If you can write a comp=
elling
<br>example for chaining calls with lazy parameters; then we can try to
<br>see if it is possible (or not) to do it with PEs properly.
<br></blockquote><div><br></div><div>See the example above.<br></div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>>
<br>>>
<br>>> Regardless of how we implement each of the them, that is
<br>>> still true. Which is why, if we could get "expression for=
warding", we
<br>>> have already solved the lazy parameter problem; so I think it =
is worth
<br>>> considering if "expression forwarding" can be done f=
irst.
<br>>
<br>>
<br>> No, as I showed you, "expression forwarding" is not enou=
gh to properly implement lazy parameters as it does not extend the lifetime=
of the temporaries to match the lifetime of temporaries with regular param=
eters.
<br>> This is a crucial point.
<br>
<br>I have shown you how to implement lazy parameters using expression
<br>forwarding: temporaries there are not an issue (for this case, but
<br>maybe you can show a chaining example where it is an issue indeed).
<br>
<br></blockquote><div><br></div><div>Those issues will arise with people us=
ing the feature. Because they will try to use it like if it behaves like no=
n-lazy ones.</div><div>It is easy to tell someone that the lazy argument mi=
ght not be evaluated, but it will be much more difficult to tell them that =
if it is evaluated, it might have dangling references while the non-lazy do=
esn't.<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/296c7f67-fc11-4c18-92d1-f1f9c360a45c%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/296c7f67-fc11-4c18-92d1-f1f9c360a45c=
%40isocpp.org</a>.<br />
------=_Part_1653_1384530189.1539620234921--
------=_Part_1652_1607796260.1539620234921--
.
Author: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
Date: Mon, 15 Oct 2018 20:16:47 +0200
Raw View
[Cut parts of the email to try to shorten the replies -- please put
them back if you think they are not a repetition of the discussion]
On Mon, Oct 15, 2018 at 6:17 PM <florian.csdt@gmail.com> wrote:
>
> Le lundi 15 octobre 2018 17:26:16 UTC+2, Miguel Ojeda a =C3=A9crit :
>>
>> My example picked GCC's expression statement rules as an example only.
>> You could say all temporaries live until the end of the full
>> expression.
>
>
> Indeed, we could make all the temporaries live until the end of the full =
expression. And that's a possibilty I already expressed.
> But you explicitly said that we don't need it for "macros".
We don't need it to implement the "print" example you showed (as I
showed in my answer after that one), i.e. one of the main use cases of
"macros"/"expression forwarding" is precisely being able to implement
lazy arguments.
> Either you say we don't have special lifetime rules for "macros"; or you =
say we can have such special rules.
> If "macros" can have such special rules, then my biggest problem with imp=
lemeting lazy parameters with parametric expressions would be lifted.
I would be fine with both ways. Even if we do not have temporaries
living out of it, the above is still true.
>> No, it isn't. Your example compares lazy arguments to a misuse of PEs.
>> That does not prove that PEs/macros cannot be used to emulate lazy
>> parameters.
>
>
> std::string get_pattern(); // expensive
> std::string_view pattern(bool use_pattern, [] -> std::string pattern) {
> if (use_pattern) return pattern();
> return " "; // empty pattern
> }
>
> std::string text =3D /* ... */;
> bool use_pattern =3D /* ... */;
>
> bool found =3D text.find(pattern(use_pattern, get_pattern())) !=3D std::s=
tring::npos;
>
> Is this example more realistic for you?
> If that's the case, then you will see it has the same lifetime issues as =
the previous one.
First of all: I would say "pattern" is an anti-pattern :-) You are
always returning a reference to a temporary. There is no way to use
safely that function except if used to pass the result into another
one in the same statement, which makes it very dangerous to use (even
worse than local temporaries being destroyed, like in normal functions
or, maybe, PEs). Even std::min/max behave slightly better: they *may*
return a temporary (which is a well-known pitfall), but in your case,
you *always* return a temporary. Unless I am misunderstanding
something, of course.
Now, having said that, the equivalent:
using pattern(using auto use_pattern, using auto pattern) {
if (use_pattern) return pattern;
return " ";
}
expands to something like:
bool found =3D text.find(({
if (use_pattern) return get_pattern();
return " ";
})) !=3D std::string::npos;
Which should not have any problem with temporaries, because AFAIU,
this should be "returning" an std::string by value out of the "block"
(or however we call it). In my view, it should work the same way as if
you compile this:
bool found =3D text.find(({
use_pattern ? get_pattern() : " ";
})) !=3D std::string::npos;
using GCC/clang's statement expressions. See:
"""
In G++, the result value of a statement expression undergoes array
and function pointer decay, and is returned by value to the enclosing
expression. For instance, if A is a class, then
A a;
({a;}).Foo ()
constructs a temporary A object to hold the result of the statement
expression, and that is used to invoke Foo. Therefore the this pointer
observed by Foo is not the address of a.
""
So, actually, the macro-like approach is safer, because it returns
std::string by value (the same type that was passed in).
> Also note that it might be desirable to put the definition of pattern in =
another translation unit if the processing required when use_pattern is fal=
se is expensive. Or maybe the computation of the condition is expensive.
Sure, we already covered that.
>> Why? This is the same as using a function that returns a reference to
>> a local variable.
>
>
> Why? Because it works with non-lazy parameters. (and it can be made to wo=
rk with lay ones)
>
See above. (...)
>> But what is the problem? AFAIK, we have not defined where temporaries
>> die yet in PEs.
>
>
> Then why did you say that this example doesn't work with PEs?
I am lost. I am not sure what do you mean. The "print" example works
with PEs if you write "print" as a PE (as intended). If you insist on
using your definition of "print" + "macro", then you need the
temporaries to last until the end of the full expression.
>> I am simply trying to discuss the idea of forwarding expressions vs.
>> lazy parameters, not a single proposal. You could say you allow
>> expr-or-braced-init-list there, for instance, or whatever is required.
>
>
> Yes, but this part is not in PE proposal.
> You asked me what are the features of lazy parameters that are not implem=
entable with PEs, this is your answer.
See above (i.e. still we don't have a good example). (...)
>> Even if the grammar wouldn't allow for it, it does not mean you want
>> to have both lazy arguments and PEs just to be able to do every single
>> thing possible. That only leads to an even more complex language.
>
>
> You still need to consider all the possibilities to know if it is good to=
omit some use cases.
> And that's exactly what I'm trying to do here: to show you what is not po=
ssible (yet?) with PE but would be beneficial on their own.
See above. (...)
>> I still have not seen a compelling example, sorry. Chaining functions
>> may be it, but we would need to see where we would use such a thing,
>> and how it cannot be done with PEs properly.
>
>
> Those examples will come naturally when people will use those features. B=
ecause they will compose macro-like code with regular code.
Not so sure about that. I still don't know what kind of example are
you thinking that would be so dangerous.
>> Maybe, but again, one has to balance language complexity vs.
>> usefulness.
>
>
> Then, why do you ask what cannot be implemented with PE?
> This balance question comes after you have identified the differences.
Because that is the key difference, no? You say PEs and LA are
orthogonal, I say PEs (at least macro-like PEs, or something similar
to PEs, i.e. the general idea of forwarding expressions) are a
superset of LAs. If we cannot find an example of LAs which PEs cannot
do; then it isn't worth it to add *both* LAs and PEs.
> Those issues will arise with people using the feature. Because they will =
try to use it like if it behaves like non-lazy ones.
> It is easy to tell someone that the lazy argument might not be evaluated,=
but it will be much more difficult to tell them that if it is evaluated, i=
t might have dangling references while the non-lazy doesn't.
Currently in C++, you can also have dangling references when returning
by reference. This is not news, nor something surprising, in my
opinion. Even your example has them if the value is not fully used by
the end of the statement.
Cheers,
Miguel
--=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/CANiq72kqO9gOPPz6zStq89MguHG4EdmzEqXH52qhm_4XNat=
%2Big%40mail.gmail.com.
.
Author: florian.csdt@gmail.com
Date: Tue, 16 Oct 2018 02:38:10 -0700 (PDT)
Raw View
------=_Part_1986_303203399.1539682690304
Content-Type: multipart/alternative;
boundary="----=_Part_1987_333896840.1539682690305"
------=_Part_1987_333896840.1539682690305
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Le lundi 15 octobre 2018 20:17:01 UTC+2, Miguel Ojeda a =C3=A9crit :
>
> [Cut parts of the email to try to shorten the replies -- please put=20
> them back if you think they are not a repetition of the discussion]=20
>
> On Mon, Oct 15, 2018 at 6:17 PM <floria...@gmail.com <javascript:>>=20
> wrote:=20
> >=20
> > Le lundi 15 octobre 2018 17:26:16 UTC+2, Miguel Ojeda a =C3=A9crit :=20
> >>=20
> >> My example picked GCC's expression statement rules as an example only.=
=20
> >> You could say all temporaries live until the end of the full=20
> >> expression.=20
> >=20
> >=20
> > Indeed, we could make all the temporaries live until the end of the ful=
l=20
> expression. And that's a possibilty I already expressed.=20
> > But you explicitly said that we don't need it for "macros".=20
>
> We don't need it to implement the "print" example you showed (as I=20
> showed in my answer after that one), i.e. one of the main use cases of=20
> "macros"/"expression forwarding" is precisely being able to implement=20
> lazy arguments.=20
>
> > Either you say we don't have special lifetime rules for "macros"; or yo=
u=20
> say we can have such special rules.=20
> > If "macros" can have such special rules, then my biggest problem with=
=20
> implemeting lazy parameters with parametric expressions would be lifted.=
=20
>
> I would be fine with both ways. Even if we do not have temporaries=20
> living out of it, the above is still true.=20
>
> >> No, it isn't. Your example compares lazy arguments to a misuse of PEs.=
=20
> >> That does not prove that PEs/macros cannot be used to emulate lazy=20
> >> parameters.=20
> >=20
> >=20
> > std::string get_pattern(); // expensive=20
> > std::string_view pattern(bool use_pattern, [] -> std::string pattern) {=
=20
> > if (use_pattern) return pattern();=20
> > return " "; // empty pattern=20
> > }=20
> >=20
> > std::string text =3D /* ... */;=20
> > bool use_pattern =3D /* ... */;=20
> >=20
> > bool found =3D text.find(pattern(use_pattern, get_pattern())) !=3D=20
> std::string::npos;=20
> >=20
> > Is this example more realistic for you?=20
> > If that's the case, then you will see it has the same lifetime issues a=
s=20
> the previous one.=20
>
> First of all: I would say "pattern" is an anti-pattern :-) You are=20
> always returning a reference to a temporary. There is no way to use=20
> safely that function except if used to pass the result into another=20
> one in the same statement, which makes it very dangerous to use (even=20
> worse than local temporaries being destroyed, like in normal functions=20
> or, maybe, PEs). Even std::min/max behave slightly better: they *may*=20
> return a temporary (which is a well-known pitfall), but in your case,=20
> you *always* return a temporary. Unless I am misunderstanding=20
> something, of course.=20
>
The core of this example is: if you don't use lazy parameters (or PE) and=
=20
just use regular parameter, it just works.
What I'm saying is: lazy parameters should behave in the same way in that=
=20
respect:
If a code works with regular parameters (with no side effect), it should=20
also work with lazy parameters.
And that example is such an example.
=20
>
> Now, having said that, the equivalent:=20
>
> using pattern(using auto use_pattern, using auto pattern) {=20
> if (use_pattern) return pattern;=20
> return " ";=20
> }=20
>
> expands to something like:=20
>
> bool found =3D text.find(({=20
> if (use_pattern) return get_pattern();=20
> return " ";=20
> })) !=3D std::string::npos;=20
>
> Which should not have any problem with temporaries, because AFAIU,=20
> this should be "returning" an std::string by value out of the "block"=20
> (or however we call it). In my view, it should work the same way as if=20
> you compile this:=20
>
> bool found =3D text.find(({=20
> use_pattern ? get_pattern() : " ";=20
> })) !=3D std::string::npos;=20
>
> using GCC/clang's statement expressions. See:=20
>
> """=20
> In G++, the result value of a statement expression undergoes array=20
> and function pointer decay, and is returned by value to the enclosing=20
> expression. For instance, if A is a class, then=20
>
> A a;=20
> ({a;}).Foo ()=20
>
> constructs a temporary A object to hold the result of the statement=20
> expression, and that is used to invoke Foo. Therefore the this pointer=20
> observed by Foo is not the address of a.=20
> ""=20
>
> So, actually, the macro-like approach is safer, because it returns=20
> std::string by value (the same type that was passed in).=20
>
Which is not equivalent to the code I've written, because I don't create a=
=20
string from the "default/empty" pattern, but a string_view that does not=20
require any memory allocation.
=20
>
> > Also note that it might be desirable to put the definition of pattern i=
n=20
> another translation unit if the processing required when use_pattern is=
=20
> false is expensive. Or maybe the computation of the condition is expensiv=
e.=20
>
> Sure, we already covered that.=20
>
> >> Why? This is the same as using a function that returns a reference to=
=20
> >> a local variable.=20
> >=20
> >=20
> > Why? Because it works with non-lazy parameters. (and it can be made to=
=20
> work with lay ones)=20
> >=20
>
> See above. (...)=20
>
> >> But what is the problem? AFAIK, we have not defined where temporaries=
=20
> >> die yet in PEs.=20
> >=20
> >=20
> > Then why did you say that this example doesn't work with PEs?=20
>
> I am lost. I am not sure what do you mean. The "print" example works=20
> with PEs if you write "print" as a PE (as intended). If you insist on=20
> using your definition of "print" + "macro", then you need the=20
> temporaries to last until the end of the full expression.=20
>
> >> I am simply trying to discuss the idea of forwarding expressions vs.=
=20
> >> lazy parameters, not a single proposal. You could say you allow=20
> >> expr-or-braced-init-list there, for instance, or whatever is required.=
=20
> >=20
> >=20
> > Yes, but this part is not in PE proposal.=20
> > You asked me what are the features of lazy parameters that are not=20
> implementable with PEs, this is your answer.=20
>
> See above (i.e. still we don't have a good example). (...)=20
>
> >> Even if the grammar wouldn't allow for it, it does not mean you want=
=20
> >> to have both lazy arguments and PEs just to be able to do every single=
=20
> >> thing possible. That only leads to an even more complex language.=20
> >=20
> >=20
> > You still need to consider all the possibilities to know if it is good=
=20
> to omit some use cases.=20
> > And that's exactly what I'm trying to do here: to show you what is not=
=20
> possible (yet?) with PE but would be beneficial on their own.=20
>
> See above. (...)=20
>
> >> I still have not seen a compelling example, sorry. Chaining functions=
=20
> >> may be it, but we would need to see where we would use such a thing,=
=20
> >> and how it cannot be done with PEs properly.=20
> >=20
> >=20
> > Those examples will come naturally when people will use those features.=
=20
> Because they will compose macro-like code with regular code.=20
>
> Not so sure about that. I still don't know what kind of example are=20
> you thinking that would be so dangerous.=20
>
As I said, the problem is that if a code with regular parameters (with no=
=20
side effects) works, people will expect that the same code with lazy=20
parameters also works.
I don't have any real example because nobody has written code with lazy=20
parameters yet.
But my example (with find pattern in a string) is sensible enough to show=
=20
it will happen.
=20
>
> >> Maybe, but again, one has to balance language complexity vs.=20
> >> usefulness.=20
> >=20
> >=20
> > Then, why do you ask what cannot be implemented with PE?=20
> > This balance question comes after you have identified the differences.=
=20
>
> Because that is the key difference, no? You say PEs and LA are=20
> orthogonal, I say PEs (at least macro-like PEs, or something similar=20
> to PEs, i.e. the general idea of forwarding expressions) are a=20
> superset of LAs. If we cannot find an example of LAs which PEs cannot=20
> do; then it isn't worth it to add *both* LAs and PEs.=20
>
What I mean is: the missing features to completely implement lazy=20
parameters are orthogonal to the current features of parametric expressions=
..
I never said we cannot extend parametric expressions further to implement=
=20
those, though.
=20
>
> > Those issues will arise with people using the feature. Because they wil=
l=20
> try to use it like if it behaves like non-lazy ones.=20
> > It is easy to tell someone that the lazy argument might not be=20
> evaluated, but it will be much more difficult to tell them that if it is=
=20
> evaluated, it might have dangling references while the non-lazy doesn't.=
=20
>
> Currently in C++, you can also have dangling references when returning=20
> by reference. This is not news, nor something surprising, in my=20
> opinion. Even your example has them if the value is not fully used by=20
> the end of the statement.=20
>
They are cases where returning a reference is fine. My point is: lazy=20
parameters should let those cases fine.
--=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/b52a1376-22b6-4aa3-95bb-ab83f5882d15%40isocpp.or=
g.
------=_Part_1987_333896840.1539682690305
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Le lundi 15 octobre 2018 20:17:01 UTC+2, Miguel Ojeda a =
=C3=A9crit=C2=A0:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">[Cut parts of=
the email to try to shorten the replies -- please put
<br>them back if you think they are not a repetition of the discussion]
<br>
<br>On Mon, Oct 15, 2018 at 6:17 PM <<a href=3D"javascript:" target=3D"_=
blank" gdf-obfuscated-mailto=3D"dYKqxiFnBAAJ" rel=3D"nofollow" onmousedown=
=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=3D=
'javascript:';return true;">floria...@gmail.com</a>> wrote:
<br>>
<br>> Le lundi 15 octobre 2018 17:26:16 UTC+2, Miguel Ojeda a =C3=A9crit=
:
<br>>>
<br>>> My example picked GCC's expression statement rules as an e=
xample only.
<br>>> You could say all temporaries live until the end of the full
<br>>> expression.
<br>>
<br>>
<br>> Indeed, we could make all the temporaries live until the end of th=
e full expression. And that's a possibilty I already expressed.
<br>> But you explicitly said that we don't need it for "macros=
".
<br>
<br>We don't need it to implement the "print" example you sho=
wed (as I
<br>showed in my answer after that one), i.e. one of the main use cases of
<br>"macros"/"expression forwarding" is precisely being=
able to implement
<br>lazy arguments.
<br>
<br>> Either you say we don't have special lifetime rules for "=
macros"; or you say we can have such special rules.
<br>> If "macros" can have such special rules, then my biggest=
problem with implemeting lazy parameters with parametric expressions would=
be lifted.
<br>
<br>I would be fine with both ways. Even if we do not have temporaries
<br>living out of it, the above is still true.
<br>
<br>>> No, it isn't. Your example compares lazy arguments to a mi=
suse of PEs.
<br>>> That does not prove that PEs/macros cannot be used to emulate =
lazy
<br>>> parameters.
<br>>
<br>>
<br>> std::string get_pattern(); // expensive
<br>> std::string_view pattern(bool use_pattern, [] -> std::string pa=
ttern) {
<br>> =C2=A0 if (use_pattern) return pattern();
<br>> =C2=A0 return " "; // empty pattern
<br>> }
<br>>
<br>> std::string text =3D /* ... */;
<br>> bool use_pattern =3D /* ... */;
<br>>
<br>> bool found =3D text.find(pattern(use_pattern, get_pattern())) !=3D=
std::string::npos;
<br>>
<br>> Is this example more realistic for you?
<br>> If that's the case, then you will see it has the same lifetime=
issues as the previous one.
<br>
<br>First of all: I would say "pattern" is an anti-pattern :-) Yo=
u are
<br>always returning a reference to a temporary. There is no way to use
<br>safely that function except if used to pass the result into another
<br>one in the same statement, which makes it very dangerous to use (even
<br>worse than local temporaries being destroyed, like in normal functions
<br>or, maybe, PEs). Even std::min/max behave slightly better: they *may*
<br>return a temporary (which is a well-known pitfall), but in your case,
<br>you *always* return a temporary. Unless I am misunderstanding
<br>something, of course.
<br></blockquote><div><br></div><div>The core of this example is: if you do=
n't use lazy parameters (or PE) and just use regular parameter, it just=
works.</div><div>What I'm saying is: lazy parameters should behave in =
the same way in that respect:</div><div>If a code works with regular parame=
ters (with no side effect), it should also work with lazy parameters.</div>=
<div>And that example is such an example.<br></div><div>=C2=A0</div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;">
<br>Now, having said that, the equivalent:
<br>
<br>=C2=A0 using pattern(using auto use_pattern, using auto pattern) {
<br>=C2=A0 =C2=A0 if (use_pattern) return pattern;
<br>=C2=A0 =C2=A0 return " ";
<br>=C2=A0 }
<br>
<br>expands to something like:
<br>
<br>=C2=A0 bool found =3D text.find(({
<br>=C2=A0 =C2=A0 if (use_pattern) return get_pattern();
<br>=C2=A0 =C2=A0 return " ";
<br>=C2=A0 })) !=3D std::string::npos;
<br>
<br>Which should not have any problem with temporaries, because AFAIU,
<br>this should be "returning" an std::string by value out of the=
"block"
<br>(or however we call it). In my view, it should work the same way as if
<br>you compile this:
<br>
<br>=C2=A0 bool found =3D text.find(({
<br>=C2=A0 =C2=A0 use_pattern ? get_pattern() : " ";
<br>=C2=A0 })) !=3D std::string::npos;
<br>
<br>using GCC/clang's statement expressions. See:
<br>
<br>=C2=A0 """
<br>=C2=A0 In G++, the result value of a statement expression undergoes arr=
ay
<br>and function pointer decay, and is returned by value to the enclosing
<br>expression. For instance, if A is a class, then
<br>
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 A a;
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 ({a;}).Foo ()
<br>
<br>=C2=A0 constructs a temporary A object to hold the result of the statem=
ent
<br>expression, and that is used to invoke Foo. Therefore the this pointer
<br>observed by Foo is not the address of a.
<br>=C2=A0 ""
<br>
<br>So, actually, the macro-like approach is safer, because it returns
<br>std::string by value (the same type that was passed in).
<br></blockquote><div><br></div><div>Which is not equivalent to the code I&=
#39;ve written, because I don't create a string from the "default/=
empty" pattern, but a string_view that does not require any memory all=
ocation.<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;">
<br>> Also note that it might be desirable to put the definition of patt=
ern in another translation unit if the processing required when use_pattern=
is false is expensive. Or maybe the computation of the condition is expens=
ive.
<br>
<br>Sure, we already covered that.
<br>
<br>>> Why? This is the same as using a function that returns a refer=
ence to
<br>>> a local variable.
<br>>
<br>>
<br>> Why? Because it works with non-lazy parameters. (and it can be mad=
e to work with lay ones)
<br>>
<br>
<br>See above. (...)
<br>
<br>>> But what is the problem? AFAIK, we have not defined where temp=
oraries
<br>>> die yet in PEs.
<br>>
<br>>
<br>> Then why did you say that this example doesn't work with PEs?
<br>
<br>I am lost. I am not sure what do you mean. The "print" exampl=
e works
<br>with PEs if you write "print" as a PE (as intended). If you i=
nsist on
<br>using your definition of "print" + "macro", then yo=
u need the
<br>temporaries to last until the end of the full expression.
<br>
<br>>> I am simply trying to discuss the idea of forwarding expressio=
ns vs.
<br>>> lazy parameters, not a single proposal. You could say you allo=
w
<br>>> expr-or-braced-init-list there, for instance, or whatever is r=
equired.
<br>>
<br>>
<br>> Yes, but this part is not in PE proposal.
<br>> You asked me what are the features of lazy parameters that are not=
implementable with PEs, this is your answer.
<br>
<br>See above (i.e. still we don't have a good example). (...)
<br>
<br>>> Even if the grammar wouldn't allow for it, it does not mea=
n you want
<br>>> to have both lazy arguments and PEs just to be able to do ever=
y single
<br>>> thing possible. That only leads to an even more complex langua=
ge.
<br>>
<br>>
<br>> You still need to consider all the possibilities to know if it is =
good to omit some use cases.
<br>> And that's exactly what I'm trying to do here: to show you=
what is not possible (yet?) with PE but would be beneficial on their own.
<br>
<br>See above. (...)
<br>
<br>>> I still have not seen a compelling example, sorry. Chaining fu=
nctions
<br>>> may be it, but we would need to see where we would use such a =
thing,
<br>>> and how it cannot be done with PEs properly.
<br>>
<br>>
<br>> Those examples will come naturally when people will use those feat=
ures. Because they will compose macro-like code with regular code.
<br>
<br>Not so sure about that. I still don't know what kind of example are
<br>you thinking that would be so dangerous.
<br></blockquote><div><br></div><div>As I said, the problem is that if a co=
de with regular parameters (with no side effects) works, people will expect=
that the same code with lazy parameters also works.</div><div>I don't =
have any real example because nobody has written code with lazy parameters =
yet.</div><div>But my example (with find pattern in a string) is sensible e=
nough to show it will happen.<br></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;">
<br>>> Maybe, but again, one has to balance language complexity vs.
<br>>> usefulness.
<br>>
<br>>
<br>> Then, why do you ask what cannot be implemented with PE?
<br>> This balance question comes after you have identified the differen=
ces.
<br>
<br>Because that is the key difference, no? You say PEs and LA are
<br>orthogonal, I say PEs (at least macro-like PEs, or something similar
<br>to PEs, i.e. the general idea of forwarding expressions) are a
<br>superset of LAs. If we cannot find an example of LAs which PEs cannot
<br>do; then it isn't worth it to add *both* LAs and PEs.
<br></blockquote><div><br></div><div>What I mean is: the missing features t=
o completely implement lazy parameters are orthogonal to the current featur=
es of parametric expressions.</div><div>I never said we cannot extend param=
etric expressions further to implement those, though.<br></div><div>=C2=A0<=
/div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>> Those issues will arise with people using the feature. Because the=
y will try to use it like if it behaves like non-lazy ones.
<br>> It is easy to tell someone that the lazy argument might not be eva=
luated, but it will be much more difficult to tell them that if it is evalu=
ated, it might have dangling references while the non-lazy doesn't.
<br>
<br>Currently in C++, you can also have dangling references when returning
<br>by reference. This is not news, nor something surprising, in my
<br>opinion. Even your example has them if the value is not fully used by
<br>the end of the statement.
<br></blockquote><div><br></div><div>They are cases where returning a refer=
ence is fine. My point is: lazy parameters should let those cases fine.<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/b52a1376-22b6-4aa3-95bb-ab83f5882d15%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b52a1376-22b6-4aa3-95bb-ab83f5882d15=
%40isocpp.org</a>.<br />
------=_Part_1987_333896840.1539682690305--
------=_Part_1986_303203399.1539682690304--
.
Author: Jason Rice <ricejasonf@gmail.com>
Date: Tue, 16 Oct 2018 09:31:15 -0700
Raw View
--000000000000d607d505785b1511
Content-Type: text/plain; charset="UTF-8"
There is an example of that here:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1221r0.html#using-parameters
I'm not sure what you mean by "right". Are you expecting the evaluation to
take place at the end of some IO operation? That would be a bit more
complex and it would require storing any values used in the input
expression.
On Tue, Oct 16, 2018 at 8:40 AM Matthew Woehlke <mwoehlke.floss@gmail.com>
wrote:
> On 11/10/2018 20.28, Miguel Ojeda wrote:
> > We also discussed laziness and "expression-parameters" in two more
> places:
> >
> >
> https://groups.google.com/a/isocpp.org/d/msg/std-proposals/jB5TIcRZeic/HV-y43WUAAAJ
> >
> https://groups.google.com/a/isocpp.org/d/msg/std-proposals/x5ucKwQI7Bc/y6iFvtQUBwAJ
> >
> > The way I see it is that lazy arguments (i.e. only evaluated once even
> > if they appear several times -- what P0927 describes) are simply a
> > sub-case of "expressions copy-pasting"/"macro-like" etc.; so less
> > flexible, and more complex to specify.
>
> How would you implement this with parametric expressions?
>
> maybe_log(cond) << expensive() << expensive();
>
> With lazy parameters, we have the possibility of doing this "right", by
> having the operator<< take a lazy RHS.
>
> --
> Matthew
>
> --
> 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/eff7e919-4bb2-9446-ffc5-213aeed00137%40gmail.com
> .
>
--
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/CANfsYuwqyw5gOfpDD44LySZ9Ghej-Ydz%3D4XKPx%3D9zZf-S0gR8A%40mail.gmail.com.
--000000000000d607d505785b1511
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div dir=3D"ltr">There is an example of that here: <a href=
=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1221r0.html#us=
ing-parameters">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p12=
21r0.html#using-parameters</a><br><br></div><div>I'm not sure what you =
mean by "right". Are you expecting the evaluation to take place a=
t the end of some IO operation? That would be a bit more complex and it wou=
ld require storing any values used in the input expression.<br></div></div>=
<br><div class=3D"gmail_quote"><div dir=3D"ltr">On Tue, Oct 16, 2018 at 8:4=
0 AM Matthew Woehlke <<a href=3D"mailto:mwoehlke.floss@gmail.com">mwoehl=
ke.floss@gmail.com</a>> wrote:<br></div><blockquote class=3D"gmail_quote=
" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">O=
n 11/10/2018 20.28, Miguel Ojeda wrote:<br>
> We also discussed laziness and "expression-parameters" in tw=
o more places:<br>
> <br>
>=C2=A0 =C2=A0<a href=3D"https://groups.google.com/a/isocpp.org/d/msg/st=
d-proposals/jB5TIcRZeic/HV-y43WUAAAJ" rel=3D"noreferrer" target=3D"_blank">=
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/jB5TIcRZeic/HV-y=
43WUAAAJ</a><br>
>=C2=A0 =C2=A0<a href=3D"https://groups.google.com/a/isocpp.org/d/msg/st=
d-proposals/x5ucKwQI7Bc/y6iFvtQUBwAJ" rel=3D"noreferrer" target=3D"_blank">=
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/x5ucKwQI7Bc/y6iF=
vtQUBwAJ</a><br>
> <br>
> The way I see it is that lazy arguments (i.e. only evaluated once even=
<br>
> if they appear several times -- what P0927 describes) are simply a<br>
> sub-case of "expressions copy-pasting"/"macro-like"=
; etc.; so less<br>
> flexible, and more complex to specify.<br>
<br>
How would you implement this with parametric expressions?<br>
<br>
=C2=A0 maybe_log(cond) << expensive() << expensive();<br>
<br>
With lazy parameters, we have the possibility of doing this "right&quo=
t;, by<br>
having the operator<< take a lazy RHS.<br>
<br>
-- <br>
Matthew<br>
<br>
-- <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%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">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/eff7e919-4bb2-9446-ffc5-213aeed00137%=
40gmail.com" rel=3D"noreferrer" target=3D"_blank">https://groups.google.com=
/a/isocpp.org/d/msgid/std-proposals/eff7e919-4bb2-9446-ffc5-213aeed00137%40=
gmail.com</a>.<br>
</blockquote></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/CANfsYuwqyw5gOfpDD44LySZ9Ghej-Ydz%3D4=
XKPx%3D9zZf-S0gR8A%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CANfsYuwqyw5g=
OfpDD44LySZ9Ghej-Ydz%3D4XKPx%3D9zZf-S0gR8A%40mail.gmail.com</a>.<br />
--000000000000d607d505785b1511--
.
Author: Jason Rice <ricejasonf@gmail.com>
Date: Tue, 16 Oct 2018 13:02:09 -0700
Raw View
--0000000000001db22105785e0842
Content-Type: text/plain; charset="UTF-8"
You're right. PE does not support overloads by design. The paper mentions
overlap with both LA and constexpr params in normal functions both of which
are meant to support overloading.
On Tue, Oct 16, 2018 at 10:20 AM Matthew Woehlke <mwoehlke.floss@gmail.com>
wrote:
> On 16/10/2018 12.31, Jason Rice wrote:
> > There is an example of that here:
> >
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1221r0.html#using-parameters
>
> Ah, I didn't know that supported operators. However...
>
> "Operator overloading is supported. (only as a member since ADL is not
> supported)"
>
> Does this mean I can't define new overloads if I am not the class
> author? If yes, that's... a problem. Or at least, it's something LA
> would (presumably) handle that PE doesn't.
>
> > I'm not sure what you mean by "right". Are you expecting the evaluation
> to
> > take place at the end of some IO operation?
>
> I'm expecting it to (potentially) not take place, period.
>
> --
> Matthew
>
> --
> 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/ff9c98b2-7ff5-4118-87e4-06a808adfe9e%40gmail.com
> .
>
--
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/CANfsYuysQaLNh7_4kFat6C7LNc2cwLnhzsJ14D4EjOZpL3cdSQ%40mail.gmail.com.
--0000000000001db22105785e0842
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">You're right. PE does not support overloads by design.=
The paper mentions overlap with both LA and constexpr params in normal fun=
ctions both of which are meant to support overloading.<br></div><br><div cl=
ass=3D"gmail_quote"><div dir=3D"ltr">On Tue, Oct 16, 2018 at 10:20 AM Matth=
ew Woehlke <<a href=3D"mailto:mwoehlke.floss@gmail.com">mwoehlke.floss@g=
mail.com</a>> wrote:<br></div><blockquote class=3D"gmail_quote" style=3D=
"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 16/10/20=
18 12.31, Jason Rice wrote:<br>
> There is an example of that here:<br>
> <a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p12=
21r0.html#using-parameters" rel=3D"noreferrer" target=3D"_blank">http://www=
..open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1221r0.html#using-parameters=
</a><br>
<br>
Ah, I didn't know that supported operators. However...<br>
<br>
=C2=A0 "Operator overloading is supported. (only as a member since ADL=
is not<br>
supported)"<br>
<br>
Does this mean I can't define new overloads if I am not the class<br>
author? If yes, that's... a problem. Or at least, it's something LA=
<br>
would (presumably) handle that PE doesn't.<br>
<br>
> I'm not sure what you mean by "right". Are you expecting=
the evaluation to<br>
> take place at the end of some IO operation?<br>
<br>
I'm expecting it to (potentially) not take place, period.<br>
<br>
-- <br>
Matthew<br>
<br>
-- <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%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">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/ff9c98b2-7ff5-4118-87e4-06a808adfe9e%=
40gmail.com" rel=3D"noreferrer" target=3D"_blank">https://groups.google.com=
/a/isocpp.org/d/msgid/std-proposals/ff9c98b2-7ff5-4118-87e4-06a808adfe9e%40=
gmail.com</a>.<br>
</blockquote></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/CANfsYuysQaLNh7_4kFat6C7LNc2cwLnhzsJ1=
4D4EjOZpL3cdSQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CANfsYuysQaLNh7_4=
kFat6C7LNc2cwLnhzsJ14D4EjOZpL3cdSQ%40mail.gmail.com</a>.<br />
--0000000000001db22105785e0842--
.