Topic: Generalized lambda captureturning values
Author: =?ISO-8859-1?Q?David_Rodr=EDguez_Ibeas?= <dibeas@ieee.org>
Date: Fri, 27 Dec 2013 14:26:00 -0500
Raw View
--001a11333c2276ae3e04ee8910c8
Content-Type: text/plain; charset=ISO-8859-1
Agree that you don't want to implicitly move. Consider the non-lambda
equivalent version:
struct X {
std::string msg;
X(const std::string& msg) : msg(msg) {}
std::string message() const {
return msg;
}
};
Would you move 'msg' in the 'message()' function call? Surely not. Lambdas
are not that different from that piece of code, among other things by
default the generated 'operator()' is 'const'. In your example you removed
that 'const' by making the lambda mutable, but this would also create
another source of confusion:
For 'mutable' lambdas it would move but for non-mutable ones it would copy
(there is no constructor taking 'std::string const &&'). I don't see that
this should be the default. For those use cases where it might make sense
(a lambda that is known to be evaluated only once...) you can always type
'std::move' in your code.
David
On Fri, Dec 27, 2013 at 1:45 PM, Cassio Neri <cassio.neri@gmail.com> wrote:
>
>
> On Friday, December 27, 2013 3:58:33 PM UTC-2, Mikhail Semenov wrote:
>
>> I have looked at the following code (A is the type of x and y):
>>
>> auto f1 = [x = std::move(x),&y]() mutable ->A
>> {
>> // some processing
>> *return std::move(x);* // should not the value be moved by
>> default here?
>> };
>>
>
> No, as Ville has explained.
>
> In addition, I disagree that an implicit move would be a good idea in this
> case because users can call f1 more than once and expect, at each time,
> to get the same result:
>
> auto x1 = f1();
> auto x2 = f1();
>
> If f1.x is implicitly moved, then (likely) x1 != x2. (Of course, the user
> could do:
>
> auto x1 = f1();
> auto x2 = x1;
>
> but still!)
>
> Giving away onwership of an object that can still be used (like f1 and
> f1.x)
> should be made explicitly by the programmer instead of implicitly by the
> compiler.
>
> A special rule in this sense could be useful if the lambda itself was an
> xvalue but additional constraints must hold. For instance the lambda should
> not be returned otherwise, we're back to square one:
>
> auto foo() {
> A x, y ; // as before
> auto f1 = ... // as before
> return f1;
> }
>
> auto f2 = foo();
> auto x1 = f2();
> auto x2 = f2();
>
> --
>
> ---
> 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.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11333c2276ae3e04ee8910c8
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Agree that you don't want to implicitly move. Consider=
the non-lambda equivalent version:<br><br>struct X {<br>=A0 =A0std::string=
msg;<br>=A0 =A0X(const std::string& msg) : msg(msg) {}<br>=A0 =A0std::=
string message() const {<br>
=A0 =A0 =A0 =A0return msg;<br>=A0 =A0}<br>};<br><br>Would you move 'msg=
' in the 'message()' function call? Surely not. Lambdas are not=
that different from that piece of code, among other things by default the =
generated 'operator()' is 'const'. In your example you remo=
ved that 'const' by making the lambda mutable, but this would also =
create another source of confusion:<br>
<br>For 'mutable' lambdas it would move but for non-mutable ones it=
would copy (there is no constructor taking 'std::string const &&am=
p;'). I don't see that this should be the default. For those use ca=
ses where it might make sense (a lambda that is known to be evaluated only =
once...) you can always type 'std::move' in your code.<br>
<br>=A0 =A0David</div><div class=3D"gmail_extra"><br><br><div class=3D"gmai=
l_quote">On Fri, Dec 27, 2013 at 1:45 PM, Cassio Neri <span dir=3D"ltr"><=
;<a href=3D"mailto:cassio.neri@gmail.com" target=3D"_blank">cassio.neri@gma=
il.com</a>></span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"im"><br><br>O=
n Friday, December 27, 2013 3:58:33 PM UTC-2, Mikhail Semenov wrote:</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 class=3D"im"><div>I have looked at the following code=
(A is the type of x and y):</div><div>=A0</div><div>=A0=A0=A0=A0=A0=A0=A0=
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 <font face=3D"courier new,monospace">a=
uto f1 =3D [x =3D std::move(x),&y]() mutable ->A<br>
=A0=A0=A0=A0=A0=A0=A0=A0 {<br>=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 // some pro=
cessing=A0=A0=A0=A0=A0=A0=A0=A0 <br></font></div></div><div class=3D"im"><d=
iv><font face=3D"courier new,monospace">=A0=A0=A0=A0=A0=A0=A0=A0 =A0=A0 <b>=
<font color=3D"#ff00ff">return std::move(x);</font></b>=A0=A0// should not =
the value be moved by default=A0here?<br>
=A0=A0=A0=A0=A0=A0=A0=A0 };</font> <br></div></div></div></blockquote><div>=
<br>No, as Ville has explained.<br><br>In addition, I disagree that an impl=
icit move would be a good idea in this<br>case because users can call f1 mo=
re than once and expect, at each time,<br>
to get the same result:<br><br>auto x1 =3D f1();<br>auto x2 =3D f1();<br><b=
r>If f1.x is implicitly moved, then (likely) x1 !=3D x2. (Of course, the us=
er<br>could do:<br><br>auto x1 =3D f1();<br>auto x2 =3D x1;<br><br>but stil=
l!)<br>
<br>Giving away onwership of an object that can still be used (like f1 and =
f1.x)<br>should be made explicitly by the programmer instead of implicitly =
by the<br>compiler.<br><br>A special rule in this sense could be useful if =
the lambda itself was an<br>
xvalue but additional constraints must hold. For instance the lambda should=
<br>not be returned otherwise, we're back to square one:<br><br>auto fo=
o() {<br>=A0 A x, y ; // as before<br>=A0 auto f1 =3D ... // as before<br>=
=A0 return f1;<br>
}<br><br>auto f2 =3D foo();<br>auto x1 =3D f2();<br>auto x2 =3D f2();<br><b=
r></div></div><div class=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
=A0<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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>
<p></p>
-- <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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11333c2276ae3e04ee8910c8--
.
Author: Mikhail Semenov <mikhailsemenov1957@gmail.com>
Date: Fri, 27 Dec 2013 12:36:50 -0800 (PST)
Raw View
------=_Part_437_7243652.1388176610454
Content-Type: text/plain; charset=ISO-8859-1
>
> I agree with your comments. My argument was fallacious.
>
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_437_7243652.1388176610454
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px=
0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); borde=
r-left-width: 1px; border-left-style: solid;"><div>I agree with your commen=
ts. My argument was fallacious.<br></div>
</blockquote></div>
<p></p>
-- <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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_437_7243652.1388176610454--
.
Author: David Krauss <potswa@gmail.com>
Date: Sat, 28 Dec 2013 15:52:43 +0800
Raw View
On 12/28/13 4:36 AM, Mikhail Semenov wrote:
> I agree with your comments. My argument was fallacious.
For the sake of argument, we could have ref-qualified lambdas
auto fn = [x]() mutable && { return x; } // Automatic move would be
reasonable here
std::move( fn ) (); // because functor can only be called as an rvalue.
fn(); // Error: no matching operator() overload for lvalue fn.
One-shot functions do come up often enough that ref-qualfied lambdas
could be a useful language feature, but I don't know if the destructive
return rule in particular is worth implementing. Arguably if specified
it should apply to all rvalue ref-qualified functions returning a
member, not only lambdas, and that would be a serious breaking change.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Mikhail Semenov <mikhailsemenov1957@gmail.com>
Date: Sat, 28 Dec 2013 09:37:46 -0800 (PST)
Raw View
------=_Part_201_12863888.1388252267005
Content-Type: text/plain; charset=ISO-8859-1
I guess something positive might come out of this discussion. I think that
for lambdas using && is not necessary, it's better to use *return
std::move(x);*
But for && member functions this approach can be useful:
class A
{
double *v;
std::size_t n;
public:
....
A operator+(A x) const &
{
for (std::size_t i = 0; i < n; i++)
{
x.v[i] += v[i];
}
return x; // copy elision according to the present standard
}
A operator+(const A& x) *&&*
{
for (std::size_t i = 0; i < n; i++)
{
v[i] += x.v[i];
}
*return *this; // copy elision should be here as well!!! You have
to write return std::move(*this); to get the desired affect*
}
};
On Saturday, December 28, 2013 7:52:43 AM UTC, David Krauss wrote:
> On 12/28/13 4:36 AM, Mikhail Semenov wrote:
> > I agree with your comments. My argument was fallacious.
>
> For the sake of argument, we could have ref-qualified lambdas
>
> auto fn = [x]() mutable && { return x; } // Automatic move would be
> reasonable here
> std::move( fn ) (); // because functor can only be called as an rvalue.
> fn(); // Error: no matching operator() overload for lvalue fn.
>
> One-shot functions do come up often enough that ref-qualfied lambdas
> could be a useful language feature, but I don't know if the destructive
> return rule in particular is worth implementing. Arguably if specified
> it should apply to all rvalue ref-qualified functions returning a
> member, not only lambdas, and that would be a serious breaking change.
>
>
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_201_12863888.1388252267005
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>I guess something positive might come out of this dis=
cussion. I think that for lambdas using && is not necessary, it's b=
etter to use <strong>return std::move(x);</strong></div><div> </div><d=
iv>But for && member functions this approach can be useful:</div><d=
iv> </div><div>class A<br>{<br> double *v;<br> =
std::size_t n;<br>public:<br>...<br> A opera=
tor+(A x) const &<br> {<br> &n=
bsp; for (std::size_t i =3D 0; i < n; i++)<br> &n=
bsp; {<br>  =
; x.v[i] +=3D v[i];<br> &nbs=
p; }<br> return x; //=
copy elision according to the present standard<br> }</di=
v><div> </div><div> A operator+(const A& x) <str=
ong>&&</strong><br> { &nbs=
p; <br> for (std::size_t i =
=3D 0; i < n; i++)<br> {<br>&n=
bsp; v[i]=
+=3D x.v[i];<br> }<br> &nbs=
p; <strong>return *this; // copy elision shou=
ld be here as well!!! You have to write return std::move(*this); to ge=
t the desired affect</strong><br> }<br>};</div><div> =
;</div><div><br> </div><div><br>On Saturday, December 28, 2013 7:52:43=
AM UTC, David Krauss wrote:</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(20=
4, 204, 204); border-left-width: 1px; border-left-style: solid;">On 12/28/1=
3 4:36 AM, Mikhail Semenov wrote:
<br>> I agree with your comments. My argument was fallacious.
<br>
<br>For the sake of argument, we could have ref-qualified lambdas
<br>
<br>auto fn =3D [x]() mutable && { return x; } // Automatic move wo=
uld be=20
<br>reasonable here
<br>std::move( fn ) (); // because functor can only be called as an rvalue.
<br>fn(); // Error: no matching operator() overload for lvalue fn.
<br>
<br>One-shot functions do come up often enough that ref-qualfied lambdas=20
<br>could be a useful language feature, but I don't know if the destructive=
=20
<br>return rule in particular is worth implementing. Arguably if specified=
=20
<br>it should apply to all rvalue ref-qualified functions returning a=20
<br>member, not only lambdas, and that would be a serious breaking change.
<br>
<br></blockquote></div>
<p></p>
-- <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 std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_201_12863888.1388252267005--
.