Topic: parameters passed by "expression": lazy/delayed


Author: florian.csdt@gmail.com
Date: Mon, 14 May 2018 06:16:07 -0700 (PDT)
Raw View
------=_Part_26389_1141879013.1526303767849
Content-Type: multipart/alternative;
 boundary="----=_Part_26390_745715132.1526303767850"

------=_Part_26390_745715132.1526303767850
Content-Type: text/plain; charset="UTF-8"

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.
But this would be useful in some cases: for example overloading operator&&
and operator|| (and also operator?: when it will be overloadable).
It could also be used to implement a select function defined like this:
float select(int i, float a, float b, float c) {
  switch (i) {
    case 0:
      return a;
    case 1:
      return b;
    case 2:
      return c;
  }
}

The delayed evaluation is important to allow a parameter with side effects
not to be executed if not needed, avoiding undefined behaviors:
float *p;

if (p && *p > 0) { ... } // this is valid

bool AND(bool a, bool b) {
  return a && b;
}

if (AND(p, *p > 0)) { ... } // This is not


I thought of 4 ways to express that:

Type qualifier + implicit evaluation:
float select(int i, float @ a, float @ b, float @ c) {
  switch (i) {
    case 0:
      return a;
    case 1:
      return b;
    case 2:
      return c;
  }
}

Type qualifier + operator:
float select(int i, float @ a, float @ b, float @ c) {
  switch (i) {
    case 0:
      return @a;
    case 1:
      return @b;
    case 2:
      return @c;
  }
}

Type qualifier + callable:
float select(int i, float @ a, float @ b, float @ c) {
  switch (i) {
    case 0:
      return a();
    case 1:
      return b();
    case 2:
      return c();
  }
}

STL type:
float select(int i, std::expression<float> a, std::expression<float> b,
std::expression<float> c) {
  switch (i) {
    case 0:
      return a();
    case 1:
      return b();
    case 2:
      return c();
  }
}


In all the 3 cases, when the select function is called, a functor-like
object is created computing the expression, and this object is then passed
to the function.
float* p;
int i;

float r = select(i, 1.f, *p, std::sqrt(*p));

// equivalent to:

float r;
switch (i) {
  case 0:
    r = 1.f;
    break;
  case 1:
    r = *p;
    break;
  case 2:
    r = std::sqrt(*p);
    break;
}

I really have the impression this could be very interesting in some corner
cases where there is currently no alternatives to do that safely (and
efficiently).

Would this be sensible? Were there any attempt to formalize passing by
expression?
Which way of expressing this should be preferred?

I would be glad to answer any question.

Florian

--
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/26b460b8-abf3-477e-a23d-4b487276fc93%40isocpp.org.

------=_Part_26390_745715132.1526303767850
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Hello everyone,<br><br>I would want to propose a new way t=
o pass parameters to functions.<br>Currently, we have 2 way to pass paramet=
ers: by value, and by reference.<br>(Passing by pointer is really passing b=
y value the address)<br><br>However, none of those allow delayed evaluation=
 of parameters.<br>But this would be useful in some cases: for example over=
loading <span style=3D"font-family: courier new, monospace;">operator&amp;&=
amp;</span> and <span style=3D"font-family: courier new, monospace;">operat=
or||</span> (and also <span style=3D"font-family: courier new, monospace;">=
operator?:</span> when it will be overloadable).<br>It could also be used t=
o implement a <span style=3D"font-family: courier new, monospace;">select</=
span> function defined like this:<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">float</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">select</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> i</=
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">float</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> a</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">float</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> b</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">float</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> c</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 </span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">switch</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">i=
</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><code class=3D"prett=
yprint"><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"=
>case</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #066;" class=3D"styled-by-prettify">0</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 </span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><spa=
n 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"styled-by-prettify"></span></code><code class=3D"prettypr=
int"><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">cas=
e</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #066;" class=3D"styled-by-prettify">1</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 =C2=A0 </span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">return</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> b</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></code><code class=3D"prettyprint">=
<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">case</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #066;" class=3D"styled-by-prettify">2</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>=C2=A0 =C2=A0 =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"> c</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"></span></code><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=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><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br></span></div></code></div><br>The delayed evaluation is important to a=
llow a parameter with side effects not to be executed if not needed, avoidi=
ng undefined behaviors:<br><div style=3D"background-color: rgb(250, 250, 25=
0); border-color: rgb(187, 187, 187); border-style: solid; border-width: 1p=
x; overflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettyp=
rint"><div class=3D"subprettyprint"><span style=3D"color: #606;" class=3D"s=
tyled-by-prettify">float *p;<br><br>if (p &amp;&amp; *p &gt; 0) { ... } // =
this is valid<br><br>bool AND(bool a, bool b) {<br>=C2=A0 return a &amp;&am=
p; b;<br>}<br><br>if (AND(p, *p &gt; 0)) { ... } // This is not<br></span><=
span style=3D"color: #660;" class=3D"styled-by-prettify"></span></div></cod=
e></div><br><br>I thought of 4 ways to express that:<br><br>Type qualifier =
+ implicit evaluation:<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"prettypr=
int"><div class=3D"subprettyprint"><div style=3D"background-color: rgb(250,=
 250, 250); border-color: rgb(187, 187, 187); border-style: solid; border-w=
idth: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><code class=3D=
"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">float</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">select</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"> i</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: #008;" class=3D"styled-by-prettify">float @</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> a</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: #008;" class=3D"style=
d-by-prettify">float</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> @ b</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: #008;" class=3D"styled-by-prettify">float</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> @ c</span><span st=
yle=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">{</span><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">switch</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">i</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</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><code class=3D"p=
rettyprint"><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-pretti=
fy">case</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #066;" class=3D"styled-by-prettify">0</span><sp=
an 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 </s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">return</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> a</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"></span></code><code class=3D"prett=
yprint"><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"=
>case</span><span style=3D"color: #000;" 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"><br>=C2=A0 =C2=A0 =C2=A0 </span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><spa=
n 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;" 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 =
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">cas=
e</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #066;" class=3D"styled-by-prettify">2</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 =C2=A0 </span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">return</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"></span></code><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></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span></div></code></div><span style=3D"color: #660;" class=
=3D"styled-by-prettify"></span></div></code></div><br>Type qualifier + oper=
ator:<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"><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: #008;" class=3D"styled-b=
y-prettify">float</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">se=
lect</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span=
 style=3D"color: #000;" 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"styled-by-prettify"> </span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">float @</span><span style=3D"color: #000;" cla=
ss=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-by-p=
rettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
float</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> @ b<=
/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: #008;" class=3D"styled-by-prettify">float</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> @ c</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">)</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"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">switch</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">i</span><spa=
n 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><code class=3D"prettyprint"><=
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">case</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #066;" class=3D"styled-by-prettify">0</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: #008;" class=3D"styled-by-prettify">return</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;" cl=
ass=3D"styled-by-prettify"></span></code><code class=3D"prettyprint"><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">case</span><spa=
n style=3D"color: #000;" 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;" =
class=3D"styled-by-prettify"><br>=C2=A0 =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"> @b</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"></span></code><code class=3D"prettyprint"><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">case</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #066;" class=3D"styled-by-prettify">2</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 </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> @c</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></code><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br>=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></span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></s=
pan></div></code></div><span style=3D"color: #660;" class=3D"styled-by-pret=
tify"></span></div></code></div><br>Type qualifier + callable:<div style=3D=
"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); bo=
rder-style: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"=
prettyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint"><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"><span style=3D"color: #008;" class=3D"styled-by-prettify">float</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">select</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"> i</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: #008;" class=3D"styled-by-pret=
tify">float</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> @ a</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: #008;" class=3D"styled-by-prettify">float @</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> b</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;" class=
=3D"styled-by-prettify">float @</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 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"><br>=C2=A0 </s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">switch</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">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"style=
d-by-prettify">{</span><code class=3D"prettyprint"><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">case</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" cl=
ass=3D"styled-by-prettify">0</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 =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"> 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"></span></code><code class=3D"prettyprint"><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">case</span><span style=3D"color: #000=
;" 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"style=
d-by-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> b</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"></span></code><code class=3D"prettyprint"><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">case</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span 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=
"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> 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></code><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></span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></code></d=
iv><span style=3D"color: #660;" class=3D"styled-by-prettify"></span></div><=
/code></div><br>STL type:<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"prett=
yprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D=
"styled-by-prettify">float</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">select</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> i</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><code class=3D"prett=
yprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">std::expr=
ession&lt;float&gt;</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"></span></code><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> a</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><co=
de class=3D"prettyprint"><code class=3D"prettyprint"><span style=3D"color: =
#008;" class=3D"styled-by-prettify">std::expression&lt;float&gt;</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"></span></code><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"></span></code><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> b</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><code class=3D"prettyprint"><code cl=
ass=3D"prettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">std::expression&lt;float&gt;</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"></span></code><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"></span></code><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> c</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 </span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">switch</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">i</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: #660;" class=3D"styled-by-pre=
ttify">{</span><code class=3D"prettyprint"><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">case</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"s=
tyled-by-prettify">0</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 </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"> a</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"></s=
pan></code><code class=3D"prettyprint"><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">case</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"sty=
led-by-prettify">1</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br>=C2=A0 =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"> b</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"></spa=
n></code><code class=3D"prettyprint"><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">case</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"style=
d-by-prettify">2</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> c</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"></span>=
</code><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></span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br></span></div></code></div><br=
><br>In all the 3 cases, when the <span style=3D"font-family: courier new, =
monospace;">select</span> function is called, a functor-like object is crea=
ted computing the expression, and this object is then passed to the functio=
n.<br><div style=3D"background-color: rgb(250, 250, 250); border-color: rgb=
(187, 187, 187); border-style: solid; border-width: 1px; overflow-wrap: bre=
ak-word;" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"s=
ubprettyprint"><span style=3D"color: #606;" class=3D"styled-by-prettify">fl=
oat* p;<br>int i;<br><br>float r =3D select(i, 1.f, *p, std::sqrt(*p));<br>=
<br>// equivalent to:<br><br>float r;<br>switch (i) {<br>=C2=A0 case 0:<br>=
=C2=A0=C2=A0=C2=A0 r =3D 1.f;<br>=C2=A0=C2=A0=C2=A0 break;</span><code clas=
s=3D"prettyprint"><span style=3D"color: #606;" class=3D"styled-by-prettify"=
><br>=C2=A0 case 1:<br>=C2=A0=C2=A0=C2=A0 r =3D *p;<br>=C2=A0=C2=A0=C2=A0 b=
reak;</span></code><span style=3D"color: #606;" class=3D"styled-by-prettify=
"><code class=3D"prettyprint"><span style=3D"color: #606;" class=3D"styled-=
by-prettify"><br>=C2=A0 case 2:<br>=C2=A0=C2=A0=C2=A0 r =3D std::sqrt(*p);<=
br>=C2=A0=C2=A0=C2=A0 break;</span></code></span></div><div class=3D"subpre=
ttyprint"><span style=3D"color: #606;" class=3D"styled-by-prettify"><code c=
lass=3D"prettyprint"><span style=3D"color: #606;" class=3D"styled-by-pretti=
fy"></span></code>}<br></span><span style=3D"color: #660;" class=3D"styled-=
by-prettify"></span></div></code></div><br>I really have the impression thi=
s could be very interesting in some corner cases where there is currently n=
o alternatives to do that safely (and efficiently).<br><br>Would this be se=
nsible? Were there any attempt to formalize passing by expression?<br>Which=
 way of expressing this should be preferred?<br><br>I would be glad to answ=
er any question.<br><br>Florian<br></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/26b460b8-abf3-477e-a23d-4b487276fc93%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/26b460b8-abf3-477e-a23d-4b487276fc93=
%40isocpp.org</a>.<br />

------=_Part_26390_745715132.1526303767850--

------=_Part_26389_1141879013.1526303767849--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 14 May 2018 06:41:53 -0700 (PDT)
Raw View
------=_Part_26098_1309849046.1526305313575
Content-Type: multipart/alternative;
 boundary="----=_Part_26099_122870971.1526305313575"

------=_Part_26099_122870971.1526305313575
Content-Type: text/plain; charset="UTF-8"

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.

--
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/f63e99cf-a7d7-49c5-bbf0-673568ea4e6e%40isocpp.org.

------=_Part_26099_122870971.1526305313575
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Monday, May 14, 2018 at 9:16:07 AM UTC-4, floria...@gma=
il.com wrote:<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">=
Hello everyone,<br><br>I would want to propose a new way to pass parameters=
 to functions.<br>Currently, we have 2 way to pass parameters: by value, an=
d by reference.<br>(Passing by pointer is really passing by value the addre=
ss)<br><br>However, none of those allow delayed evaluation of parameters.<b=
r></div></blockquote><div><br><a href=3D"http://wg21.link/P0927">P0927 cove=
rs this general idea.</a> I&#39;m not sure if it was discussed at Jacksonvi=
lle.</div><br></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/f63e99cf-a7d7-49c5-bbf0-673568ea4e6e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/f63e99cf-a7d7-49c5-bbf0-673568ea4e6e=
%40isocpp.org</a>.<br />

------=_Part_26099_122870971.1526305313575--

------=_Part_26098_1309849046.1526305313575--

.


Author: mihailnajdenov@gmail.com
Date: Sat, 26 May 2018 01:52:06 -0700 (PDT)
Raw View
------=_Part_18171_995281439.1527324726982
Content-Type: multipart/alternative;
 boundary="----=_Part_18172_1224312713.1527324726983"

------=_Part_18172_1224312713.1527324726983
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

 - How are these lazy arguments different then taking=20
std::function/function_ref?=20

 - On the call site I really doubt not be able to see you are NOT=20
constructing the argument on function call is a good idea - it will make=20
the code misleading
In a way we will repeat the problem with non-const references, where one is=
=20
not able to tell if the argument is passed by reference or not, without=20
looking at the function interface!

 - But there is also a more serious issue - proliferation of anonymous=20
classes!

Where right now the user will have write clumsy lambda

SaveAction([this]{ return _filepath; });
CopyAction([this]{ return _filepath; });
MoveAction([this]{ return _filepath; });

Sooner or later the user will see the obvious solution to use a variable=20
for all cases

std::function<Filepath()> _filepathSource =3D [this]{ return _filepath; };

SaveAction(_filepathSource);
=E2=80=A6
=E2=80=A6

The user will NEVER do that if he has transparent lambdas creation, which=
=20
ultimately will lead to code bloat and/or more optimizer work.




On Monday, May 14, 2018 at 4:16:07 PM UTC+3, 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.
> But this would be useful in some cases: for example overloading operator&=
&=20
> and operator|| (and also operator?: when it will be overloadable).
> It could also be used to implement a select function defined like this:
> float select(int i, float a, float b, float c) {
>   switch (i) {
>     case 0:
>       return a;
>     case 1:
>       return b;
>     case 2:
>       return c;
>   }
> }
>
> The delayed evaluation is important to allow a parameter with side effect=
s=20
> not to be executed if not needed, avoiding undefined behaviors:
> float *p;
>
> if (p && *p > 0) { ... } // this is valid
>
> bool AND(bool a, bool b) {
>   return a && b;
> }
>
> if (AND(p, *p > 0)) { ... } // This is not
>
>
> I thought of 4 ways to express that:
>
> Type qualifier + implicit evaluation:
> float select(int i, float @ a, float @ b, float @ c) {
>   switch (i) {
>     case 0:
>       return a;
>     case 1:
>       return b;
>     case 2:
>       return c;
>   }
> }
>
> Type qualifier + operator:
> float select(int i, float @ a, float @ b, float @ c) {
>   switch (i) {
>     case 0:
>       return @a;
>     case 1:
>       return @b;
>     case 2:
>       return @c;
>   }
> }
>
> Type qualifier + callable:
> float select(int i, float @ a, float @ b, float @ c) {
>   switch (i) {
>     case 0:
>       return a();
>     case 1:
>       return b();
>     case 2:
>       return c();
>   }
> }
>
> STL type:
> float select(int i, std::expression<float> a, std::expression<float> b,=
=20
> std::expression<float> c) {
>   switch (i) {
>     case 0:
>       return a();
>     case 1:
>       return b();
>     case 2:
>       return c();
>   }
> }
>
>
> In all the 3 cases, when the select function is called, a functor-like=20
> object is created computing the expression, and this object is then passe=
d=20
> to the function.
> float* p;
> int i;
>
> float r =3D select(i, 1.f, *p, std::sqrt(*p));
>
> // equivalent to:
>
> float r;
> switch (i) {
>   case 0:
>     r =3D 1.f;
>     break;
>   case 1:
>     r =3D *p;
>     break;
>   case 2:
>     r =3D std::sqrt(*p);
>     break;
> }
>
> I really have the impression this could be very interesting in some corne=
r=20
> cases where there is currently no alternatives to do that safely (and=20
> efficiently).
>
> Would this be sensible? Were there any attempt to formalize passing by=20
> expression?
> Which way of expressing this should be preferred?
>
> I would be glad to answer any question.
>
> 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/4ad104fa-1d8a-4e40-8275-ceefb0840d81%40isocpp.or=
g.

------=_Part_18172_1224312713.1527324726983
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>=C2=A0- How are these lazy arguments different then t=
aking std::function/function_ref?=C2=A0</div><div><br></div><div>=C2=A0- On=
 the call site I really doubt not be able to see you are NOT constructing t=
he argument on function call is a good idea - it will make the code mislead=
ing<br></div><div>In a way we will repeat the problem with non-const refere=
nces, where one is not able to tell if the argument is passed by reference =
or not, without looking at the function interface!</div><div><font face=3D"=
courier new,monospace"><br></font></div><div><font face=3D"arial,sans-serif=
">=C2=A0- But there is also a more serious issue - proliferation of anonymo=
us classes!</font></div><div><font face=3D"arial,sans-serif"><br></font></d=
iv><div><font face=3D"arial,sans-serif">Where right now the user </font>wil=
l have write clumsy lambda</div><div><br></div><div><font face=3D"courier n=
ew,monospace">SaveAction([this]{ return _filepath; });</font></div><div><fo=
nt face=3D"courier new,monospace"></font><span style=3D"display: inline !im=
portant; 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; orphans: 2;=
 text-align: left; text-decoration: none; text-indent: 0px; text-transform:=
 none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0=
px;">CopyAction([this]{ return _filepath; });</span></div><div><span style=
=3D"background-color: transparent; border-bottom-color: rgb(34, 34, 34); bo=
rder-bottom-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-l=
eft-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-style: normal; font-variant: normal; font-weight: 40=
0; letter-spacing: normal; margin-bottom: 0px; margin-left: 0px; margin-rig=
ht: 0px; margin-top: 0px; orphans: 2; padding-bottom: 0px; padding-left: 0p=
x; padding-right: 0px; padding-top: 0px; text-align: left; text-decoration:=
 none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0=
px; white-space: normal; word-spacing: 0px;">MoveAction([this]{ return _fil=
epath; });</span><b style=3D"background-attachment: scroll; background-clip=
: border-box; background-color: transparent; background-image: none; backgr=
ound-origin: padding-box; background-position-x: 0%; background-position-y:=
 0%; background-repeat: repeat; background-size: auto; 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); font-family: &amp;quot;Arial&amp;quot;,&amp;q=
uot;Helvetica&amp;quot;,sans-serif; font-size: 13px; font-style: normal; fo=
nt-variant: normal; font-weight: 700; height: auto; letter-spacing: normal;=
 margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; =
min-width: 0px; orphans: 2; overflow: visible; overflow-x: visible; overflo=
w-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; p=
adding-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;"></b><i style=3D"background-attachment: scroll; backgro=
und-clip: border-box; background-color: transparent; background-image: none=
; background-origin: padding-box; background-position-x: 0%; background-pos=
ition-y: 0%; background-repeat: repeat; background-size: auto; border-botto=
m-color: rgb(34, 34, 34); border-bottom-style: none; border-bottom-width: 0=
px; border-image-outset: 0; border-image-repeat: stretch; border-image-slic=
e: 100%; border-image-source: none; border-image-width: 1; border-left-colo=
r: 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-to=
p-width: 0px; color: rgb(34, 34, 34); font-family: &amp;quot;Arial&amp;quot=
;,&amp;quot;Helvetica&amp;quot;,sans-serif; font-size: 13px; font-style: it=
alic; font-variant: normal; font-weight: 400; height: auto; letter-spacing:=
 normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-to=
p: 0px; min-width: 0px; orphans: 2; overflow: visible; overflow-x: visible;=
 overflow-y: visible; padding-bottom: 0px; padding-left: 0px; padding-right=
: 0px; padding-top: 0px; text-align: left; text-decoration: none; text-inde=
nt: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space:=
 normal; word-spacing: 0px;"></i><u style=3D"background-attachment: scroll;=
 background-clip: border-box; background-color: transparent; background-ima=
ge: none; background-origin: padding-box; background-position-x: 0%; backgr=
ound-position-y: 0%; background-repeat: repeat; background-size: auto; 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); font-family: &amp;quot;Arial&=
amp;quot;,&amp;quot;Helvetica&amp;quot;,sans-serif; font-size: 13px; font-s=
tyle: normal; font-variant: normal; font-weight: 400; height: auto; letter-=
spacing: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; m=
argin-top: 0px; min-width: 0px; orphans: 2; overflow: visible; overflow-x: =
visible; overflow-y: visible; padding-bottom: 0px; padding-left: 0px; paddi=
ng-right: 0px; padding-top: 0px; text-align: left; text-decoration: underli=
ne; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px;=
 white-space: normal; word-spacing: 0px;"></u><sub style=3D"background-colo=
r: transparent; border-bottom-color: rgb(34, 34, 34); border-bottom-style: =
none; border-bottom-width: 0px; border-image-outset: 0; border-image-repeat=
: stretch; border-image-slice: 100%; border-image-source: none; border-imag=
e-width: 1; border-left-color: rgb(34, 34, 34); border-left-style: none; bo=
rder-left-width: 0px; border-right-color: rgb(34, 34, 34); border-right-sty=
le: none; border-right-width: 0px; border-top-color: rgb(34, 34, 34); borde=
r-top-style: none; border-top-width: 0px; color: rgb(34, 34, 34); font-fami=
ly: &amp;quot;Arial&amp;quot;,&amp;quot;Helvetica&amp;quot;,sans-serif; fon=
t-size: 9px; font-style: normal; font-variant: normal; font-weight: 400; le=
tter-spacing: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0=
px; margin-top: 0px; orphans: 2; padding-bottom: 0px; padding-left: 0px; pa=
dding-right: 0px; padding-top: 0px; text-align: left; text-decoration: none=
; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; w=
hite-space: normal; word-spacing: 0px;"></sub><sup style=3D"background-colo=
r: transparent; border-bottom-color: rgb(34, 34, 34); border-bottom-style: =
none; border-bottom-width: 0px; border-image-outset: 0; border-image-repeat=
: stretch; border-image-slice: 100%; border-image-source: none; border-imag=
e-width: 1; border-left-color: rgb(34, 34, 34); border-left-style: none; bo=
rder-left-width: 0px; border-right-color: rgb(34, 34, 34); border-right-sty=
le: none; border-right-width: 0px; border-top-color: rgb(34, 34, 34); borde=
r-top-style: none; border-top-width: 0px; color: rgb(34, 34, 34); font-fami=
ly: &amp;quot;Arial&amp;quot;,&amp;quot;Helvetica&amp;quot;,sans-serif; fon=
t-size: 9px; font-style: normal; font-variant: normal; font-weight: 400; le=
tter-spacing: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0=
px; margin-top: 0px; orphans: 2; padding-bottom: 0px; padding-left: 0px; pa=
dding-right: 0px; padding-top: 0px; text-align: left; text-decoration: none=
; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; w=
hite-space: normal; word-spacing: 0px;"></sup><strike style=3D"background-c=
olor: transparent; border-bottom-color: rgb(34, 34, 34); border-bottom-styl=
e: none; border-bottom-width: 0px; border-image-outset: 0; border-image-rep=
eat: stretch; border-image-slice: 100%; border-image-source: none; border-i=
mage-width: 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); bo=
rder-top-style: none; border-top-width: 0px; color: rgb(34, 34, 34); font-f=
amily: &amp;quot;Arial&amp;quot;,&amp;quot;Helvetica&amp;quot;,sans-serif; =
font-size: 13px; font-style: normal; font-variant: normal; font-weight: 400=
; letter-spacing: normal; margin-bottom: 0px; margin-left: 0px; margin-righ=
t: 0px; margin-top: 0px; orphans: 2; padding-bottom: 0px; padding-left: 0px=
; padding-right: 0px; padding-top: 0px; text-align: left; text-decoration: =
line-through; text-indent: 0px; text-transform: none; -webkit-text-stroke-w=
idth: 0px; white-space: normal; word-spacing: 0px;"></strike><b></b><i></i>=
<u></u><sub></sub><sup></sup><strike></strike></div><div><br></div><div>Soo=
ner or later the user will see the obvious solution to use a variable for a=
ll cases</div><div><br></div><div><font face=3D"courier new,monospace">std:=
:function&lt;Filepath()&gt; _filepathSource =3D <span style=3D"text-align: =
left; color: rgb(34, 34, 34); text-transform: none; text-indent: 0px; lette=
r-spacing: normal; font-size: 13px; font-style: normal; font-variant: norma=
l; font-weight: 400; text-decoration: none; word-spacing: 0px; display: inl=
ine !important; white-space: normal; orphans: 2; float: none; -webkit-text-=
stroke-width: 0px; background-color: transparent;">[this]{ return _filepath=
; };</span></font></div><div><font face=3D"courier new,monospace"><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;"><br></=
span></font></div><div><font face=3D"courier new,monospace"><span style=3D"=
text-align: left; color: rgb(34, 34, 34); text-transform: none; text-indent=
: 0px; letter-spacing: normal; font-size: 13px; font-variant: normal; word-=
spacing: 0px; display: inline !important; white-space: normal; orphans: 2; =
float: none; -webkit-text-stroke-width: 0px; background-color: transparent;=
"><span style=3D"display: inline !important; float: none; background-color:=
 transparent; color: rgb(34, 34, 34); font-family: courier new,monospace; f=
ont-size: 13px; font-style: normal; font-variant: normal; font-weight: 400;=
 letter-spacing: normal; orphans: 2; text-align: left; text-decoration: non=
e; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; =
white-space: normal; word-spacing: 0px;">SaveAction(_filepathSource);</span=
><b></b><i></i><u></u><sub></sub><sup></sup><strike></strike><br></span></f=
ont></div><div><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;"><font face=3D"courier new,monospace">=E2=80=A6</font></sp=
an></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-decorati=
on: none; word-spacing: 0px; display: inline !important; white-space: norma=
l; orphans: 2; float: none; -webkit-text-stroke-width: 0px; background-colo=
r: transparent;"><font face=3D"courier new,monospace">=E2=80=A6</font></spa=
n><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; wo=
rd-spacing: 0px; display: inline !important; white-space: normal; orphans: =
2; float: none; -webkit-text-stroke-width: 0px; background-color: transpare=
nt;"><font face=3D"courier new,monospace"><br></font></span></div><div><fon=
t face=3D"courier new,monospace"><span style=3D"text-align: left; color: rg=
b(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; text-decoration: none; word-spacing: 0px; display: inline !important;=
 white-space: normal; orphans: 2; float: none; -webkit-text-stroke-width: 0=
px; background-color: transparent;"><br></span></font></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">The user will NEVER do that if he has transparent =
lambdas creation, which ultimately will lead to code bloat and/or more opti=
mizer work.</font></span></div><div><span style=3D"text-align: left; 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-weig=
ht: 400; text-decoration: none; word-spacing: 0px; display: inline !importa=
nt; white-space: normal; orphans: 2; float: none; -webkit-text-stroke-width=
: 0px; background-color: transparent;"><font face=3D"arial,sans-serif"><br>=
</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; 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;"><font face=3D"arial,sans-serif"><br></font></sp=
an></div><div><b></b><i></i><u></u><sub></sub><sup></sup><strike></strike><=
font face=3D"courier new,monospace"></font><font face=3D"arial,sans-serif">=
</font><br></div><b></b><i></i><u></u><sub></sub><sup></sup><strike></strik=
e><b></b><i></i><u></u><sub></sub><sup></sup><strike></strike><br>On Monday=
, May 14, 2018 at 4:16:07 PM UTC+3, floria...@gmail.com wrote:<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">Hello everyone,<br><br>I w=
ould want to propose a new way to pass parameters to functions.<br>Currentl=
y, we have 2 way to pass parameters: by value, and by reference.<br>(Passin=
g by pointer is really passing by value the address)<br><br>However, none o=
f those allow delayed evaluation of parameters.<br>But this would be useful=
 in some cases: for example overloading <span style=3D"font-family:courier =
new,monospace">operator&amp;&amp;</span> and <span style=3D"font-family:cou=
rier new,monospace">operator||</span> (and also <span style=3D"font-family:=
courier new,monospace">operator?:</span> when it will be overloadable).<br>=
It could also be used to implement a <span style=3D"font-family:courier new=
,monospace">select</span> function defined like this:<br><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:#008">float</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#008">select</span><sp=
an 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 styl=
e=3D"color:#000"> </span><span style=3D"color:#008">float</span><span style=
=3D"color:#000"> a</span><span style=3D"color:#660">,</span><span style=3D"=
color:#000"> </span><span style=3D"color:#008">float</span><span style=3D"c=
olor:#000"> b</span><span style=3D"color:#660">,</span><span style=3D"color=
:#000"> </span><span style=3D"color:#008">float</span><span style=3D"color:=
#000"> c</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">switch</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">)</span><span style=3D"color:#000"> </=
span><span style=3D"color:#660">{</span><code><span style=3D"color:#000"><b=
r>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span style=3D=
"color:#000"> </span><span style=3D"color:#066">0</span><span style=3D"colo=
r:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span>=
<span style=3D"color:#008">return</span><span style=3D"color:#000"> a</span=
><span style=3D"color:#660">;</span><span style=3D"color:#000"></span></cod=
e><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"=
color:#008">case</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#066">1</span><span style=3D"color:#660">:</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</spa=
n><span style=3D"color:#000"> b</span><span style=3D"color:#660">;</span><s=
pan style=3D"color:#000"></span></code><code><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"=
color:#000"> </span><span style=3D"color:#066">2</span><span style=3D"color=
:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><=
span style=3D"color:#008">return</span><span style=3D"color:#000"> c</span>=
<span style=3D"color:#660">;</span><span style=3D"color:#000"></span></code=
><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:#660">}</s=
pan><span style=3D"color:#000"><br></span></div></code></div><br>The delaye=
d evaluation is important to allow a parameter with side effects not to be =
executed if not needed, avoiding undefined behaviors:<br><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:#606">float *p;<br><b=
r>if (p &amp;&amp; *p &gt; 0) { ... } // this is valid<br><br>bool AND(bool=
 a, bool b) {<br>=C2=A0 return a &amp;&amp; b;<br>}<br><br>if (AND(p, *p &g=
t; 0)) { ... } // This is not<br></span><span style=3D"color:#660"></span><=
/div></code></div><br><br>I thought of 4 ways to express that:<br><br>Type =
qualifier + implicit evaluation:<br><div style=3D"background-color:rgb(250,=
250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px"=
><code><div><div style=3D"background-color:rgb(250,250,250);border-color:rg=
b(187,187,187);border-style:solid;border-width:1px"><code><div><span style=
=3D"color:#008">float</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">select</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"color:#000"> </span><span style=3D"c=
olor:#008">float @</span><span style=3D"color:#000"> a</span><span style=3D=
"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#008">float</span><span style=3D"color:#000"> @ b</span><span style=3D"co=
lor:#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#=
008">float</span><span style=3D"color:#000"> @ c</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">switch</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=
">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{</=
span><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=
=3D"color:#008">case</span><span style=3D"color:#000"> </span><span style=
=3D"color:#066">0</span><span style=3D"color:#660">:</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">retur=
n</span><span style=3D"color:#000"> a</span><span style=3D"color:#660">;</s=
pan><span style=3D"color:#000"></span></code><code><span style=3D"color:#00=
0"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#066">1</span><span style=3D=
"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </=
span><span style=3D"color:#008">return</span><span style=3D"color:#000"> b<=
/span><span style=3D"color:#660">;</span><span style=3D"color:#000"></span>=
</code><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span styl=
e=3D"color:#008">case</span><span style=3D"color:#000"> </span><span style=
=3D"color:#066">2</span><span style=3D"color:#660">:</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">retur=
n</span><span style=3D"color:#000"> c</span><span style=3D"color:#660">;</s=
pan><span style=3D"color:#000"></span></code><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:#660">}</span><span style=3D"color:#000">=
<br></span></div></code></div><span style=3D"color:#660"></span></div></cod=
e></div><br>Type qualifier + operator:<br><div style=3D"background-color:rg=
b(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-widt=
h:1px"><code><div><div style=3D"background-color:rgb(250,250,250);border-co=
lor:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><span =
style=3D"color:#008">float</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#008">select</span><span style=3D"color:#660">(</span><span s=
tyle=3D"color:#008">int</span><span style=3D"color:#000"> i</span><span sty=
le=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D=
"color:#008">float @</span><span style=3D"color:#000"> a</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#008">float</span><span style=3D"color:#000"> @ b</span><span style=3D=
"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#008">float</span><span style=3D"color:#000"> @ c</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>=C2=A0 </span><span style=3D"co=
lor:#008">switch</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#660">(</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><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">case</span><span style=3D"color:#000"> </span><span style=
=3D"color:#066">0</span><span style=3D"color:#660">:</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">retur=
n</span><span style=3D"color:#000"> @a</span><span style=3D"color:#660">;</=
span><span style=3D"color:#000"></span></code><code><span style=3D"color:#0=
00"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#066">1</span><span style=
=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 </span><span style=3D"color:#008">return</span><span style=3D"color:#000">=
 @b</span><span style=3D"color:#660">;</span><span style=3D"color:#000"></s=
pan></code><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span =
style=3D"color:#008">case</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#066">2</span><span style=3D"color:#660">:</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">=
return</span><span style=3D"color:#000"> @c</span><span style=3D"color:#660=
">;</span><span style=3D"color:#000"></span></code><span style=3D"color:#00=
0"><br>=C2=A0 </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></span></div></code></div><span style=3D"color:#660"></span></div=
></code></div><br>Type qualifier + callable:<div style=3D"background-color:=
rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-wi=
dth:1px"><code><div><div style=3D"background-color:rgb(250,250,250);border-=
color:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><spa=
n style=3D"color:#008">float</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#008">select</span><span style=3D"color:#660">(</span><span=
 style=3D"color:#008">int</span><span style=3D"color:#000"> i</span><span s=
tyle=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">float</span><span style=3D"color:#000"> @ a</span><span sty=
le=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D=
"color:#008">float @</span><span style=3D"color:#000"> b</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#008">float @</span><span style=3D"color:#000"> c</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"><br>=C2=A0 </span><span style=3D=
"color:#008">switch</span><span style=3D"color:#000"> </span><span style=3D=
"color:#660">(</span><span style=3D"color:#000">i</span><span style=3D"colo=
r:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#66=
0">{</span><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span =
style=3D"color:#008">case</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#066">0</span><span style=3D"color:#660">:</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">=
return</span><span style=3D"color:#000"> a</span><span style=3D"color:#660"=
>();</span><span style=3D"color:#000"></span></code><code><span style=3D"co=
lor:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#066">1</span><span s=
tyle=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:=
#000"> b</span><span style=3D"color:#660">();</span><span style=3D"color:#0=
00"></span></code><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span=
><span style=3D"color:#008">case</span><span style=3D"color:#000"> </span><=
span style=3D"color:#066">2</span><span style=3D"color:#660">:</span><span =
style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#=
008">return</span><span style=3D"color:#000"> c</span><span style=3D"color:=
#660">();</span><span style=3D"color:#000"></span></code><span style=3D"col=
or:#000"><br>=C2=A0 </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></span></div></code></div><span style=3D"color:#660"></=
span></div></code></div><br>STL type:<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">float</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#008">select</span><span style=3D"colo=
r:#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"color:#000"=
> </span><code><span style=3D"color:#008">std::expression&lt;float&gt;</spa=
n><span style=3D"color:#000"></span></code><span style=3D"color:#000"> a</s=
pan><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span><=
code><code><span style=3D"color:#008">std::expression&lt;float&gt;</span><s=
pan style=3D"color:#000"></span></code><span style=3D"color:#000"></span></=
code><span style=3D"color:#000"> b</span><span style=3D"color:#660">,</span=
><span style=3D"color:#000"> </span><code><code><span style=3D"color:#008">=
std::expression&lt;float&gt;</span><span style=3D"color:#000"></span></code=
><span style=3D"color:#000"></span></code><span style=3D"color:#000"> c</sp=
an><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>=C2=A0 </sp=
an><span style=3D"color:#008">switch</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#660">(</span><span style=3D"color:#000">i</span><s=
pan style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#660">{</span><code><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 </span><span style=3D"color:#008">case</span><span style=3D"color:#000"=
> </span><span style=3D"color:#066">0</span><span style=3D"color:#660">:</s=
pan><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#008">return</span><span style=3D"color:#000"> a</span><span styl=
e=3D"color:#660">();</span><span style=3D"color:#000"></span></code><code><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#00=
8">case</span><span style=3D"color:#000"> </span><span style=3D"color:#066"=
>1</span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span s=
tyle=3D"color:#000"> b</span><span style=3D"color:#660">();</span><span sty=
le=3D"color:#000"></span></code><code><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"color:#=
000"> </span><span style=3D"color:#066">2</span><span style=3D"color:#660">=
:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span st=
yle=3D"color:#008">return</span><span style=3D"color:#000"> c</span><span s=
tyle=3D"color:#660">();</span><span style=3D"color:#000"></span></code><spa=
n 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:#660">}</span><=
span style=3D"color:#000"><br></span></div></code></div><br><br>In all the =
3 cases, when the <span style=3D"font-family:courier new,monospace">select<=
/span> function is called, a functor-like object is created computing the e=
xpression, and this object is then passed to the function.<br><div style=3D=
"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-sty=
le:solid;border-width:1px"><code><div><span style=3D"color:#606">float* p;<=
br>int i;<br><br>float r =3D select(i, 1.f, *p, std::sqrt(*p));<br><br>// e=
quivalent to:<br><br>float r;<br>switch (i) {<br>=C2=A0 case 0:<br>=C2=A0=
=C2=A0=C2=A0 r =3D 1.f;<br>=C2=A0=C2=A0=C2=A0 break;</span><code><span styl=
e=3D"color:#606"><br>=C2=A0 case 1:<br>=C2=A0=C2=A0=C2=A0 r =3D *p;<br>=C2=
=A0=C2=A0=C2=A0 break;</span></code><span style=3D"color:#606"><code><span =
style=3D"color:#606"><br>=C2=A0 case 2:<br>=C2=A0=C2=A0=C2=A0 r =3D std::sq=
rt(*p);<br>=C2=A0=C2=A0=C2=A0 break;</span></code></span></div><div><span s=
tyle=3D"color:#606"><code><span style=3D"color:#606"></span></code>}<br></s=
pan><span style=3D"color:#660"></span></div></code></div><br>I really have =
the impression this could be very interesting in some corner cases where th=
ere is currently no alternatives to do that safely (and efficiently).<br><b=
r>Would this be sensible? Were there any attempt to formalize passing by ex=
pression?<br>Which way of expressing this should be preferred?<br><br>I wou=
ld be glad to answer any question.<br><br>Florian<br></div></blockquote></d=
iv>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/4ad104fa-1d8a-4e40-8275-ceefb0840d81%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4ad104fa-1d8a-4e40-8275-ceefb0840d81=
%40isocpp.org</a>.<br />

------=_Part_18172_1224312713.1527324726983--

------=_Part_18171_995281439.1527324726982--

.


Author: Florian Lemaitre <florian.csdt@gmail.com>
Date: Sun, 27 May 2018 18:19:26 +0200
Raw View
This is a multi-part message in MIME format.
--------------6E6AFE97BD508C535845AB42
Content-Type: text/plain; charset="UTF-8"; format=flowed
Content-Transfer-Encoding: quoted-printable

Lazy arguments are compatible with terse lambda. Having one will not=20
remove the need for the other.

You seem to miss one crucial point with this proposal (P0927): it will=20
not create anonymous classes at all: it will always use a function=20
pointer like this: T (*)(void*)

If I give an example with the proposal syntax, this will be:

|
intfoo([]->inti){
returni();
}

intbar(intj){
returnfoo(j+2);
}
intfoobar(intj){
returnfoo(2*j);
}
|

With lambdas, you will have two instantiation of foo, but in this=20
proposal, you will have a single symbol for foo, which would be=20
equivalent to int foo(int (*)(void*), void*).

So the previous example will be strictly equivalent to:
|
intfoo(int(*i)(void*),void*stack_p){
returni(stack_p);
}

intbar(intj){
intclosure(void*stack_p){
intj =3D*static_cast<int*>(stack_p +/* offset j */);
returnj+2;
}
returnfoo(&closure,__builtin_frame_address(0));
}
|
intfoobar(intj){
intclosure(void*stack_p){
intj =3D*static_cast<int*>(stack_p +/* offset j */);
return2*j;
}
returnfoo(&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=20
type. And those functions will be created anyway if you want any form of=20
lazyness delayed evaluation. Even if the call site is aware that it is=20
creating those functions.

As you can see, it is even mush simpler and lighter than creating a=20
std::function std::function_ref. There is no extra burden on the=20
compiler to optimize this: it is just inlining a function pointer when=20
this pointer is known: no heap allocation!


Now, that's true it will be the same call syntax when it is passed by=20
value/ref as when it is passed lazily, giving potential side-effects not=20
be executed.
Guess what? That's already the case in template code when using && and=20
||: those operators are short-circuiting when used on bools, but maybe=20
overrided by any custom class losing their short-circuiting property.
In fact, this proposal would solve this last problem by allowing=20
implementations of custom classes to also be short-circuiting.

On 26/05/2018 10:52, mihailnajdenov@gmail.com wrote:
> =C2=A0- How are these lazy arguments different then taking=20
> std::function/function_ref?
>
> =C2=A0- On the call site I really doubt not be able to see you are NOT=20
> constructing the argument on function call is a good idea - it will=20
> make the code misleading
> In a way we will repeat the problem with non-const references, where=20
> one is not able to tell if the argument is passed by reference or not,=20
> without looking at the function interface!
>
> =C2=A0- But there is also a more serious issue - proliferation of anonymo=
us=20
> classes!
>
> Where right now the user will have write clumsy lambda
>
> SaveAction([this]{ return _filepath; });
> CopyAction([this]{ return _filepath; });
> MoveAction([this]{ return _filepath; });
>
> Sooner or later the user will see the obvious solution to use a=20
> variable for all cases
>
> std::function<Filepath()> _filepathSource =3D [this]{ return _filepath; }=
;
>
> SaveAction(_filepathSource);
> =E2=80=A6
> =E2=80=A6
>
> The user will NEVER do that if he has transparent lambdas creation,=20
> which ultimately will lead to code bloat and/or more optimizer work.
>
>
>
>
> On Monday, May 14, 2018 at 4:16:07 PM UTC+3, 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.
>     But this would be useful in some cases: for example overloading
>     operator&& and operator|| (and also operator?: when it will be
>     overloadable).
>     It could also be used to implement a select function defined like
>     this:
>     |
>     floatselect(inti,floata,floatb,floatc){
>     switch(i){|
>     case0:
>     returna;||
>     case1:
>     returnb;||
>     case2:
>     returnc;|
>     }
>     }
>     |
>
>     The delayed evaluation is important to allow a parameter with side
>     effects not to be executed if not needed, avoiding undefined
>     behaviors:
>     |
>     float *p;
>
>     if (p && *p > 0) { ... } // this is valid
>
>     bool AND(bool a, bool b) {
>     =C2=A0 return a && b;
>     }
>
>     if (AND(p, *p > 0)) { ... } // This is not
>     |
>
>
>     I thought of 4 ways to express that:
>
>     Type qualifier + implicit evaluation:
>     |
>     |
>     floatselect(inti,float @a,float@ b,float@ c){
>     switch(i){|
>     case0:
>     returna;||
>     case1:
>     returnb;||
>     case2:
>     returnc;|
>     }
>     }
>     |
>     |
>
>     Type qualifier + operator:
>     |
>     |
>     floatselect(inti,float @a,float@ b,float@ c){
>     switch(i){|
>     case0:
>     return@a;||
>     case1:
>     return@b;||
>     case2:
>     return@c;|
>     }
>     }
>     |
>     |
>
>     Type qualifier + callable:
>     |
>     |
>     floatselect(inti,float@ a,float @b,float @c){
>     switch(i){|
>     case0:
>     returna();||
>     case1:
>     returnb();||
>     case2:
>     returnc();|
>     }
>     }
>     |
>     |
>
>     STL type:
>     |
>     floatselect(inti,|std::expression<float>|a,||std::expression<float>||=
b,||std::expression<float>||c){
>     switch(i){|
>     case0:
>     returna();||
>     case1:
>     returnb();||
>     case2:
>     returnc();|
>     }
>     }
>     |
>
>
>     In all the 3 cases, when the select function is called, a
>     functor-like object is created computing the expression, and this
>     object is then passed to the function.
>     |
>     float* p;
>     int i;
>
>     float r =3D select(i, 1.f, *p, std::sqrt(*p));
>
>     // equivalent to:
>
>     float r;
>     switch (i) {
>     =C2=A0 case 0:
>     =C2=A0=C2=A0=C2=A0 r =3D 1.f;
>     =C2=A0=C2=A0=C2=A0 break;|
>     =C2=A0 case 1:
>     =C2=A0=C2=A0=C2=A0 r =3D *p;
>     =C2=A0=C2=A0=C2=A0 break;||
>     =C2=A0 case 2:
>     =C2=A0=C2=A0=C2=A0 r =3D std::sqrt(*p);
>     =C2=A0=C2=A0=C2=A0 break;|
>     ||}
>     |
>
>     I really have the impression this could be very interesting in
>     some corner cases where there is currently no alternatives to do
>     that safely (and efficiently).
>
>     Would this be sensible? Were there any attempt to formalize
>     passing by expression?
>     Which way of expressing this should be preferred?
>
>     I would be glad to answer any question.
>
>     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/e35048a4-3937-659b-f8a5-c93ccc7397be%40gmail.com=
..

--------------6E6AFE97BD508C535845AB42
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<html>
  <head>
    <meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8=
">
  </head>
  <body text=3D"#000000" bgcolor=3D"#FFFFFF">
    <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, 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"styled-by-prettify">([]</span><=
span
            style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an
            style=3D"color: #660;" class=3D"styled-by-prettify">-&gt;</span=
><span
            style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an
            style=3D"color: #008;" class=3D"styled-by-prettify">int</span><=
span
            style=3D"color: #000;" class=3D"styled-by-prettify"> i</span><s=
pan
            style=3D"color: #660;" class=3D"styled-by-prettify">)</span><sp=
an
            style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an
            style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an
            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;" 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"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">=
int</span><span
            style=3D"color: #000;" class=3D"styled-by-prettify"> bar</span>=
<span
            style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an
            style=3D"color: #008;" class=3D"styled-by-prettify">int</span><=
span
            style=3D"color: #000;" class=3D"styled-by-prettify"> j</span><s=
pan
            style=3D"color: #660;" class=3D"styled-by-prettify">)</span><sp=
an
            style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an
            style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an
            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;" class=3D"styled-by-prettify"> foo</span><span
            style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an
            style=3D"color: #000;" class=3D"styled-by-prettify">j</span><sp=
an
            style=3D"color: #660;" class=3D"styled-by-prettify">+</span><sp=
an
            style=3D"color: #066;" class=3D"styled-by-prettify">2</span><sp=
an
            style=3D"color: #660;" class=3D"styled-by-prettify">);</span><s=
pan
            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>
          </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
int</span><span
            style=3D"color: #000;" class=3D"styled-by-prettify"> foobar</sp=
an><span
            style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an
            style=3D"color: #008;" class=3D"styled-by-prettify">int</span><=
span
            style=3D"color: #000;" class=3D"styled-by-prettify"> j</span><s=
pan
            style=3D"color: #660;" class=3D"styled-by-prettify">)</span><sp=
an
            style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an
            style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an
            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;" class=3D"styled-by-prettify"> foo</span><span
            style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an
            style=3D"color: #066;" class=3D"styled-by-prettify">2</span><sp=
an
            style=3D"color: #660;" class=3D"styled-by-prettify">*</span><sp=
an
            style=3D"color: #000;" class=3D"styled-by-prettify">j</span><sp=
an
            style=3D"color: #660;" class=3D"styled-by-prettify">);</span><s=
pan
            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>
          </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, 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"styled-by-prettify">(</span><sp=
an
            style=3D"color: #008;" class=3D"styled-by-prettify">int</span><=
span
            style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an
            style=3D"color: #660;" class=3D"styled-by-prettify">(*</span><s=
pan
            style=3D"color: #000;" class=3D"styled-by-prettify">i</span><sp=
an
            style=3D"color: #660;" class=3D"styled-by-prettify">)(</span><s=
pan
            style=3D"color: #008;" class=3D"styled-by-prettify">void</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">void</span>=
<span
            style=3D"color: #660;" class=3D"styled-by-prettify">*</span><sp=
an
            style=3D"color: #000;" class=3D"styled-by-prettify"> stack_p</s=
pan><span
            style=3D"color: #660;" class=3D"styled-by-prettify">)</span><sp=
an
            style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an
            style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an
            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;" class=3D"styled-by-prettify"> i</span><span
            style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an
            style=3D"color: #000;" class=3D"styled-by-prettify">stack_p</sp=
an><span
            style=3D"color: #660;" class=3D"styled-by-prettify">);</span><s=
pan
            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">=
int</span><span
            style=3D"color: #000;" class=3D"styled-by-prettify"> bar</span>=
<span
            style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an
            style=3D"color: #008;" class=3D"styled-by-prettify">int</span><=
span
            style=3D"color: #000;" class=3D"styled-by-prettify"> j</span><s=
pan
            style=3D"color: #660;" class=3D"styled-by-prettify">)</span><sp=
an
            style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an
            style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an
            style=3D"color: #000;" class=3D"styled-by-prettify"><br>
            =C2=A0 </span><span style=3D"color: #008;"
            class=3D"styled-by-prettify">int</span><span style=3D"color:
            #000;" class=3D"styled-by-prettify"> closure</span><span
            style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an
            style=3D"color: #008;" class=3D"styled-by-prettify">void</span>=
<span
            style=3D"color: #660;" class=3D"styled-by-prettify">*</span><sp=
an
            style=3D"color: #000;" class=3D"styled-by-prettify"> stack_p</s=
pan><span
            style=3D"color: #660;" class=3D"styled-by-prettify">)</span><sp=
an
            style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an
            style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an
            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">int</span><span style=3D"color:
            #000;" class=3D"styled-by-prettify"> j </span><span
            style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><=
span
            style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an
            style=3D"color: #660;" class=3D"styled-by-prettify">*</span><sp=
an
            style=3D"color: #008;" class=3D"styled-by-prettify">static_cast=
</span><span
            style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span>=
<span
            style=3D"color: #008;" class=3D"styled-by-prettify">int</span><=
span
            style=3D"color: #660;" class=3D"styled-by-prettify">*&gt;(</spa=
n><span
            style=3D"color: #000;" class=3D"styled-by-prettify">stack_p </s=
pan><span
            style=3D"color: #660;" class=3D"styled-by-prettify">+</span><sp=
an
            style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an
            style=3D"color: #800;" class=3D"styled-by-prettify">/* offset j
            */</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">return</span><span style=3D"color:
            #000;" class=3D"styled-by-prettify"> j</span><span
            style=3D"color: #660;" class=3D"styled-by-prettify">+</span><sp=
an
            style=3D"color: #066;" class=3D"styled-by-prettify">2</span><sp=
an
            style=3D"color: #660;" class=3D"styled-by-prettify">;</span><sp=
an
            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: #008;"
            class=3D"styled-by-prettify">return</span><span style=3D"color:
            #000;" class=3D"styled-by-prettify"> foo</span><span
            style=3D"color: #660;" class=3D"styled-by-prettify">(&amp;</spa=
n><span
            style=3D"color: #000;" class=3D"styled-by-prettify">closure</sp=
an><span
            style=3D"color: #660;" class=3D"styled-by-prettify">,</span><sp=
an
            style=3D"color: #000;" class=3D"styled-by-prettify">
            __builtin_frame_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: #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><br>
          <span style=3D"color: #000;" class=3D"styled-by-prettify"><code
              class=3D"prettyprint"><span style=3D"color: #000;"
                class=3D"styled-by-prettify"><br>
              </span><span style=3D"color: #008;"
                class=3D"styled-by-prettify">int</span><span style=3D"color=
:
                #000;" class=3D"styled-by-prettify"> foobar</span><span
                style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span
                style=3D"color: #008;" class=3D"styled-by-prettify">int</sp=
an><span
                style=3D"color: #000;" class=3D"styled-by-prettify"> j</spa=
n><span
                style=3D"color: #660;" class=3D"styled-by-prettify">)</span=
><span
                style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span
                style=3D"color: #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">int</span><span style=3D"color=
:
                #000;" class=3D"styled-by-prettify"> closure</span><span
                style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span
                style=3D"color: #008;" class=3D"styled-by-prettify">void</s=
pan><span
                style=3D"color: #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-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">int</span><span style=3D"color=
:
                #000;" class=3D"styled-by-prettify"> j </span><span
                style=3D"color: #660;" class=3D"styled-by-prettify">=3D</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: #008;" class=3D"styled-by-prettify">static_=
cast</span><span
                style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</s=
pan><span
                style=3D"color: #008;" class=3D"styled-by-prettify">int</sp=
an><span
                style=3D"color: #660;" class=3D"styled-by-prettify">*&gt;(<=
/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">/*
                offset j */</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">return</span><span
                style=3D"color: #000;" class=3D"styled-by-prettify"> 2*j</s=
pan><span
                style=3D"color: #660;" class=3D"styled-by-prettify"></span>=
<span
                style=3D"color: #066;" 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 </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;" class=3D"styled-by-prettify"> foo</s=
pan><span
                style=3D"color: #660;" class=3D"styled-by-prettify">(&amp;<=
/span><span
                style=3D"color: #000;" class=3D"styled-by-prettify">closure=
</span><span
                style=3D"color: #660;" class=3D"styled-by-prettify">,</span=
><span
                style=3D"color: #000;" class=3D"styled-by-prettify">
                __builtin_frame_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: #660;" class=3D"styled-by-prettify">));</sp=
an><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>
              </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>
    <br>
    <br>
    Now, that's true it will be the same call syntax when it is passed
    by value/ref as when it is passed lazily, giving potential
    side-effects not be executed.<br>
    Guess what? That's already the case in template code when using
    &amp;&amp; and ||: those operators are short-circuiting when used on
    bools, but maybe overrided by any custom class losing their
    short-circuiting property.<br>
    In fact, this proposal would solve this last problem by allowing
    implementations of custom classes to also be short-circuiting.<br>
    <br>
    <div class=3D"moz-cite-prefix">On 26/05/2018 10:52,
      <a class=3D"moz-txt-link-abbreviated" href=3D"mailto:mihailnajdenov@g=
mail.com">mihailnajdenov@gmail.com</a> wrote:<br>
    </div>
    <blockquote type=3D"cite"
      cite=3D"mid:4ad104fa-1d8a-4e40-8275-ceefb0840d81@isocpp.org">
      <div dir=3D"ltr">
        <div>=C2=A0- How are these lazy arguments different then taking
          std::function/function_ref?=C2=A0</div>
        <div><br>
        </div>
        <div>=C2=A0- 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 - it will make the code misleading<br>
        </div>
        <div>In a way we will repeat the problem with non-const
          references, where one is not able to tell if the argument is
          passed by reference or not, without looking at the function
          interface!</div>
        <div><font face=3D"courier new,monospace"><br>
          </font></div>
        <div><font face=3D"arial,sans-serif">=C2=A0- But there is also a mo=
re
            serious issue - proliferation of anonymous classes!</font></div=
>
        <div><font face=3D"arial,sans-serif"><br>
          </font></div>
        <div><font face=3D"arial,sans-serif">Where right now the user </fon=
t>will
          have write clumsy lambda</div>
        <div><br>
        </div>
        <div><font face=3D"courier new,monospace">SaveAction([this]{
            return _filepath; });</font></div>
        <div><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; orphans: 2; text-align: left;
            text-decoration: none; text-indent: 0px; text-transform:
            none; -webkit-text-stroke-width: 0px; white-space: normal;
            word-spacing: 0px;">CopyAction([this]{ return _filepath; });</s=
pan></div>
        <div><span style=3D"background-color: transparent;
            border-bottom-color: rgb(34, 34, 34); border-bottom-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-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-style: normal; font-variant: 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;">MoveAction([this]{ return _filepath; });</s=
pan></div>
        <div><br>
        </div>
        <div>Sooner or later the user will see the obvious solution to
          use a variable for all cases</div>
        <div><br>
        </div>
        <div><font face=3D"courier new,monospace">std::function&lt;Filepath=
()&gt;
            _filepathSource =3D <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; orphans: 2; float: none;
              -webkit-text-stroke-width: 0px; background-color:
              transparent;">[this]{ return _filepath; };</span></font></div=
>
        <div><font face=3D"courier new,monospace"><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; orphans: 2; float:
              none; -webkit-text-stroke-width: 0px; background-color:
              transparent;"><br>
            </span></font></div>
        <div><font face=3D"courier new,monospace"><span style=3D"text-align=
:
              left; color: rgb(34, 34, 34); text-transform: none;
              text-indent: 0px; letter-spacing: normal; font-size: 13px;
              font-variant: normal; word-spacing: 0px; display: inline
              !important; white-space: normal; orphans: 2; float: none;
              -webkit-text-stroke-width: 0px; background-color:
              transparent;"><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;
                orphans: 2; text-align: left; text-decoration: none;
                text-indent: 0px; text-transform: none;
                -webkit-text-stroke-width: 0px; white-space: normal;
                word-spacing: 0px;">SaveAction(_filepathSource);</span><br>
            </span></font></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; orphans: 2; float: none; -webkit-text-stroke-width:
            0px; background-color: transparent;"><font face=3D"courier
              new,monospace">=E2=80=A6</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; orphans: 2; float: none; -webkit-text-stroke-width:
            0px; background-color: transparent;"><font face=3D"courier
              new,monospace">=E2=80=A6</font></span><span style=3D"text-ali=
gn:
            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; orphans: 2; float: none;
            -webkit-text-stroke-width: 0px; background-color:
            transparent;"><font face=3D"courier new,monospace"><br>
            </font></span></div>
        <div><font face=3D"courier new,monospace"><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; orphans: 2; float:
              none; -webkit-text-stroke-width: 0px; background-color:
              transparent;"><br>
            </span></font></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; orphans: 2; float: none; -webkit-text-stroke-width:
            0px; background-color: transparent;"><font
              face=3D"arial,sans-serif">The user will NEVER do that if he
              has transparent lambdas creation, which ultimately will
              lead to code bloat and/or more optimizer work.</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; orphans: 2; float: none; -webkit-text-stroke-width:
            0px; background-color: transparent;"><font
              face=3D"arial,sans-serif"><br>
            </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; orphans: 2; float: none; -webkit-text-stroke-width:
            0px; background-color: transparent;"><font
              face=3D"arial,sans-serif"><br>
            </font></span></div>
        <div><br>
        </div>
        <br>
        On Monday, May 14, 2018 at 4:16:07 PM UTC+3, <a class=3D"moz-txt-li=
nk-abbreviated" href=3D"mailto:floria...@gmail.com">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">Hello everyone,<br>
            <br>
            I would want to propose a new way to pass parameters 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
            parameters.<br>
            But this would be useful in some cases: for example
            overloading <span style=3D"font-family:courier new,monospace">o=
perator&amp;&amp;</span>
            and <span style=3D"font-family:courier new,monospace">operator|=
|</span>
            (and also <span style=3D"font-family:courier new,monospace">ope=
rator?:</span>
            when it will be overloadable).<br>
            It could also be used to implement a <span
              style=3D"font-family:courier new,monospace">select</span>
            function defined like this:<br>
            <div
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bo=
rder-style:solid;border-width:1px"><code>
                <div><span style=3D"color:#008">float</span><span
                    style=3D"color:#000"> </span><span style=3D"color:#008"=
>select</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"color:#000"> </span><span style=3D"color:#008"=
>float</span><span
                    style=3D"color:#000"> a</span><span style=3D"color:#660=
">,</span><span
                    style=3D"color:#000"> </span><span style=3D"color:#008"=
>float</span><span
                    style=3D"color:#000"> b</span><span style=3D"color:#660=
">,</span><span
                    style=3D"color:#000"> </span><span style=3D"color:#008"=
>float</span><span
                    style=3D"color:#000"> c</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">switch</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"=
>)</span><span
                    style=3D"color:#000"> </span><span style=3D"color:#660"=
>{</span><code><span
                      style=3D"color:#000"><br>
                      =C2=A0 =C2=A0 </span><span style=3D"color:#008">case<=
/span><span
                      style=3D"color:#000"> </span><span
                      style=3D"color:#066">0</span><span
                      style=3D"color:#660">:</span><span
                      style=3D"color:#000"><br>
                      =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008=
">return</span><span
                      style=3D"color:#000"> a</span><span
                      style=3D"color:#660">;</span><span
                      style=3D"color:#000"></span></code><code><span
                      style=3D"color:#000"><br>
                      =C2=A0 =C2=A0 </span><span style=3D"color:#008">case<=
/span><span
                      style=3D"color:#000"> </span><span
                      style=3D"color:#066">1</span><span
                      style=3D"color:#660">:</span><span
                      style=3D"color:#000"><br>
                      =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008=
">return</span><span
                      style=3D"color:#000"> b</span><span
                      style=3D"color:#660">;</span><span
                      style=3D"color:#000"></span></code><code><span
                      style=3D"color:#000"><br>
                      =C2=A0 =C2=A0 </span><span style=3D"color:#008">case<=
/span><span
                      style=3D"color:#000"> </span><span
                      style=3D"color:#066">2</span><span
                      style=3D"color:#660">:</span><span
                      style=3D"color:#000"><br>
                      =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008=
">return</span><span
                      style=3D"color:#000"> c</span><span
                      style=3D"color:#660">;</span><span
                      style=3D"color:#000"></span></code><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:#660">}</span><span
                    style=3D"color:#000"><br>
                  </span></div>
              </code></div>
            <br>
            The delayed evaluation is important to allow a parameter
            with side effects not to be executed if not needed, avoiding
            undefined behaviors:<br>
            <div
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bo=
rder-style:solid;border-width:1px"><code>
                <div><span style=3D"color:#606">float *p;<br>
                    <br>
                    if (p &amp;&amp; *p &gt; 0) { ... } // this is valid<br=
>
                    <br>
                    bool AND(bool a, bool b) {<br>
                    =C2=A0 return a &amp;&amp; b;<br>
                    }<br>
                    <br>
                    if (AND(p, *p &gt; 0)) { ... } // This is not<br>
                  </span><span style=3D"color:#660"></span></div>
              </code></div>
            <br>
            <br>
            I thought of 4 ways to express that:<br>
            <br>
            Type qualifier + implicit evaluation:<br>
            <div
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bo=
rder-style:solid;border-width:1px"><code>
                <div>
                  <div
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bo=
rder-style:solid;border-width:1px"><code>
                      <div><span style=3D"color:#008">float</span><span
                          style=3D"color:#000"> </span><span
                          style=3D"color:#008">select</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"color:#000"> </span><span
                          style=3D"color:#008">float @</span><span
                          style=3D"color:#000"> a</span><span
                          style=3D"color:#660">,</span><span
                          style=3D"color:#000"> </span><span
                          style=3D"color:#008">float</span><span
                          style=3D"color:#000"> @ b</span><span
                          style=3D"color:#660">,</span><span
                          style=3D"color:#000"> </span><span
                          style=3D"color:#008">float</span><span
                          style=3D"color:#000"> @ c</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">switch</=
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">)</span><span
                          style=3D"color:#000"> </span><span
                          style=3D"color:#660">{</span><code><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 </span><span style=3D"color:#008"=
>case</span><span
                            style=3D"color:#000"> </span><span
                            style=3D"color:#066">0</span><span
                            style=3D"color:#660">:</span><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"colo=
r:#008">return</span><span
                            style=3D"color:#000"> a</span><span
                            style=3D"color:#660">;</span><span
                            style=3D"color:#000"></span></code><code><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 </span><span style=3D"color:#008"=
>case</span><span
                            style=3D"color:#000"> </span><span
                            style=3D"color:#066">1</span><span
                            style=3D"color:#660">:</span><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"colo=
r:#008">return</span><span
                            style=3D"color:#000"> b</span><span
                            style=3D"color:#660">;</span><span
                            style=3D"color:#000"></span></code><code><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 </span><span style=3D"color:#008"=
>case</span><span
                            style=3D"color:#000"> </span><span
                            style=3D"color:#066">2</span><span
                            style=3D"color:#660">:</span><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"colo=
r:#008">return</span><span
                            style=3D"color:#000"> c</span><span
                            style=3D"color:#660">;</span><span
                            style=3D"color:#000"></span></code><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:#660">}</span><span
                          style=3D"color:#000"><br>
                        </span></div>
                    </code></div>
                  <span style=3D"color:#660"></span></div>
              </code></div>
            <br>
            Type qualifier + operator:<br>
            <div
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bo=
rder-style:solid;border-width:1px"><code>
                <div>
                  <div
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bo=
rder-style:solid;border-width:1px"><code>
                      <div><span style=3D"color:#008">float</span><span
                          style=3D"color:#000"> </span><span
                          style=3D"color:#008">select</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"color:#000"> </span><span
                          style=3D"color:#008">float @</span><span
                          style=3D"color:#000"> a</span><span
                          style=3D"color:#660">,</span><span
                          style=3D"color:#000"> </span><span
                          style=3D"color:#008">float</span><span
                          style=3D"color:#000"> @ b</span><span
                          style=3D"color:#660">,</span><span
                          style=3D"color:#000"> </span><span
                          style=3D"color:#008">float</span><span
                          style=3D"color:#000"> @ c</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">switch</=
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">)</span><span
                          style=3D"color:#000"> </span><span
                          style=3D"color:#660">{</span><code><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 </span><span style=3D"color:#008"=
>case</span><span
                            style=3D"color:#000"> </span><span
                            style=3D"color:#066">0</span><span
                            style=3D"color:#660">:</span><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"colo=
r:#008">return</span><span
                            style=3D"color:#000"> @a</span><span
                            style=3D"color:#660">;</span><span
                            style=3D"color:#000"></span></code><code><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 </span><span style=3D"color:#008"=
>case</span><span
                            style=3D"color:#000"> </span><span
                            style=3D"color:#066">1</span><span
                            style=3D"color:#660">:</span><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"colo=
r:#008">return</span><span
                            style=3D"color:#000"> @b</span><span
                            style=3D"color:#660">;</span><span
                            style=3D"color:#000"></span></code><code><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 </span><span style=3D"color:#008"=
>case</span><span
                            style=3D"color:#000"> </span><span
                            style=3D"color:#066">2</span><span
                            style=3D"color:#660">:</span><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"colo=
r:#008">return</span><span
                            style=3D"color:#000"> @c</span><span
                            style=3D"color:#660">;</span><span
                            style=3D"color:#000"></span></code><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:#660">}</span><span
                          style=3D"color:#000"><br>
                        </span></div>
                    </code></div>
                  <span style=3D"color:#660"></span></div>
              </code></div>
            <br>
            Type qualifier + callable:
            <div
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bo=
rder-style:solid;border-width:1px"><code>
                <div>
                  <div
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bo=
rder-style:solid;border-width:1px"><code>
                      <div><span style=3D"color:#008">float</span><span
                          style=3D"color:#000"> </span><span
                          style=3D"color:#008">select</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"color:#000"> </span><span
                          style=3D"color:#008">float</span><span
                          style=3D"color:#000"> @ a</span><span
                          style=3D"color:#660">,</span><span
                          style=3D"color:#000"> </span><span
                          style=3D"color:#008">float @</span><span
                          style=3D"color:#000"> b</span><span
                          style=3D"color:#660">,</span><span
                          style=3D"color:#000"> </span><span
                          style=3D"color:#008">float @</span><span
                          style=3D"color:#000"> c</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">switch</=
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">)</span><span
                          style=3D"color:#000"> </span><span
                          style=3D"color:#660">{</span><code><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 </span><span style=3D"color:#008"=
>case</span><span
                            style=3D"color:#000"> </span><span
                            style=3D"color:#066">0</span><span
                            style=3D"color:#660">:</span><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"colo=
r:#008">return</span><span
                            style=3D"color:#000"> a</span><span
                            style=3D"color:#660">();</span><span
                            style=3D"color:#000"></span></code><code><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 </span><span style=3D"color:#008"=
>case</span><span
                            style=3D"color:#000"> </span><span
                            style=3D"color:#066">1</span><span
                            style=3D"color:#660">:</span><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"colo=
r:#008">return</span><span
                            style=3D"color:#000"> b</span><span
                            style=3D"color:#660">();</span><span
                            style=3D"color:#000"></span></code><code><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 </span><span style=3D"color:#008"=
>case</span><span
                            style=3D"color:#000"> </span><span
                            style=3D"color:#066">2</span><span
                            style=3D"color:#660">:</span><span
                            style=3D"color:#000"><br>
                            =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"colo=
r:#008">return</span><span
                            style=3D"color:#000"> c</span><span
                            style=3D"color:#660">();</span><span
                            style=3D"color:#000"></span></code><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:#660">}</span><span
                          style=3D"color:#000"><br>
                        </span></div>
                    </code></div>
                  <span style=3D"color:#660"></span></div>
              </code></div>
            <br>
            STL type:<br>
            <div
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bo=
rder-style:solid;border-width:1px"><code>
                <div><span style=3D"color:#008">float</span><span
                    style=3D"color:#000"> </span><span style=3D"color:#008"=
>select</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"color:#000"> </span><code><span
                      style=3D"color:#008">std::expression&lt;float&gt;</sp=
an><span
                      style=3D"color:#000"></span></code><span
                    style=3D"color:#000"> a</span><span style=3D"color:#660=
">,</span><span
                    style=3D"color:#000"> </span><code><code><span
                        style=3D"color:#008">std::expression&lt;float&gt;</=
span><span
                        style=3D"color:#000"></span></code><span
                      style=3D"color:#000"></span></code><span
                    style=3D"color:#000"> b</span><span style=3D"color:#660=
">,</span><span
                    style=3D"color:#000"> </span><code><code><span
                        style=3D"color:#008">std::expression&lt;float&gt;</=
span><span
                        style=3D"color:#000"></span></code><span
                      style=3D"color:#000"></span></code><span
                    style=3D"color:#000"> c</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">switch</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"=
>)</span><span
                    style=3D"color:#000"> </span><span style=3D"color:#660"=
>{</span><code><span
                      style=3D"color:#000"><br>
                      =C2=A0 =C2=A0 </span><span style=3D"color:#008">case<=
/span><span
                      style=3D"color:#000"> </span><span
                      style=3D"color:#066">0</span><span
                      style=3D"color:#660">:</span><span
                      style=3D"color:#000"><br>
                      =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008=
">return</span><span
                      style=3D"color:#000"> a</span><span
                      style=3D"color:#660">();</span><span
                      style=3D"color:#000"></span></code><code><span
                      style=3D"color:#000"><br>
                      =C2=A0 =C2=A0 </span><span style=3D"color:#008">case<=
/span><span
                      style=3D"color:#000"> </span><span
                      style=3D"color:#066">1</span><span
                      style=3D"color:#660">:</span><span
                      style=3D"color:#000"><br>
                      =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008=
">return</span><span
                      style=3D"color:#000"> b</span><span
                      style=3D"color:#660">();</span><span
                      style=3D"color:#000"></span></code><code><span
                      style=3D"color:#000"><br>
                      =C2=A0 =C2=A0 </span><span style=3D"color:#008">case<=
/span><span
                      style=3D"color:#000"> </span><span
                      style=3D"color:#066">2</span><span
                      style=3D"color:#660">:</span><span
                      style=3D"color:#000"><br>
                      =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008=
">return</span><span
                      style=3D"color:#000"> c</span><span
                      style=3D"color:#660">();</span><span
                      style=3D"color:#000"></span></code><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:#660">}</span><span
                    style=3D"color:#000"><br>
                  </span></div>
              </code></div>
            <br>
            <br>
            In all the 3 cases, when the <span
              style=3D"font-family:courier new,monospace">select</span>
            function is called, a functor-like object is created
            computing the expression, and this object is then passed to
            the function.<br>
            <div
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bo=
rder-style:solid;border-width:1px"><code>
                <div><span style=3D"color:#606">float* p;<br>
                    int i;<br>
                    <br>
                    float r =3D select(i, 1.f, *p, std::sqrt(*p));<br>
                    <br>
                    // equivalent to:<br>
                    <br>
                    float r;<br>
                    switch (i) {<br>
                    =C2=A0 case 0:<br>
                    =C2=A0=C2=A0=C2=A0 r =3D 1.f;<br>
                    =C2=A0=C2=A0=C2=A0 break;</span><code><span style=3D"co=
lor:#606"><br>
                      =C2=A0 case 1:<br>
                      =C2=A0=C2=A0=C2=A0 r =3D *p;<br>
                      =C2=A0=C2=A0=C2=A0 break;</span></code><span style=3D=
"color:#606"><code><span
                        style=3D"color:#606"><br>
                        =C2=A0 case 2:<br>
                        =C2=A0=C2=A0=C2=A0 r =3D std::sqrt(*p);<br>
                        =C2=A0=C2=A0=C2=A0 break;</span></code></span></div=
>
                <div><span style=3D"color:#606"><code><span
                        style=3D"color:#606"></span></code>}<br>
                  </span><span style=3D"color:#660"></span></div>
              </code></div>
            <br>
            I really have the impression this could be very interesting
            in some corner cases where there is currently no
            alternatives to do that safely (and efficiently).<br>
            <br>
            Would this be sensible? Were there any attempt to formalize
            passing by expression?<br>
            Which way of expressing this should be preferred?<br>
            <br>
            I would be glad to answer any question.<br>
            <br>
            Florian<br>
          </div>
        </blockquote>
      </div>
    </blockquote>
    <br>
  </body>
</html>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/e35048a4-3937-659b-f8a5-c93ccc7397be%=
40gmail.com?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/e35048a4-3937-659b-f8a5-c93ccc7397be%=
40gmail.com</a>.<br />

--------------6E6AFE97BD508C535845AB42--

.


Author: mihailnajdenov@gmail.com
Date: Sun, 27 May 2018 10:08:29 -0700 (PDT)
Raw View
------=_Part_10089_31704569.1527440909319
Content-Type: multipart/alternative;
 boundary="----=_Part_10090_816286703.1527440909320"

------=_Part_10090_816286703.1527440909320
Content-Type: text/plain; charset="UTF-8"



On Sunday, May 27, 2018 at 7:19:31 PM UTC+3, 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.
>
>
I admit I skimmed a bit the part it is just a function pointer. I am also
allergic to "lets use lambda for this and that".
Of course the impl. limits their uses compared to normal functors, but I
guess that's normal, and that's makes them different.
I personally use late evaluation A LOT so I will keep an eye where
something like this could be used in my case, as I tend to sore the
functors which evaluate, not unlike the action example above.

Also the fact that we are still on the same stack alleviates the need to be
explicit about late evaluation on call site.

I will think about it more and write back if I have something to comment
more.

The topic of callable objects is very interesting to me. I also believe
entire function/functors system needs COMPLETE overhaul and be made core
language.
I have written some "mad scientist" ideas here if you have nothing better
to
do https://groups.google.com/a/isocpp.org/d/msg/std-proposals/Do4dMUSlS7Q/i5Pp6EKlBAAJ


--
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/12a15136-82ed-4706-b2c6-8d0def8177af%40isocpp.org.

------=_Part_10090_816286703.1527440909320
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Sunday, May 27, 2018 at 7:19:31 PM UTC+3, Flori=
an Lemaitre wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-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">-&gt;</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">&lt;</span><sp=
an style=3D"color:#008">int</span><span style=3D"color:#660">*&gt;(</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">(&amp;</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">&lt;</span=
><span style=3D"color:#008">int</span><span style=3D"color:#660">*&gt;(</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">(&amp;</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></div></blockquote><div><br></div><div>I admit I skimmed a bit the =
part it is just a function pointer. I am also allergic to &quot;lets use la=
mbda for this and that&quot;.</div><div>Of course the impl. limits their us=
es compared to normal functors, but I guess that&#39;s normal, and that&#39=
;s makes them different.</div><div>I personally use late evaluation A LOT s=
o I will keep an eye where something like this could be used in my case, as=
 I tend to sore the functors which evaluate, not unlike the action example =
above.</div><div><br></div><div>Also the fact that we are still on the same=
 stack alleviates the need to be explicit about late evaluation on call sit=
e.=C2=A0</div><div><br></div><div>I will think about it more and write back=
 if I have something to comment more.=C2=A0</div><div><br></div><div>The to=
pic of callable objects is very interesting to me. I also believe entire fu=
nction/functors system needs COMPLETE overhaul and be made core language.=
=C2=A0</div><div>I have written some &quot;mad scientist&quot; ideas here i=
f you have nothing better to do=C2=A0https://groups.google.com/a/isocpp.org=
/d/msg/std-proposals/Do4dMUSlS7Q/i5Pp6EKlBAAJ</div><div><br></div><div><br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF"=
 text=3D"#000000">
  </div>

</blockquote></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/12a15136-82ed-4706-b2c6-8d0def8177af%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/12a15136-82ed-4706-b2c6-8d0def8177af=
%40isocpp.org</a>.<br />

------=_Part_10090_816286703.1527440909320--

------=_Part_10089_31704569.1527440909319--

.


Author: Edward Catmur <ed@catmur.co.uk>
Date: Tue, 29 May 2018 07:09:43 -0700 (PDT)
Raw View
------=_Part_38781_1868072012.1527602983721
Content-Type: multipart/alternative;
 boundary="----=_Part_38782_1900935792.1527602983723"

------=_Part_38782_1900935792.1527602983723
Content-Type: text/plain; charset="UTF-8"



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?

--
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/74576851-b3ec-4061-9566-094ca75345a8%40isocpp.org.

------=_Part_38782_1900935792.1527602983723
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>On Sunday, 27 May 2018 17:19:31 UTC+1, Florian Lem=
aitre  wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
 =20
   =20
 =20
  <div text=3D"#000000" bgcolor=3D"#FFFFFF">
    <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">-&gt;</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">&lt;</span><sp=
an style=3D"color:#008">int</span><span style=3D"color:#660">*&gt;(</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">(&amp;</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">&lt;</span=
><span style=3D"color:#008">int</span><span style=3D"color:#660">*&gt;(</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">(&amp;</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 class=3D"pret=
typrint" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(1=
87, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-wor=
d;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> bar</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">([]</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">-&gt;</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> i<=
/span><font color=3D"#000000"><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"> </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">return</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> i</span><span style=3D"col=
or: #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></font><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">int</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><span style=3D"color: #000;" class=3D"styled-by-prettify">std<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">function_ref</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">()&gt;</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;" cla=
ss=3D"styled-by-prettify"> </span><font color=3D"#666600"><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;" class=
=3D"styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> f</span><span style=3D"color: #660;" class=3D"styled-b=
y-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></font><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> foo</span><span st=
yle=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">-&gt;</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: #000;" class=3D"styled-=
by-prettify"> i</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">)</span><span style=3D"color: #000;" 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"><br>=C2=A0 =C2=A0 </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> bar</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">i</span><span style=3D"color: #66=
0;" 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"> baz</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">([&amp;]</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 styl=
e=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=3D=
"color: #000;" 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"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">};</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
></span></div></code></div><div><span style=3D"font-family: monospace; back=
ground-color: rgb(250, 250, 250); color: rgb(102, 102, 0);"><br></span></di=
v><div>Indeed (and perhaps controversially), if the parentheses-suffixed fo=
rm is the only way to use the identifier of the parameter, then the parenth=
eses are redundant and can (should) be omitted, such that any use of the id=
entifier (in evaluated context) represents an evaluation of the argument ex=
pression (and thus a call through the code pointer):<span style=3D"font-fam=
ily: monospace; background-color: rgb(250, 250, 250); color: rgb(102, 102, =
0);"><br></span></div><div><br></div><div><div class=3D"prettyprint" style=
=3D"border-width: 1px; border-style: solid; border-color: rgb(187, 187, 187=
); background-color: rgb(250, 250, 250); word-wrap: break-word;"><code clas=
s=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"> bar</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: #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">int</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> i</span><font colo=
r=3D"#000000"><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"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> i</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">}</span></font><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> baz</s=
pan><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">function_ref</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">int</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">()&gt;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> f</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><font color=3D"#666600"><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: #008;" class=3D"styled-by-pret=
tify">return</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> f</span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">}</span></font><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> foo</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">([]</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">-&gt;</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> i<=
/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"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"=
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;" c=
lass=3D"styled-by-prettify">i</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"> baz</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">([&amp;]</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"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">return</span><span style=3D"color: #000;" c=
lass=3D"styled-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"><br></=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span></di=
v></code></div></div><div><br></div><div>The address-of operation would ret=
urn the address of the result of the argument expression, if the lazy param=
eter has a reference type, and would otherwise be ill-formed (since a [] -&=
gt; T lazy parameter would be a prvalue):</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: brea=
k-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span st=
yle=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: #0=
00;" class=3D"styled-by-prettify"> foo</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">-&gt;</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">in=
t</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;</sp=
an><span style=3D"color: #000;" 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"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"> </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">&amp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">i=
</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"> </span><span style=3D"color: #800;" =
class=3D"styled-by-prettify">// OK</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></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=
"> bar</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: #660;" class=3D"styled-by-prettify">-&gt;</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">int</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> i</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </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">return</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><span style=
=3D"color: #000;" 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"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: #800;" class=3D"styled-by-prettify=
">// ill-formed, taking address of a prvalue</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br></span></div></code></div><div><br></=
div><div>Again, this would be similar to references, where any use of an id=
entifier 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 b=
ound object rather than the reference itself.</div><div><br></div><div>This=
 would certainly make translation from existing code simple, but maybe it i=
s a step too far?</div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/74576851-b3ec-4061-9566-094ca75345a8%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/74576851-b3ec-4061-9566-094ca75345a8=
%40isocpp.org</a>.<br />

------=_Part_38782_1900935792.1527602983723--

------=_Part_38781_1868072012.1527602983721--

.


Author: mihailnajdenov@gmail.com
Date: Tue, 29 May 2018 07:36:28 -0700 (PDT)
Raw View
------=_Part_38770_38601452.1527604588464
Content-Type: multipart/alternative;
 boundary="----=_Part_38771_1190584593.1527604588466"

------=_Part_38771_1190584593.1527604588466
Content-Type: text/plain; charset="UTF-8"



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?




--
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/612d6f3c-a603-4dac-b8f5-feb79002472e%40isocpp.org.

------=_Part_38771_1190584593.1527604588466
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:09:43 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><br>On Sunday, 27 May 2018 17:19:31 UTC+1, Florian Lemaitre  wrote:<=
blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border=
-left:1px #ccc solid;padding-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">-&gt;</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">&lt;</span><sp=
an style=3D"color:#008">int</span><span style=3D"color:#660">*&gt;(</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">(&amp;</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">&lt;</span=
><span style=3D"color:#008">int</span><span style=3D"color:#660">*&gt;(</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">(&amp;</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">-&gt;</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">&lt;</span><span style=3D"color:#008">int</span><s=
pan style=3D"color:#660">()&gt;</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">-&gt;</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">([&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">();</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">-&gt;</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">&lt;</span><s=
pan style=3D"color:#008">int</span><span style=3D"color:#660">()&gt;</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=
">-&gt;</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 [] -=
&gt; 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">-&gt;</span><span style=3D"=
color:#000"> </span><span style=3D"color:#008">int</span><span style=3D"col=
or:#660">&amp;</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">-&gt;</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">&amp;</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">[] -&gt; int</font><span style=3D"back=
ground-color: transparent; border-bottom-color: rgb(0, 0, 0); border-bottom=
-style: none; border-bottom-width: 0px; border-image-outset: 0; border-imag=
e-repeat: stretch; border-image-slice: 100%; border-image-source: none; bor=
der-image-width: 1; border-left-color: rgb(0, 0, 0); border-left-style: non=
e; border-left-width: 0px; border-right-color: rgb(0, 0, 0); border-right-s=
tyle: none; border-right-width: 0px; border-top-color: rgb(0, 0, 0); border=
-top-style: none; border-top-width: 0px; color: rgb(0, 0, 0); font-family: =
&amp;quot;Arial&amp;quot;,&amp;quot;Helvetica&amp;quot;,sans-serif; font-si=
ze: 13px; font-style: normal; font-variant: normal; font-weight: 400; lette=
r-spacing: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px;=
 margin-top: 0px; orphans: 2; padding-bottom: 0px; padding-left: 0px; paddi=
ng-right: 0px; padding-top: 0px; text-align: left; text-decoration: none; t=
ext-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; whit=
e-space: normal; word-spacing: 0px;"> instead of=C2=A0<span style=3D"backgr=
ound-color: transparent; border-bottom-color: rgb(102, 102, 0); border-bott=
om-style: none; border-bottom-width: 0px; border-image-outset: 0; border-im=
age-repeat: stretch; border-image-slice: 100%; border-image-source: none; b=
order-image-width: 1; border-left-color: rgb(102, 102, 0); border-left-styl=
e: none; border-left-width: 0px; border-right-color: rgb(102, 102, 0); bord=
er-right-style: none; border-right-width: 0px; border-top-color: rgb(102, 1=
02, 0); border-top-style: none; border-top-width: 0px; color: rgb(102, 102,=
 0); font-family: &amp;quot;Arial&amp;quot;,&amp;quot;Helvetica&amp;quot;,s=
ans-serif; 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; orphans: 2; padding-bottom: 0px; paddin=
g-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; text-d=
ecoration: none; text-indent: 0px; text-transform: none; -webkit-text-strok=
e-width: 0px; white-space: normal; word-spacing: 0px;"></span><font face=3D=
"courier new,monospace">std::function_ref&lt;int()&gt; </font><font face=3D=
"arial,sans-serif">as a parameter?=C2=A0</font></span></div><div><br></div>=
<div><font color=3D"#b00000" face=3D"arial,sans-serif"></font><b></b><i></i=
><u></u><sub></sub><sup></sup><strike></strike><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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/612d6f3c-a603-4dac-b8f5-feb79002472e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/612d6f3c-a603-4dac-b8f5-feb79002472e=
%40isocpp.org</a>.<br />

------=_Part_38771_1190584593.1527604588466--

------=_Part_38770_38601452.1527604588464--

.


Author: mihailnajdenov@gmail.com
Date: Tue, 29 May 2018 07:40:52 -0700 (PDT)
Raw View
------=_Part_20977_779185645.1527604852989
Content-Type: multipart/alternative;
 boundary="----=_Part_20978_1567192847.1527604852990"

------=_Part_20978_1567192847.1527604852990
Content-Type: text/plain; charset="UTF-8"



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?

Why limit the interface to that just that callable?
I am not against the callable itself, but it does not make good interface,
does it?

--
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/e0189b4c-caff-4597-bfdc-e4716ba5827b%40isocpp.org.

------=_Part_20978_1567192847.1527604852990
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:09:43 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><br>On Sunday, 27 May 2018 17:19:31 UTC+1, Florian Lemaitre  wrote:<=
blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border=
-left:1px #ccc solid;padding-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">-&gt;</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">&lt;</span><sp=
an style=3D"color:#008">int</span><span style=3D"color:#660">*&gt;(</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">(&amp;</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">&lt;</span=
><span style=3D"color:#008">int</span><span style=3D"color:#660">*&gt;(</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">(&amp;</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">-&gt;</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">&lt;</span><span style=3D"color:#008">int</span><s=
pan style=3D"color:#660">()&gt;</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">-&gt;</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">([&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">();</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">-&gt;</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">&lt;</span><s=
pan style=3D"color:#008">int</span><span style=3D"color:#660">()&gt;</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=
">-&gt;</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 [] -=
&gt; 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">-&gt;</span><span style=3D"=
color:#000"> </span><span style=3D"color:#008">int</span><span style=3D"col=
or:#660">&amp;</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">-&gt;</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">&amp;</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><span style=3D"display: inline !important; flo=
at: none; background-color: transparent; color: rgb(34, 34, 34); font-famil=
y: &quot;Arial&quot;,&quot;Helvetica&quot;,sans-serif; font-size: 13px; fon=
t-style: normal; font-variant: normal; font-weight: 400; letter-spacing: no=
rmal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px=
; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal=
; word-spacing: 0px;">Question: Why would you ever want to use=C2=A0</span>=
<font face=3D"courier new,monospace" style=3D"background-color: transparent=
; border-bottom-color: rgb(34, 34, 34); border-bottom-style: none; border-b=
ottom-width: 0px; border-image-outset: 0; border-image-repeat: stretch; bor=
der-image-slice: 100%; border-image-source: none; border-image-width: 1; bo=
rder-left-color: rgb(34, 34, 34); border-left-style: none; border-left-widt=
h: 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: n=
one; border-top-width: 0px; color: rgb(34, 34, 34); font-family: courier ne=
w,monospace; font-size: 13px; font-style: normal; font-variant: normal; fon=
t-weight: 400; letter-spacing: normal; margin-bottom: 0px; margin-left: 0px=
; margin-right: 0px; margin-top: 0px; orphans: 2; padding-bottom: 0px; padd=
ing-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; text=
-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-str=
oke-width: 0px; white-space: normal; word-spacing: 0px;">[] -&gt; int</font=
><span style=3D"background-color: transparent; border-bottom-color: rgb(34,=
 34, 34); border-bottom-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, 3=
4); border-left-style: none; border-left-width: 0px; border-right-color: rg=
b(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; co=
lor: rgb(34, 34, 34); font-family: &amp;quot;Arial&amp;quot;,&amp;quot;Helv=
etica&amp;quot;,sans-serif; font-size: 13px; font-style: normal; font-varia=
nt: normal; font-weight: 400; letter-spacing: normal; margin-bottom: 0px; m=
argin-left: 0px; margin-right: 0px; margin-top: 0px; orphans: 2; padding-bo=
ttom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-al=
ign: left; text-decoration: none; text-indent: 0px; text-transform: none; -=
webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px;"> in=
stead of=C2=A0<span style=3D"border-bottom-color: rgb(34, 34, 34); border-b=
ottom-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-st=
yle: none; border-left-width: 0px; border-right-color: rgb(34, 34, 34); bor=
der-right-style: none; border-right-width: 0px; border-top-color: rgb(34, 3=
4, 34); border-top-style: 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; padding-top: 0px;"></span><font face=
=3D"courier new,monospace" style=3D"border-bottom-color: rgb(34, 34, 34); b=
order-bottom-style: none; border-bottom-width: 0px; border-image-outset: 0;=
 border-image-repeat: stretch; border-image-slice: 100%; border-image-sourc=
e: none; border-image-width: 1; border-left-color: rgb(34, 34, 34); border-=
left-style: none; border-left-width: 0px; border-right-color: rgb(34, 34, 3=
4); border-right-style: none; border-right-width: 0px; border-top-color: rg=
b(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=
: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;">std::funct=
ion_ref&lt;int()&gt; </font><font face=3D"arial,sans-serif" style=3D"border=
-bottom-color: rgb(34, 34, 34); border-bottom-style: none; border-bottom-wi=
dth: 0px; border-image-outset: 0; border-image-repeat: stretch; border-imag=
e-slice: 100%; border-image-source: none; border-image-width: 1; border-lef=
t-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; 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: 0=
px; padding-top: 0px;">as a parameter?=C2=A0</font></span></div><div><br></=
div><div>Why limit the interface to that just that callable?=C2=A0</div><di=
v>I am not against the callable itself, but it does not make good interface=
, does it?=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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/e0189b4c-caff-4597-bfdc-e4716ba5827b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/e0189b4c-caff-4597-bfdc-e4716ba5827b=
%40isocpp.org</a>.<br />

------=_Part_20978_1567192847.1527604852990--

------=_Part_20977_779185645.1527604852989--

.


Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 29 May 2018 07:48:43 -0700 (PDT)
Raw View
------=_Part_38912_2123031326.1527605323658
Content-Type: multipart/alternative;
 boundary="----=_Part_38913_873038836.1527605323658"

------=_Part_38913_873038836.1527605323658
Content-Type: text/plain; charset="UTF-8"

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.

--
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/71626882-1470-4e81-a29d-ac33a8211e3c%40isocpp.org.

------=_Part_38913_873038836.1527605323658
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Tuesday, May 29, 2018 at 10:40:53 AM UTC-4, mihailn...@=
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"><div></div><div><span style=3D"display:inline!important;float:none;backg=
round-color:transparent;color:rgb(34,34,34);font-family:&quot;Arial&quot;,&=
quot;Helvetica&quot;,sans-serif;font-size:13px;font-style:normal;font-varia=
nt:normal;font-weight:400;letter-spacing:normal;text-align:left;text-decora=
tion:none;text-indent:0px;text-transform:none;white-space:normal;word-spaci=
ng:0px">Question: Why would you ever want to use=C2=A0</span><font style=3D=
"background-color:transparent;border-bottom-color:rgb(34,34,34);border-bott=
om-style:none;border-bottom-width:0px;border-left-color:rgb(34,34,34);borde=
r-left-style:none;border-left-width:0px;border-right-color:rgb(34,34,34);bo=
rder-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);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;ma=
rgin-right:0px;margin-top:0px;padding-bottom:0px;padding-left:0px;padding-r=
ight:0px;padding-top:0px;text-align:left;text-decoration:none;text-indent:0=
px;text-transform:none;white-space:normal;word-spacing:0px" face=3D"courier=
 new,monospace">[] -&gt; int</font><span> instead of=C2=A0<span style=3D"bo=
rder-bottom-color:rgb(34,34,34);border-bottom-style:none;border-bottom-widt=
h:0px;border-left-color:rgb(34,34,34);border-left-style:none;border-left-wi=
dth: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;border-to=
p-width:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;margin-top:0=
px;padding-bottom:0px;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-bottom-width:0px;border-left-color:rgb(34,34,34);border-left-st=
yle:none;border-left-width:0px;border-right-color:rgb(34,34,34);border-righ=
t-style:none;border-right-width:0px;border-top-color:rgb(34,34,34);border-t=
op-style: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;padding-top:0px" face=3D"courier new,monospace">std::function_ref&lt;i=
nt()&gt; </font><font style=3D"border-bottom-color:rgb(34,34,34);border-bot=
tom-style:none;border-bottom-width:0px;border-left-color:rgb(34,34,34);bord=
er-left-style:none;border-left-width:0px;border-right-color:rgb(34,34,34);b=
order-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:0px;padding-left:0px;pad=
ding-right:0px;padding-top:0px" face=3D"arial,sans-serif">as a parameter?=
=C2=A0</font></span></div></div></blockquote><div><br></div><div>Because I =
don&#39;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 typ=
e. That this happens through &quot;a function&quot; is an <i>implementation=
 detail</i>, one that I have no interest in as the writer of that function.=
</div><br></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/71626882-1470-4e81-a29d-ac33a8211e3c%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/71626882-1470-4e81-a29d-ac33a8211e3c=
%40isocpp.org</a>.<br />

------=_Part_38913_873038836.1527605323658--

------=_Part_38912_2123031326.1527605323658--

.


Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Mon, 4 Jun 2018 12:26:39 -0400
Raw View
On 2018-06-04 00:53, Edward Catmur wrote:
> 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 :
>>> 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)

As far as obfuscation, this is no worse than macros.

>> This example is really great to show mutliple evaluations should not be
>> allowed, period.
>=20
> That depends, though. We're perfectly happy to write `while (a++) ...;` a=
nd
> it's not unreasonable to think that this facility might be used for
> functions with control flow that requires multiple invocation.

....but control-flow keywords are not much like functions. IMHO, if you
really need multiple evaluation, use a full lambda. The main problems I
see delayed evaluation trying to solve do not need multiple evaluation,
and permitting it adds an additional "gotcha".

--=20
Matthew

--=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/f5f16870-e555-34ad-fa7f-8b82c5f0a79d%40gmail.com=
..

.


Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Thu, 14 Jun 2018 00:19:25 -0700 (PDT)
Raw View
------=_Part_2033_277378652.1528960765248
Content-Type: multipart/alternative;
 boundary="----=_Part_2034_1736847373.1528960765249"

------=_Part_2034_1736847373.1528960765249
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

I have been pondering this proposal and P0927 for a while to see if I could=
=20
reconcile the two use cases of P0927 into one decent feature. I failed, and=
=20
I think that they must be served by different features.

The first use case is to avoid evaluating argument expressions if not=20
needed, which may be a performance optimization such as in a logging case=
=20
or semantically important as in a shortcut operator. The parameter of=20
std::optional::value_or would also be a good use case if it wasn't too late=
=20
for that. Here an important property is that the call site does not have to=
=20
care whether the parameter is lazy and that the argument can be forwarded=
=20
to another lazy parameter without problems. These two requirements mean=20
that temporaries of the argument expression must be preserved until the=20
callee returns and that the parameter must be allowed to be evaluatated=20
more than once (or forwarding would be ridiculously useless).

The second use case is for a nullary lambda which is usable inside the=20
callee by returning values when called. A primary feature is that the=20
callee should not have to be a template function. Thanks to guaranteed=20
return value elison this can allow initiating non-movable types as if=20
values by that type were magically passed into the callee. This would also=
=20
benefit from allowing an argument expression to be transformed to such a=20
nullary lambda but this is not a really important property compared to the=
=20
general need for a non-templated way of passing callables to functions. The=
=20
proposed std::function_ref class serves this purpose well.

With this in mind I argue for a lazy parameter passing method, maybe using=
=20
a void func([]->int x) syntax. This is still to be viewed as a parameter by=
=20
both caller and callee and not as a terse lambda.

The other use case I think is served well enough by std::function_ref. I=20
tried the idea of allowing a function_ref<T()> to have a constructor from a=
=20
[]->T but I couldn't get the semantics intiutive enough due to the=20
requirement that it should be able to return a non-copyable type.


Den m=C3=A5ndag 14 maj 2018 kl. 15:16:07 UTC+2 skrev floria...@gmail.com:
>
> 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.
> But this would be useful in some cases: for example overloading operator&=
&=20
> and operator|| (and also operator?: when it will be overloadable).
> It could also be used to implement a select function defined like this:
> float select(int i, float a, float b, float c) {
>   switch (i) {
>     case 0:
>       return a;
>     case 1:
>       return b;
>     case 2:
>       return c;
>   }
> }
>
> The delayed evaluation is important to allow a parameter with side effect=
s=20
> not to be executed if not needed, avoiding undefined behaviors:
> float *p;
>
> if (p && *p > 0) { ... } // this is valid
>
> bool AND(bool a, bool b) {
>   return a && b;
> }
>
> if (AND(p, *p > 0)) { ... } // This is not
>
>
> I thought of 4 ways to express that:
>
> Type qualifier + implicit evaluation:
> float select(int i, float @ a, float @ b, float @ c) {
>   switch (i) {
>     case 0:
>       return a;
>     case 1:
>       return b;
>     case 2:
>       return c;
>   }
> }
>
> Type qualifier + operator:
> float select(int i, float @ a, float @ b, float @ c) {
>   switch (i) {
>     case 0:
>       return @a;
>     case 1:
>       return @b;
>     case 2:
>       return @c;
>   }
> }
>
> Type qualifier + callable:
> float select(int i, float @ a, float @ b, float @ c) {
>   switch (i) {
>     case 0:
>       return a();
>     case 1:
>       return b();
>     case 2:
>       return c();
>   }
> }
>
> STL type:
> float select(int i, std::expression<float> a, std::expression<float> b,=
=20
> std::expression<float> c) {
>   switch (i) {
>     case 0:
>       return a();
>     case 1:
>       return b();
>     case 2:
>       return c();
>   }
> }
>
>
> In all the 3 cases, when the select function is called, a functor-like=20
> object is created computing the expression, and this object is then passe=
d=20
> to the function.
> float* p;
> int i;
>
> float r =3D select(i, 1.f, *p, std::sqrt(*p));
>
> // equivalent to:
>
> float r;
> switch (i) {
>   case 0:
>     r =3D 1.f;
>     break;
>   case 1:
>     r =3D *p;
>     break;
>   case 2:
>     r =3D std::sqrt(*p);
>     break;
> }
>
> I really have the impression this could be very interesting in some corne=
r=20
> cases where there is currently no alternatives to do that safely (and=20
> efficiently).
>
> Would this be sensible? Were there any attempt to formalize passing by=20
> expression?
> Which way of expressing this should be preferred?
>
> I would be glad to answer any question.
>
> 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/24c0e6f4-bac1-4c1d-ba13-0019ecd62605%40isocpp.or=
g.

------=_Part_2034_1736847373.1528960765249
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">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 feat=
ure. 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 expre=
ssions if not needed, which may be a performance optimization such as in a =
logging case or semantically important as in a shortcut operator. The param=
eter of std::optional::value_or would also be a good use case if it wasn&#3=
9;t too late for that. Here an important property is that the call site doe=
s not have to care whether the parameter is lazy and that the argument can =
be forwarded to another lazy parameter without problems. These two requirem=
ents mean that temporaries of the argument expression must be preserved unt=
il the callee returns and that the parameter must be allowed to be evaluata=
ted more than once (or forwarding would be ridiculously useless).</div><div=
><br></div><div>The second use case is for a nullary lambda which is usable=
 inside the callee by returning values when called. A primary feature is th=
at the callee should not have to be a template function. Thanks to guarante=
ed return value elison this can allow initiating non-movable types as if va=
lues by that type were magically passed into the callee. This would also be=
nefit from allowing an argument expression to be transformed to such a null=
ary lambda but this is not a really important property compared to the gene=
ral need for a non-templated way of passing callables to functions. The pro=
posed std::function_ref class serves this purpose well.</div><div><br></div=
><div>With this in mind I argue for a lazy parameter passing method, maybe =
using a void func([]-&gt;int x) syntax. This is still to be viewed as a par=
ameter by both caller and callee and not as a terse lambda.</div><div><br><=
/div><div>The other use case I think is served well enough by std::function=
_ref. I tried the idea of allowing a function_ref&lt;T()&gt; to have a cons=
tructor from a []-&gt;T but I couldn&#39;t get the semantics intiutive enou=
gh due to the requirement that it should be able to return a non-copyable t=
ype.</div><div><br><br>Den m=C3=A5ndag 14 maj 2018 kl. 15:16:07 UTC+2 skrev=
 floria...@gmail.com:<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">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>But this would be useful in some cases: for example overloading =
<span style=3D"font-family:courier new,monospace">operator&amp;&amp;</span>=
 and <span style=3D"font-family:courier new,monospace">operator||</span> (a=
nd also <span style=3D"font-family:courier new,monospace">operator?:</span>=
 when it will be overloadable).<br>It could also be used to implement a <sp=
an style=3D"font-family:courier new,monospace">select</span> function defin=
ed like this:<br><div style=3D"background-color:rgb(250,250,250);border-col=
or:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><span s=
tyle=3D"color:#008">float</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#008">select</span><span style=3D"color:#660">(</span><span st=
yle=3D"color:#008">int</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:#008">float</span><span style=3D"color:#000"> a</span><span style=3D"=
color:#660">,</span><span style=3D"color:#000"> </span><span style=3D"color=
:#008">float</span><span style=3D"color:#000"> b</span><span style=3D"color=
:#660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#008=
">float</span><span style=3D"color:#000"> c</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=
">switch</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">)</=
span><span style=3D"color:#000"> </span><span style=3D"color:#660">{</span>=
<code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"co=
lor:#008">case</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#066">0</span><span style=3D"color:#660">:</span><span style=3D"color:#00=
0"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span>=
<span style=3D"color:#000"> a</span><span style=3D"color:#660">;</span><spa=
n style=3D"color:#000"></span></code><code><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#066">1</span><span style=3D"color:=
#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><s=
pan style=3D"color:#008">return</span><span style=3D"color:#000"> b</span><=
span style=3D"color:#660">;</span><span style=3D"color:#000"></span></code>=
<code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"co=
lor:#008">case</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#066">2</span><span style=3D"color:#660">:</span><span style=3D"color:#00=
0"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span>=
<span style=3D"color:#000"> c</span><span style=3D"color:#660">;</span><spa=
n style=3D"color:#000"></span></code><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:#660">}</span><span style=3D"color:#000"><br></sp=
an></div></code></div><br>The delayed evaluation is important to allow a pa=
rameter with side effects not to be executed if not needed, avoiding undefi=
ned behaviors:<br><div style=3D"background-color:rgb(250,250,250);border-co=
lor:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><span =
style=3D"color:#606">float *p;<br><br>if (p &amp;&amp; *p &gt; 0) { ... } /=
/ this is valid<br><br>bool AND(bool a, bool b) {<br>=C2=A0 return a &amp;&=
amp; b;<br>}<br><br>if (AND(p, *p &gt; 0)) { ... } // This is not<br></span=
><span style=3D"color:#660"></span></div></code></div><br><br>I thought of =
4 ways to express that:<br><br>Type qualifier + implicit evaluation:<br><di=
v style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);=
border-style:solid;border-width:1px"><code><div><div style=3D"background-co=
lor:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;borde=
r-width:1px"><code><div><span style=3D"color:#008">float</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">select</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:#008">float @</span><span style=3D"co=
lor:#000"> a</span><span style=3D"color:#660">,</span><span style=3D"color:=
#000"> </span><span style=3D"color:#008">float</span><span style=3D"color:#=
000"> @ b</span><span style=3D"color:#660">,</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#008">float</span><span style=3D"color:#000=
"> @ c</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">switch</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">)</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">{</span><code><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"=
color:#000"> </span><span style=3D"color:#066">0</span><span style=3D"color=
:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><=
span style=3D"color:#008">return</span><span style=3D"color:#000"> a</span>=
<span style=3D"color:#660">;</span><span style=3D"color:#000"></span></code=
><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"c=
olor:#008">case</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#066">1</span><span style=3D"color:#660">:</span><span style=3D"color:#0=
00"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span=
><span style=3D"color:#000"> b</span><span style=3D"color:#660">;</span><sp=
an style=3D"color:#000"></span></code><code><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#066">2</span><span style=3D"color:=
#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><s=
pan style=3D"color:#008">return</span><span style=3D"color:#000"> c</span><=
span style=3D"color:#660">;</span><span style=3D"color:#000"></span></code>=
<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:#660">}</sp=
an><span style=3D"color:#000"><br></span></div></code></div><span style=3D"=
color:#660"></span></div></code></div><br>Type qualifier + operator:<br><di=
v style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);=
border-style:solid;border-width:1px"><code><div><div style=3D"background-co=
lor:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;borde=
r-width:1px"><code><div><span style=3D"color:#008">float</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">select</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:#008">float @</span><span style=3D"co=
lor:#000"> a</span><span style=3D"color:#660">,</span><span style=3D"color:=
#000"> </span><span style=3D"color:#008">float</span><span style=3D"color:#=
000"> @ b</span><span style=3D"color:#660">,</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#008">float</span><span style=3D"color:#000=
"> @ c</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">switch</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">)</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">{</span><code><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"=
color:#000"> </span><span style=3D"color:#066">0</span><span style=3D"color=
:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><=
span style=3D"color:#008">return</span><span style=3D"color:#000"> @a</span=
><span style=3D"color:#660">;</span><span style=3D"color:#000"></span></cod=
e><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"=
color:#008">case</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#066">1</span><span style=3D"color:#660">:</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</spa=
n><span style=3D"color:#000"> @b</span><span style=3D"color:#660">;</span><=
span style=3D"color:#000"></span></code><code><span style=3D"color:#000"><b=
r>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span style=3D=
"color:#000"> </span><span style=3D"color:#066">2</span><span style=3D"colo=
r:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span>=
<span style=3D"color:#008">return</span><span style=3D"color:#000"> @c</spa=
n><span style=3D"color:#660">;</span><span style=3D"color:#000"></span></co=
de><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:#660">}<=
/span><span style=3D"color:#000"><br></span></div></code></div><span style=
=3D"color:#660"></span></div></code></div><br>Type qualifier + callable:<di=
v style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);=
border-style:solid;border-width:1px"><code><div><div style=3D"background-co=
lor:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;borde=
r-width:1px"><code><div><span style=3D"color:#008">float</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">select</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:#008">float</span><span style=3D"colo=
r:#000"> @ a</span><span style=3D"color:#660">,</span><span style=3D"color:=
#000"> </span><span style=3D"color:#008">float @</span><span style=3D"color=
:#000"> b</span><span style=3D"color:#660">,</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#008">float @</span><span style=3D"color:#0=
00"> c</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">switch</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">)</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">{</span><code><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"=
color:#000"> </span><span style=3D"color:#066">0</span><span style=3D"color=
:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><=
span style=3D"color:#008">return</span><span style=3D"color:#000"> a</span>=
<span style=3D"color:#660">();</span><span style=3D"color:#000"></span></co=
de><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D=
"color:#008">case</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#066">1</span><span style=3D"color:#660">:</span><span style=3D"color:=
#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</sp=
an><span style=3D"color:#000"> b</span><span style=3D"color:#660">();</span=
><span style=3D"color:#000"></span></code><code><span style=3D"color:#000">=
<br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span style=
=3D"color:#000"> </span><span style=3D"color:#066">2</span><span style=3D"c=
olor:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </sp=
an><span style=3D"color:#008">return</span><span style=3D"color:#000"> c</s=
pan><span style=3D"color:#660">();</span><span style=3D"color:#000"></span>=
</code><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#6=
60">}</span><span style=3D"color:#000"><br></span><span style=3D"color:#660=
">}</span><span style=3D"color:#000"><br></span></div></code></div><span st=
yle=3D"color:#660"></span></div></code></div><br>STL type:<br><div style=3D=
"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-sty=
le:solid;border-width:1px"><code><div><span style=3D"color:#008">float</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#008">select</spa=
n><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"color:#000"> </span><code><span style=3D"color:#008">std::express=
ion&lt;float&gt;</span><span style=3D"color:#000"></span></code><span style=
=3D"color:#000"> a</span><span style=3D"color:#660">,</span><span style=3D"=
color:#000"> </span><code><code><span style=3D"color:#008">std::expression&=
lt;float&gt;</span><span style=3D"color:#000"></span></code><span style=3D"=
color:#000"></span></code><span style=3D"color:#000"> b</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> </span><code><code><spa=
n style=3D"color:#008">std::expression&lt;float&gt;</span><span style=3D"co=
lor:#000"></span></code><span style=3D"color:#000"></span></code><span styl=
e=3D"color:#000"> c</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"><br>=C2=A0 </span><span style=3D"color:#008">switch</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#660">(</span><span style=3D=
"color:#000">i</span><span style=3D"color:#660">)</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#660">{</span><code><span style=3D"col=
or:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#066">0</span><span st=
yle=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:#00=
0"> a</span><span style=3D"color:#660">();</span><span style=3D"color:#000"=
></span></code><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><s=
pan style=3D"color:#008">case</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#066">1</span><span style=3D"color:#660">:</span><span sty=
le=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008=
">return</span><span style=3D"color:#000"> b</span><span style=3D"color:#66=
0">();</span><span style=3D"color:#000"></span></code><code><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#066">2</span><span=
 style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:=
#000"> c</span><span style=3D"color:#660">();</span><span style=3D"color:#0=
00"></span></code><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:#660">}</span><span style=3D"color:#000"><br></span></div></code>=
</div><br><br>In all the 3 cases, when the <span style=3D"font-family:couri=
er new,monospace">select</span> function is called, a functor-like object i=
s created computing the expression, and this object is then passed to the f=
unction.<br><div style=3D"background-color:rgb(250,250,250);border-color:rg=
b(187,187,187);border-style:solid;border-width:1px"><code><div><span style=
=3D"color:#606">float* p;<br>int i;<br><br>float r =3D select(i, 1.f, *p, s=
td::sqrt(*p));<br><br>// equivalent to:<br><br>float r;<br>switch (i) {<br>=
=C2=A0 case 0:<br>=C2=A0=C2=A0=C2=A0 r =3D 1.f;<br>=C2=A0=C2=A0=C2=A0 break=
;</span><code><span style=3D"color:#606"><br>=C2=A0 case 1:<br>=C2=A0=C2=A0=
=C2=A0 r =3D *p;<br>=C2=A0=C2=A0=C2=A0 break;</span></code><span style=3D"c=
olor:#606"><code><span style=3D"color:#606"><br>=C2=A0 case 2:<br>=C2=A0=C2=
=A0=C2=A0 r =3D std::sqrt(*p);<br>=C2=A0=C2=A0=C2=A0 break;</span></code></=
span></div><div><span style=3D"color:#606"><code><span style=3D"color:#606"=
></span></code>}<br></span><span style=3D"color:#660"></span></div></code><=
/div><br>I really have the impression this could be very interesting in som=
e corner cases where there is currently no alternatives to do that safely (=
and efficiently).<br><br>Would this be sensible? Were there any attempt to =
formalize passing by expression?<br>Which way of expressing this should be =
preferred?<br><br>I would be glad to answer any question.<br><br>Florian<br=
></div></blockquote></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/24c0e6f4-bac1-4c1d-ba13-0019ecd62605%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/24c0e6f4-bac1-4c1d-ba13-0019ecd62605=
%40isocpp.org</a>.<br />

------=_Part_2034_1736847373.1528960765249--

------=_Part_2033_277378652.1528960765248--

.


Author: florian.csdt@gmail.com
Date: Thu, 14 Jun 2018 04:37:16 -0700 (PDT)
Raw View
------=_Part_2999_1954660082.1528976236376
Content-Type: multipart/alternative;
 boundary="----=_Part_3000_1134278324.1528976236378"

------=_Part_3000_1134278324.1528976236378
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

I don't clearly get your point.

If in your second use case, you don't want multiple evaluations, then both=
=20
use cases are possible within a single feature (as I already showed=20
earlier).
If you do, std::function_ref would be the answer.

There is a case that would be improved with=20
struct Foo {
  int i;
  Foo(const Foo&) =3D delete;
};

template <class T>
struct Bar {
  T* p =3D nullptr;
  ~Bar() { delete p; }

  void set(T const& v) { p =3D new T(v); }
  void set_lazy([] -> T v) { p =3D new T(v()); }
  void set_func(std::function_ref<T()> f) { return new T(f()); }
  template <class... Args>
  void emplace(Args&&... args) { p =3D new T(std::forward<Args>(args)...); =
}
};

Bar<Foo> bar;
// We want to construct Foo from { .i =3D 1 } // designated initializer lis=
t
bar.set({ .i =3D 1 }); // Foo is not copyable
bar.set_lazy({ .i =3D 1 }); // this is fine
bar.emplace(/* what here? */); // designated initializer list construction=
=20
is not a constructor
bar.set_func([]() -> Foo { return { .i =3D 1 }; }); // name has to be=20
mentionned here

In this case, set cannot work because Foo is non-copyable.
emplace cannot work because it is not a constructor (and it is not=20
type-erased).
And you would need to name the type to make set_func works (even with an=20
hypothetical terse lambda syntax).
While set_lazy would have all the good properties we want here.

Le jeudi 14 juin 2018 09:19:25 UTC+2, Bengt Gustafsson a =C3=A9crit :
>
> I have been pondering this proposal and P0927 for a while to see if I=20
> could reconcile the two use cases of P0927 into one decent feature. I=20
> failed, and I think that they must be served by different features.
>
> The first use case is to avoid evaluating argument expressions if not=20
> needed, which may be a performance optimization such as in a logging case=
=20
> or semantically important as in a shortcut operator. The parameter of=20
> std::optional::value_or would also be a good use case if it wasn't too la=
te=20
> for that. Here an important property is that the call site does not have =
to=20
> care whether the parameter is lazy and that the argument can be forwarded=
=20
> to another lazy parameter without problems. These two requirements mean=
=20
> that temporaries of the argument expression must be preserved until the=
=20
> callee returns and that the parameter must be allowed to be evaluatated=
=20
> more than once (or forwarding would be ridiculously useless).
>
> The second use case is for a nullary lambda which is usable inside the=20
> callee by returning values when called. A primary feature is that the=20
> callee should not have to be a template function. Thanks to guaranteed=20
> return value elison this can allow initiating non-movable types as if=20
> values by that type were magically passed into the callee. This would als=
o=20
> benefit from allowing an argument expression to be transformed to such a=
=20
> nullary lambda but this is not a really important property compared to th=
e=20
> general need for a non-templated way of passing callables to functions. T=
he=20
> proposed std::function_ref class serves this purpose well.
>
> With this in mind I argue for a lazy parameter passing method, maybe usin=
g=20
> a void func([]->int x) syntax. This is still to be viewed as a parameter =
by=20
> both caller and callee and not as a terse lambda.
>
> The other use case I think is served well enough by std::function_ref. I=
=20
> tried the idea of allowing a function_ref<T()> to have a constructor from=
 a=20
> []->T but I couldn't get the semantics intiutive enough due to the=20
> requirement that it should be able to return a non-copyable type.
>
>
> Den m=C3=A5ndag 14 maj 2018 kl. 15:16:07 UTC+2 skrev floria...@gmail.com:
>>
>> 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.
>> But this would be useful in some cases: for example overloading=20
>> operator&& and operator|| (and also operator?: when it will be=20
>> overloadable).
>> It could also be used to implement a select function defined like this:
>> float select(int i, float a, float b, float c) {
>>   switch (i) {
>>     case 0:
>>       return a;
>>     case 1:
>>       return b;
>>     case 2:
>>       return c;
>>   }
>> }
>>
>> The delayed evaluation is important to allow a parameter with side=20
>> effects not to be executed if not needed, avoiding undefined behaviors:
>> float *p;
>>
>> if (p && *p > 0) { ... } // this is valid
>>
>> bool AND(bool a, bool b) {
>>   return a && b;
>> }
>>
>> if (AND(p, *p > 0)) { ... } // This is not
>>
>>
>> I thought of 4 ways to express that:
>>
>> Type qualifier + implicit evaluation:
>> float select(int i, float @ a, float @ b, float @ c) {
>>   switch (i) {
>>     case 0:
>>       return a;
>>     case 1:
>>       return b;
>>     case 2:
>>       return c;
>>   }
>> }
>>
>> Type qualifier + operator:
>> float select(int i, float @ a, float @ b, float @ c) {
>>   switch (i) {
>>     case 0:
>>       return @a;
>>     case 1:
>>       return @b;
>>     case 2:
>>       return @c;
>>   }
>> }
>>
>> Type qualifier + callable:
>> float select(int i, float @ a, float @ b, float @ c) {
>>   switch (i) {
>>     case 0:
>>       return a();
>>     case 1:
>>       return b();
>>     case 2:
>>       return c();
>>   }
>> }
>>
>> STL type:
>> float select(int i, std::expression<float> a, std::expression<float> b,=
=20
>> std::expression<float> c) {
>>   switch (i) {
>>     case 0:
>>       return a();
>>     case 1:
>>       return b();
>>     case 2:
>>       return c();
>>   }
>> }
>>
>>
>> In all the 3 cases, when the select function is called, a functor-like=
=20
>> object is created computing the expression, and this object is then pass=
ed=20
>> to the function.
>> float* p;
>> int i;
>>
>> float r =3D select(i, 1.f, *p, std::sqrt(*p));
>>
>> // equivalent to:
>>
>> float r;
>> switch (i) {
>>   case 0:
>>     r =3D 1.f;
>>     break;
>>   case 1:
>>     r =3D *p;
>>     break;
>>   case 2:
>>     r =3D std::sqrt(*p);
>>     break;
>> }
>>
>> I really have the impression this could be very interesting in some=20
>> corner cases where there is currently no alternatives to do that safely=
=20
>> (and efficiently).
>>
>> Would this be sensible? Were there any attempt to formalize passing by=
=20
>> expression?
>> Which way of expressing this should be preferred?
>>
>> I would be glad to answer any question.
>>
>> 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/e692d0e1-02e3-4d5e-baff-7c681089fba9%40isocpp.or=
g.

------=_Part_3000_1134278324.1528976236378
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I don&#39;t clearly get your point.<br><br>If in your seco=
nd use case, you don&#39;t want multiple evaluations, then both use cases a=
re possible within a single feature (as I already showed earlier).<br>If yo=
u do, std::function_ref would be the answer.<br><br>There is a case that wo=
uld be improved with <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"prettypri=
nt"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">struct</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-pretti=
fy">Foo</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"><br>=C2=A0 </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> i</span><span style=3D"col=
or: #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: #606=
;" class=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">const</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: #660;" class=3D"styled-by-prettify">&amp;=
)</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 st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">delete</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"styl=
ed-by-prettify"><br><br></span><span style=3D"color: #008;" class=3D"styled=
-by-prettify">template</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">&lt;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">cla=
ss</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> T</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=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: #6=
06;" class=3D"styled-by-prettify">Bar</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"><br>=C2=A0 T</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 style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">nullptr</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"c=
olor: #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: #6=
06;" class=3D"styled-by-prettify">Bar</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: #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">delete</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> p</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>=C2=A0 </span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">void</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">set</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: #008;" class=3D"styled-by-prettify">const=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> 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: #6=
60;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> p </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">=3D</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"styled-by-prettify"> T</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify">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;" cl=
ass=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">void</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> set_lazy</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">([]</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">-&gt=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> T v</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: #00=
0;" class=3D"styled-by-prettify"> p </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">new</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">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"><br>=C2=A0 </span><span style=3D"color: #008;"=
 class=3D"styled-by-prettify">void</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> set_func</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">=
function_ref</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">T</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">()&gt;</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> f</span><span st=
yle=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">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"style=
d-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"styled-by-prettify"> T</s=
pan><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"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"><code class=3D"prettyprint"><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">template</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">&lt;</span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">class</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: #606;" class=3D"styled-by-prettify">Args</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</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">void</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> emplace</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"co=
lor: #606;" class=3D"styled-by-prettify">Args</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">&amp;&amp;...</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> args</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-pret=
tify"> p </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;" class=3D"styled-by-prettify">new</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;" 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">&lt;</span><span style=3D"color: #606;" class=3D"styled-by=
-prettify">Args</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">&gt;(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
args</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: #660;" class=3D"styled-by-prettify">}</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span></code></span><sp=
an 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: #606;" class=3D"styled-by-prettify">Bar</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #6=
06;" class=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> bar</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></span><span style=3D"color: #800;" class=3D"styled-by-prettify">=
// We want to construct Foo from { .i =3D 1 } // designated initializer lis=
t</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>bar</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">set</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">i </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">1</=
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"> </span><span style=3D"color=
: #800;" class=3D"styled-by-prettify">// Foo is not copyable</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>bar</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">set_lazy</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">({</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">i </span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #066;" class=3D"styled-by-prettify">1</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: #800;" cl=
ass=3D"styled-by-prettify">// this is fine</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>bar</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">emplace</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">(</span><span style=3D"color: #800;" class=3D"styled-by-pr=
ettify">/* what here? */</span><span style=3D"color: #660;" class=3D"styled=
-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">// =
designated initializer list construction is not a constructor</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>bar</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">set_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">-&gt;</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-=
prettify">Foo</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"> </span><span s=
tyle=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=
: #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">i </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #066;" class=3D"styled-by-prettify">1</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: #660;" cl=
ass=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">// name has to be mentionned here</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br></span></div></code></div><br>In this=
 case, <span style=3D"font-family: courier new, monospace;">set </span>cann=
ot work because <span style=3D"font-family: courier new, monospace;">Foo</s=
pan> is non-copyable.<br><span style=3D"font-family: courier new, monospace=
;">emplace</span> cannot work because it is not a constructor (and it is no=
t type-erased).<br>And you would need to name the type to make <span style=
=3D"font-family: courier new, monospace;">set_func</span> works (even with =
an hypothetical terse lambda syntax).<br>While <span style=3D"font-family: =
courier new, monospace;">set_lazy</span> would have all the good properties=
 we want here.<br><br>Le jeudi 14 juin 2018 09:19:25 UTC+2, Bengt Gustafsso=
n 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">I have been pondering this proposal and P0927 for a while to see i=
f I could reconcile the two use cases of P0927 into one decent feature. I f=
ailed, and I think that they must be served by different features.<div><br>=
</div><div>The first use case is to avoid evaluating argument expressions i=
f 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&#39;t too =
late for that. Here an important property is that the call site does not ha=
ve to care whether the parameter is lazy and that the argument can be forwa=
rded to another lazy parameter without problems. These two requirements mea=
n that temporaries of the argument expression must be preserved until the c=
allee returns and that the parameter must be allowed to be evaluatated more=
 than once (or forwarding would be ridiculously useless).</div><div><br></d=
iv><div>The second use case is for a nullary lambda which is usable inside =
the callee by returning values when called. A primary feature is that the c=
allee should not have to be a template function. Thanks to guaranteed retur=
n value elison this can allow initiating non-movable types as if values by =
that type were magically passed into the callee. This would also benefit fr=
om allowing an argument expression to be transformed to such a nullary lamb=
da but this is not a really important property compared to the general need=
 for a non-templated way of passing callables to functions. The proposed st=
d::function_ref class serves this purpose well.</div><div><br></div><div>Wi=
th this in mind I argue for a lazy parameter passing method, maybe using a =
void func([]-&gt;int x) syntax. This is still to be viewed as a parameter b=
y both caller and callee and not as a terse lambda.</div><div><br></div><di=
v>The other use case I think is served well enough by std::function_ref. I =
tried the idea of allowing a function_ref&lt;T()&gt; to have a constructor =
from a []-&gt;T but I couldn&#39;t get the semantics intiutive enough due t=
o the requirement that it should be able to return a non-copyable type.</di=
v><div><br><br>Den m=C3=A5ndag 14 maj 2018 kl. 15:16:07 UTC+2 skrev <a>flor=
ia...@gmail.com</a>:<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>But this would be useful in some cases: for example overloading <span s=
tyle=3D"font-family:courier new,monospace">operator&amp;&amp;</span> and <s=
pan style=3D"font-family:courier new,monospace">operator||</span> (and also=
 <span style=3D"font-family:courier new,monospace">operator?:</span> when i=
t will be overloadable).<br>It could also be used to implement a <span styl=
e=3D"font-family:courier new,monospace">select</span> function defined like=
 this:<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">float</span><span style=3D"color:#000"> </span><span style=3D"=
color:#008">select</span><span style=3D"color:#660">(</span><span style=3D"=
color:#008">int</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:#=
008">float</span><span style=3D"color:#000"> a</span><span style=3D"color:#=
660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#008">=
float</span><span style=3D"color:#000"> b</span><span style=3D"color:#660">=
,</span><span style=3D"color:#000"> </span><span style=3D"color:#008">float=
</span><span style=3D"color:#000"> c</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">switc=
h</span><span style=3D"color:#000"> </span><span style=3D"color:#660">(</sp=
an><span style=3D"color:#000">i</span><span style=3D"color:#660">)</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">{</span><code><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#00=
8">case</span><span style=3D"color:#000"> </span><span style=3D"color:#066"=
>0</span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span s=
tyle=3D"color:#000"> a</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"></span></code><code><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#066">1</span><span style=3D"color:#660">:=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">return</span><span style=3D"color:#000"> b</span><span st=
yle=3D"color:#660">;</span><span style=3D"color:#000"></span></code><code><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#00=
8">case</span><span style=3D"color:#000"> </span><span style=3D"color:#066"=
>2</span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span s=
tyle=3D"color:#000"> c</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"></span></code><span style=3D"color:#000"><br>=C2=A0 </span>=
<span style=3D"color:#660">}</span><span style=3D"color:#000"><br></span><s=
pan style=3D"color:#660">}</span><span style=3D"color:#000"><br></span></di=
v></code></div><br>The delayed evaluation is important to allow a parameter=
 with side effects not to be executed if not needed, avoiding undefined beh=
aviors:<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:#606">float *p;<br><br>if (p &amp;&amp; *p &gt; 0) { ... } // thi=
s is valid<br><br>bool AND(bool a, bool b) {<br>=C2=A0 return a &amp;&amp; =
b;<br>}<br><br>if (AND(p, *p &gt; 0)) { ... } // This is not<br></span><spa=
n style=3D"color:#660"></span></div></code></div><br><br>I thought of 4 way=
s to express that:<br><br>Type qualifier + implicit evaluation:<br><div sty=
le=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);borde=
r-style:solid;border-width:1px"><code><div><div style=3D"background-color:r=
gb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-wid=
th:1px"><code><div><span style=3D"color:#008">float</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#008">select</span><span style=3D"co=
lor:#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"color:#00=
0"> </span><span style=3D"color:#008">float @</span><span style=3D"color:#0=
00"> a</span><span style=3D"color:#660">,</span><span style=3D"color:#000">=
 </span><span style=3D"color:#008">float</span><span style=3D"color:#000"> =
@ b</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </=
span><span style=3D"color:#008">float</span><span style=3D"color:#000"> @ c=
</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">switch</span><span style=3D"color:#000"> =
</span><span style=3D"color:#660">(</span><span style=3D"color:#000">i</spa=
n><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#660">{</span><code><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"color:#=
000"> </span><span style=3D"color:#066">0</span><span style=3D"color:#660">=
:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span st=
yle=3D"color:#008">return</span><span style=3D"color:#000"> a</span><span s=
tyle=3D"color:#660">;</span><span style=3D"color:#000"></span></code><code>=
<span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#0=
08">case</span><span style=3D"color:#000"> </span><span style=3D"color:#066=
">1</span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span =
style=3D"color:#000"> b</span><span style=3D"color:#660">;</span><span styl=
e=3D"color:#000"></span></code><code><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#066">2</span><span style=3D"color:#660">:=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">return</span><span style=3D"color:#000"> c</span><span st=
yle=3D"color:#660">;</span><span style=3D"color:#000"></span></code><span s=
tyle=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#660">}</span><s=
pan style=3D"color:#000"><br></span><span style=3D"color:#660">}</span><spa=
n style=3D"color:#000"><br></span></div></code></div><span style=3D"color:#=
660"></span></div></code></div><br>Type qualifier + operator:<br><div style=
=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-=
style:solid;border-width:1px"><code><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">float</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#008">select</span><span style=3D"colo=
r:#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"color:#000"=
> </span><span style=3D"color:#008">float @</span><span style=3D"color:#000=
"> a</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#008">float</span><span style=3D"color:#000"> @ =
b</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#008">float</span><span style=3D"color:#000"> @ c</=
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">switch</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">)</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#660">{</span><code><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#066">0</span><span style=3D"color:#660">:=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">return</span><span style=3D"color:#000"> @a</span><span s=
tyle=3D"color:#660">;</span><span style=3D"color:#000"></span></code><code>=
<span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#0=
08">case</span><span style=3D"color:#000"> </span><span style=3D"color:#066=
">1</span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span =
style=3D"color:#000"> @b</span><span style=3D"color:#660">;</span><span sty=
le=3D"color:#000"></span></code><code><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"color:#=
000"> </span><span style=3D"color:#066">2</span><span style=3D"color:#660">=
:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span st=
yle=3D"color:#008">return</span><span style=3D"color:#000"> @c</span><span =
style=3D"color:#660">;</span><span style=3D"color:#000"></span></code><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:#660">}</span><s=
pan style=3D"color:#000"><br></span></div></code></div><span style=3D"color=
:#660"></span></div></code></div><br>Type qualifier + callable:<div style=
=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-=
style:solid;border-width:1px"><code><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">float</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#008">select</span><span style=3D"colo=
r:#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"color:#000"=
> </span><span style=3D"color:#008">float</span><span style=3D"color:#000">=
 @ a</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#008">float @</span><span style=3D"color:#000"> =
b</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#008">float @</span><span style=3D"color:#000"> c</=
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">switch</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">)</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#660">{</span><code><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#066">0</span><span style=3D"color:#660">:=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">return</span><span style=3D"color:#000"> a</span><span st=
yle=3D"color:#660">();</span><span style=3D"color:#000"></span></code><code=
><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#=
008">case</span><span style=3D"color:#000"> </span><span style=3D"color:#06=
6">1</span><span style=3D"color:#660">:</span><span style=3D"color:#000"><b=
r>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span=
 style=3D"color:#000"> b</span><span style=3D"color:#660">();</span><span s=
tyle=3D"color:#000"></span></code><code><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#066">2</span><span style=3D"color:#66=
0">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span=
 style=3D"color:#008">return</span><span style=3D"color:#000"> c</span><spa=
n style=3D"color:#660">();</span><span style=3D"color:#000"></span></code><=
span style=3D"color:#000"><br>=C2=A0 </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></span></div></code></div><span style=3D"c=
olor:#660"></span></div></code></div><br>STL type:<br><div style=3D"backgro=
und-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid=
;border-width:1px"><code><div><span style=3D"color:#008">float</span><span =
style=3D"color:#000"> </span><span style=3D"color:#008">select</span><span =
style=3D"color:#660">(</span><span style=3D"color:#008">int</span><span sty=
le=3D"color:#000"> i</span><span style=3D"color:#660">,</span><span style=
=3D"color:#000"> </span><code><span style=3D"color:#008">std::expression&lt=
;float&gt;</span><span style=3D"color:#000"></span></code><span style=3D"co=
lor:#000"> a</span><span style=3D"color:#660">,</span><span style=3D"color:=
#000"> </span><code><code><span style=3D"color:#008">std::expression&lt;flo=
at&gt;</span><span style=3D"color:#000"></span></code><span style=3D"color:=
#000"></span></code><span style=3D"color:#000"> b</span><span style=3D"colo=
r:#660">,</span><span style=3D"color:#000"> </span><code><code><span style=
=3D"color:#008">std::expression&lt;float&gt;</span><span style=3D"color:#00=
0"></span></code><span style=3D"color:#000"></span></code><span style=3D"co=
lor:#000"> c</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">switch</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660">(</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><code><span style=3D"color:#000=
"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#066">0</span><span style=3D"=
color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">return</span><span style=3D"color:#000"> a</=
span><span style=3D"color:#660">();</span><span style=3D"color:#000"></span=
></code><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">case</span><span style=3D"color:#000"> </span><span style=
=3D"color:#066">1</span><span style=3D"color:#660">:</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">retur=
n</span><span style=3D"color:#000"> b</span><span style=3D"color:#660">();<=
/span><span style=3D"color:#000"></span></code><code><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#066">2</span><span style=
=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 </span><span style=3D"color:#008">return</span><span style=3D"color:#000">=
 c</span><span style=3D"color:#660">();</span><span style=3D"color:#000"></=
span></code><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"col=
or:#660">}</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=
><br>In all the 3 cases, when the <span style=3D"font-family:courier new,mo=
nospace">select</span> function is called, a functor-like object is created=
 computing the expression, and this object is then passed to the function.<=
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:=
#606">float* p;<br>int i;<br><br>float r =3D select(i, 1.f, *p, std::sqrt(*=
p));<br><br>// equivalent to:<br><br>float r;<br>switch (i) {<br>=C2=A0 cas=
e 0:<br>=C2=A0=C2=A0=C2=A0 r =3D 1.f;<br>=C2=A0=C2=A0=C2=A0 break;</span><c=
ode><span style=3D"color:#606"><br>=C2=A0 case 1:<br>=C2=A0=C2=A0=C2=A0 r =
=3D *p;<br>=C2=A0=C2=A0=C2=A0 break;</span></code><span style=3D"color:#606=
"><code><span style=3D"color:#606"><br>=C2=A0 case 2:<br>=C2=A0=C2=A0=C2=A0=
 r =3D std::sqrt(*p);<br>=C2=A0=C2=A0=C2=A0 break;</span></code></span></di=
v><div><span style=3D"color:#606"><code><span style=3D"color:#606"></span><=
/code>}<br></span><span style=3D"color:#660"></span></div></code></div><br>=
I really have the impression this could be very interesting in some corner =
cases where there is currently no alternatives to do that safely (and effic=
iently).<br><br>Would this be sensible? Were there any attempt to formalize=
 passing by expression?<br>Which way of expressing this should be preferred=
?<br><br>I would be glad to answer any question.<br><br>Florian<br></div></=
blockquote></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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/e692d0e1-02e3-4d5e-baff-7c681089fba9%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/e692d0e1-02e3-4d5e-baff-7c681089fba9=
%40isocpp.org</a>.<br />

------=_Part_3000_1134278324.1528976236378--

------=_Part_2999_1954660082.1528976236376--

.


Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Fri, 15 Jun 2018 03:36:12 -0700 (PDT)
Raw View
------=_Part_7173_990987082.1529058972137
Content-Type: multipart/alternative;
 boundary="----=_Part_7174_1526934452.1529058972139"

------=_Part_7174_1526934452.1529058972139
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable



Den torsdag 14 juni 2018 kl. 13:37:16 UTC+2 skrev floria...@gmail.com:
>
> I don't clearly get your point.
>
> If in your second use case, you don't want multiple evaluations, then bot=
h=20
> use cases are possible within a single feature (as I already showed=20
> earlier).
>

The problem is that if the first use case is for a by value parameter and=
=20
evaluates it multiple times the type must be copyable. So we can't combine=
=20
allowing multiple usage with  allowing non-copyability.
If you consider the code that the compiler has to generate for the lazy=20
parameter thunk I can't see that we can get both in the same feature. The=
=20
only possibility would be for the compiler to generate different code=20
depending on whether the
parameter type is copyable. This could be possible but I don't have time=20
right now to think that trhough.

=20

> If you do, std::function_ref would be the answer.
>


=20

>
> There is a case that would be improved with=20
> struct Foo {
>   int i;
>   Foo(const Foo&) =3D delete;
> };
>
> template <class T>
> struct Bar {
>   T* p =3D nullptr;
>   ~Bar() { delete p; }
>
>   void set(T const& v) { p =3D new T(v); }
>   void set_lazy([] -> T v) { p =3D new T(v()); }
>   void set_func(std::function_ref<T()> f) { return new T(f()); }
>   template <class... Args>
>   void emplace(Args&&... args) { p =3D new T(std::forward<Args>(args)...)=
; }
> };
>
> Bar<Foo> bar;
> // We want to construct Foo from { .i =3D 1 } // designated initializer l=
ist
> bar.set({ .i =3D 1 }); // Foo is not copyable
> bar.set_lazy({ .i =3D 1 }); // this is fine
> bar.emplace(/* what here? */); // designated initializer list=20
> construction is not a constructor
> bar.set_func([]() -> Foo { return { .i =3D 1 }; }); // name has to be=20
> mentionned here
>
> In this case, set cannot work because Foo is non-copyable.
> emplace cannot work because it is not a constructor (and it is not=20
> type-erased).
> And you would need to name the type to make set_func works (even with an=
=20
> hypothetical terse lamb=20
>
da syntax). While set_lazy would have all the good properties we want here.
>
=20
Yes, I know. This is the second use case. I don't see it as important at=20
all compared to the first use case. I would like someone to come up with a=
=20
situation where this is actually interesting. Is it even legal to=20
initialize a class with a constructor (albeit deleted) from a braced init=
=20
list. If it is: Can you come up with a class which as good reason to be=20
non-movable but where the constructor does absolutely nothing. If so, how=
=20
can it be important to not have a constructor instead of the braced init=20
list. If there is a constructor it would be much more logical to send the=
=20
constructor parameters than a "fake" object as the parameter type. After=20
all it is very odd to pass an object of a non-copyable type as a BY VALUE=
=20
parameter. This feels like a totally academic excecise devised just to=20
prevent a perfectly good feature (lazy parameters) from getting a=20
reasonable and easy to understand definition.
=20

>
> Le jeudi 14 juin 2018 09:19:25 UTC+2, Bengt Gustafsson a =C3=A9crit :
>>
>> I have been pondering this proposal and P0927 for a while to see if I=20
>> could reconcile the two use cases of P0927 into one decent feature. I=20
>> failed, and I think that they must be served by different features.
>>
>> The first use case is to avoid evaluating argument expressions if not=20
>> needed, which may be a performance optimization such as in a logging cas=
e=20
>> or semantically important as in a shortcut operator. The parameter of=20
>> std::optional::value_or would also be a good use case if it wasn't too l=
ate=20
>> for that. Here an important property is that the call site does not have=
 to=20
>> care whether the parameter is lazy and that the argument can be forwarde=
d=20
>> to another lazy parameter without problems. These two requirements mean=
=20
>> that temporaries of the argument expression must be preserved until the=
=20
>> callee returns and that the parameter must be allowed to be evaluatated=
=20
>> more than once (or forwarding would be ridiculously useless).
>>
>> The second use case is for a nullary lambda which is usable inside the=
=20
>> callee by returning values when called. A primary feature is that the=20
>> callee should not have to be a template function. Thanks to guaranteed=
=20
>> return value elison this can allow initiating non-movable types as if=20
>> values by that type were magically passed into the callee. This would al=
so=20
>> benefit from allowing an argument expression to be transformed to such a=
=20
>> nullary lambda but this is not a really important property compared to t=
he=20
>> general need for a non-templated way of passing callables to functions. =
The=20
>> proposed std::function_ref class serves this purpose well.
>>
>> With this in mind I argue for a lazy parameter passing method, maybe=20
>> using a void func([]->int x) syntax. This is still to be viewed as a=20
>> parameter by both caller and callee and not as a terse lambda.
>>
>> The other use case I think is served well enough by std::function_ref. I=
=20
>> tried the idea of allowing a function_ref<T()> to have a constructor fro=
m a=20
>> []->T but I couldn't get the semantics intiutive enough due to the=20
>> requirement that it should be able to return a non-copyable type.
>>
>>
>> Den m=C3=A5ndag 14 maj 2018 kl. 15:16:07 UTC+2 skrev floria...@gmail.com=
:
>>>
>>> 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.
>>> But this would be useful in some cases: for example overloading=20
>>> operator&& and operator|| (and also operator?: when it will be=20
>>> overloadable).
>>> It could also be used to implement a select function defined like this:
>>> float select(int i, float a, float b, float c) {
>>>   switch (i) {
>>>     case 0:
>>>       return a;
>>>     case 1:
>>>       return b;
>>>     case 2:
>>>       return c;
>>>   }
>>> }
>>>
>>> The delayed evaluation is important to allow a parameter with side=20
>>> effects not to be executed if not needed, avoiding undefined behaviors:
>>> float *p;
>>>
>>> if (p && *p > 0) { ... } // this is valid
>>>
>>> bool AND(bool a, bool b) {
>>>   return a && b;
>>> }
>>>
>>> if (AND(p, *p > 0)) { ... } // This is not
>>>
>>>
>>> I thought of 4 ways to express that:
>>>
>>> Type qualifier + implicit evaluation:
>>> float select(int i, float @ a, float @ b, float @ c) {
>>>   switch (i) {
>>>     case 0:
>>>       return a;
>>>     case 1:
>>>       return b;
>>>     case 2:
>>>       return c;
>>>   }
>>> }
>>>
>>> Type qualifier + operator:
>>> float select(int i, float @ a, float @ b, float @ c) {
>>>   switch (i) {
>>>     case 0:
>>>       return @a;
>>>     case 1:
>>>       return @b;
>>>     case 2:
>>>       return @c;
>>>   }
>>> }
>>>
>>> Type qualifier + callable:
>>> float select(int i, float @ a, float @ b, float @ c) {
>>>   switch (i) {
>>>     case 0:
>>>       return a();
>>>     case 1:
>>>       return b();
>>>     case 2:
>>>       return c();
>>>   }
>>> }
>>>
>>> STL type:
>>> float select(int i, std::expression<float> a, std::expression<float> b,=
=20
>>> std::expression<float> c) {
>>>   switch (i) {
>>>     case 0:
>>>       return a();
>>>     case 1:
>>>       return b();
>>>     case 2:
>>>       return c();
>>>   }
>>> }
>>>
>>>
>>> In all the 3 cases, when the select function is called, a functor-like=
=20
>>> object is created computing the expression, and this object is then pas=
sed=20
>>> to the function.
>>> float* p;
>>> int i;
>>>
>>> float r =3D select(i, 1.f, *p, std::sqrt(*p));
>>>
>>> // equivalent to:
>>>
>>> float r;
>>> switch (i) {
>>>   case 0:
>>>     r =3D 1.f;
>>>     break;
>>>   case 1:
>>>     r =3D *p;
>>>     break;
>>>   case 2:
>>>     r =3D std::sqrt(*p);
>>>     break;
>>> }
>>>
>>> I really have the impression this could be very interesting in some=20
>>> corner cases where there is currently no alternatives to do that safely=
=20
>>> (and efficiently).
>>>
>>> Would this be sensible? Were there any attempt to formalize passing by=
=20
>>> expression?
>>> Which way of expressing this should be preferred?
>>>
>>> I would be glad to answer any question.
>>>
>>> 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/34dc7d4d-d655-49cd-8ebd-356fec230cc9%40isocpp.or=
g.

------=_Part_7174_1526934452.1529058972139
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><br>Den torsdag 14 juni 2018 kl. 13:37:16 UTC+2 skrev =
floria...@gmail.com:<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"ltr">I don&#39;t clearly get your point.<br><br>If in your second use c=
ase, you don&#39;t want multiple evaluations, then both use cases are possi=
ble within a single feature (as I already showed earlier).<br></div></block=
quote><div><br></div><div>The problem is that if the first use case is for =
a by value parameter and evaluates it multiple times the type must be copya=
ble. So we can&#39;t combine allowing multiple usage with=C2=A0 allowing no=
n-copyability.</div><div>If you consider the code that the compiler has to =
generate for the lazy parameter thunk I can&#39;t see that we can get both =
in the same feature. The only possibility would be for the compiler to gene=
rate different code depending on whether the</div><div>parameter type is co=
pyable. This could be possible but I don&#39;t have time right now to think=
 that trhough.</div><div><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;"><div dir=3D"ltr">If you do, std::function_ref would b=
e the answer.<br></div></blockquote><div><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"><br>=
There is a case that would be improved with <br><div style=3D"background-co=
lor:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;borde=
r-width:1px"><code><div><span style=3D"color:#008">struct</span><span style=
=3D"color:#000"> </span><span style=3D"color:#606">Foo</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"colo=
r:#000"><br>=C2=A0 </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"><br>=C2=A0 </span><span style=3D"color:#606">Foo</span><span st=
yle=3D"color:#660">(</span><span style=3D"color:#008">const</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#606">Foo</span><span style=
=3D"color:#660">&amp;)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D=
"color:#008">delete</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><br></span><span style=3D"color:#008">template</span><span =
style=3D"color:#000"> </span><span style=3D"color:#660">&lt;</span><span st=
yle=3D"color:#008">class</span><span style=3D"color:#000"> T</span><span st=
yle=3D"color:#660">&gt;</span><span style=3D"color:#000"><br></span><span s=
tyle=3D"color:#008">struct</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#606">Bar</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 T</span><spa=
n style=3D"color:#660">*</span><span style=3D"color:#000"> p </span><span s=
tyle=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#008">nullptr</span><span style=3D"color:#660">;</span><span sty=
le=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#660">~</span><spa=
n style=3D"color:#606">Bar</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">delete</span><span style=
=3D"color:#000"> 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><br>=C2=A0 </span><span style=3D"color:#008">void</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#008">set</span><span style=
=3D"color:#660">(</span><span style=3D"color:#000">T </span><span style=3D"=
color:#008">const</span><span style=3D"color:#660">&amp;</span><span style=
=3D"color:#000"> v</span><span style=3D"color:#660">)</span><span style=3D"=
color:#000"> </span><span style=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:#00=
0"> T</span><span style=3D"color:#660">(</span><span style=3D"color:#000">v=
</span><span style=3D"color:#660">);</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0=
 </span><span style=3D"color:#008">void</span><span style=3D"color:#000"> s=
et_lazy</span><span style=3D"color:#660">([]</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">-&gt;</span><span style=3D"color:#000=
"> T v</span><span style=3D"color:#660">)</span><span style=3D"color:#000">=
 </span><span style=3D"color:#660">{</span><span style=3D"color:#000"> p </=
span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#008">new</span><span style=3D"color:#000"> T</span>=
<span style=3D"color:#660">(</span><span style=3D"color:#000">v</span><span=
 style=3D"color:#660">());</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0 </span><s=
pan style=3D"color:#008">void</span><span style=3D"color:#000"> set_func</s=
pan><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_re=
f</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#000">T<=
/span><span style=3D"color:#660">()<wbr>&gt;</span><span style=3D"color:#00=
0"> f</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> =
</span><span style=3D"color:#660">{</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#008">return</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#008">new</span><span style=3D"color:#000"> T</span>=
<span style=3D"color:#660">(</span><span style=3D"color:#000">f</span><span=
 style=3D"color:#660">());</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#660">}</span><span style=3D"color:#000"><code><span style=3D=
"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">template</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">&lt;</span><spa=
n style=3D"color:#008">class</span><span style=3D"color:#660">...</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#606">Args</span><span=
 style=3D"color:#660">&gt;</span><span style=3D"color:#000"><br>=C2=A0 </sp=
an><span style=3D"color:#008">void</span><span style=3D"color:#000"> emplac=
e</span><span style=3D"color:#660">(</span><span style=3D"color:#606">Args<=
/span><span style=3D"color:#660">&amp;&amp;...</span><span style=3D"color:#=
000"> args</span><span style=3D"color:#660">)</span><span style=3D"color:#0=
00"> </span><span style=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:#000"> T</s=
pan><span style=3D"color:#660">(</span><span style=3D"color:#000">std</span=
><span style=3D"color:#660">::</span><span style=3D"color:#000">forward</sp=
an><span style=3D"color:#660">&lt;</span><span style=3D"color:#606">Args</s=
pan><span style=3D"color:#660">&gt;(</span><span style=3D"color:#000">args<=
/span><span style=3D"color:#660">)...)<wbr>;</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">}</span><span style=3D"color:#000"><b=
r></span></code></span><span style=3D"color:#660">};</span><span style=3D"c=
olor:#000"><br><br></span><span style=3D"color:#606">Bar</span><span style=
=3D"color:#660">&lt;</span><span style=3D"color:#606">Foo</span><span style=
=3D"color:#660">&gt;</span><span style=3D"color:#000"> bar</span><span styl=
e=3D"color:#660">;</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#800">// We want to construct Foo from { .i =3D 1 } // designated=
 initializer list</span><span style=3D"color:#000"><br>bar</span><span styl=
e=3D"color:#660">.</span><span style=3D"color:#008">set</span><span style=
=3D"color:#660">({</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">.</span><span style=3D"color:#000">i </span><span style=3D"colo=
r:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#=
066">1</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
});</span><span style=3D"color:#000"> </span><span style=3D"color:#800">// =
Foo is not copyable</span><span style=3D"color:#000"><br>bar</span><span st=
yle=3D"color:#660">.</span><span style=3D"color:#000">set_lazy</span><span =
style=3D"color:#660">({</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">.</span><span style=3D"color:#000">i </span><span style=3D=
"color:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#066">1</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660">});</span><span style=3D"color:#000"> </span><span style=3D"color:#800=
">// this is fine</span><span style=3D"color:#000"><br>bar</span><span styl=
e=3D"color:#660">.</span><span style=3D"color:#000">emplace</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#800">/* what here? */</span=
><span style=3D"color:#660">);</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#800">// designated initializer list construction is not =
a constructor</span><span style=3D"color:#000"><br>bar</span><span style=3D=
"color:#660">.</span><span style=3D"color:#000">set_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:#606">Foo</span><span style=3D"color:#000"> </span><span style=3D=
"color:#660">{</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#008">return</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#660">{</span><span style=3D"color:#000"> </span><span style=3D"color:#66=
0">.</span><span style=3D"color:#000">i </span><span style=3D"color:#660">=
=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#066">1</=
span><span style=3D"color:#000"> </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"> </span><span style=3D"color:#800">// name has to =
be mentionned here</span><span style=3D"color:#000"><br></span></div></code=
></div><br>In this case, <span style=3D"font-family:courier new,monospace">=
set </span>cannot work because <span style=3D"font-family:courier new,monos=
pace">Foo</span> is non-copyable.<br><span style=3D"font-family:courier new=
,monospace">emplace</span> cannot work because it is not a constructor (and=
 it is not type-erased).<br>And you would need to name the type to make <sp=
an style=3D"font-family:courier new,monospace">set_func</span> works (even =
with an hypothetical terse lamb=C2=A0</div></blockquote><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">da syntax). While <span style=
=3D"font-family: &quot;courier new&quot;, monospace;">set_lazy</span> would=
 have all the good properties we want here.</div></blockquote><div>=C2=A0</=
div><div>Yes, I know. This is the second use case. I don&#39;t see it as im=
portant at all compared to the first use case. I would like someone to come=
 up with a situation where this is actually interesting. Is it even legal t=
o initialize a class with a constructor (albeit deleted) from a braced init=
 list. If it is: Can you come up with a class which as good reason to be no=
n-movable but where the constructor does absolutely nothing. If so, how can=
 it be important to not have a constructor instead of the braced init list.=
 If there is a constructor it would be much more logical to send the constr=
uctor parameters than a &quot;fake&quot; object as the parameter type. Afte=
r all it is very odd to pass an object of a non-copyable type as a BY VALUE=
 parameter. This feels like a totally academic excecise devised just to pre=
vent a perfectly good feature (lazy parameters) from getting a reasonable a=
nd easy to understand definition.</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"><br>Le jeudi 14 juin 2018 09:1=
9:25 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;paddi=
ng-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 cases of P0927 into on=
e decent feature. I failed, and I think that they must be served by differe=
nt features.<div><br></div><div>The first use case is to avoid evaluating a=
rgument expressions if not needed, which may be a performance optimization =
such as in a logging case or semantically important as in a shortcut operat=
or. The parameter of std::optional::value_or would also be a good use case =
if it wasn&#39;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 t=
o be evaluatated more than once (or forwarding would be ridiculously useles=
s).</div><div><br></div><div>The second use case is for a nullary lambda wh=
ich is usable inside the callee by returning values when called. A primary =
feature is that the callee should not have to be a template function. Thank=
s to guaranteed return value elison this can allow initiating non-movable t=
ypes as if values by that type were magically passed into the callee. This =
would also benefit from allowing an argument expression to be transformed t=
o such a nullary lambda but this is not a really important property compare=
d to the general need for a non-templated way of passing callables to funct=
ions. The proposed std::function_ref class serves this purpose well.</div><=
div><br></div><div>With this in mind I argue for a lazy parameter passing m=
ethod, maybe using a void func([]-&gt;int x) syntax. This is still to be vi=
ewed as a parameter by both caller and callee and not as a terse lambda.</d=
iv><div><br></div><div>The other use case I think is served well enough by =
std::function_ref. I tried the idea of allowing a function_ref&lt;T()&gt; t=
o have a constructor from a []-&gt;T but I couldn&#39;t get the semantics i=
ntiutive enough due to the requirement that it should be able to return a n=
on-copyable type.</div><div><br><br>Den m=C3=A5ndag 14 maj 2018 kl. 15:16:0=
7 UTC+2 skrev <a>floria...@gmail.com</a>:<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">Hello everyone,<br><br>I would want to propose a new=
 way to pass parameters to functions.<br>Currently, we have 2 way to pass p=
arameters: by value, and by reference.<br>(Passing by pointer is really pas=
sing by value the address)<br><br>However, none of those allow delayed eval=
uation of parameters.<br>But this would be useful in some cases: for exampl=
e overloading <span style=3D"font-family:courier new,monospace">operator&am=
p;&amp;</span> and <span style=3D"font-family:courier new,monospace">operat=
or||</span> (and also <span style=3D"font-family:courier new,monospace">ope=
rator?:</span> when it will be overloadable).<br>It could also be used to i=
mplement a <span style=3D"font-family:courier new,monospace">select</span> =
function defined like this:<br><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">float</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#008">select</span><span style=3D"color:#660">(<=
/span><span style=3D"color:#008">int</span><span style=3D"color:#000"> i</s=
pan><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span><=
span style=3D"color:#008">float</span><span style=3D"color:#000"> a</span><=
span style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span =
style=3D"color:#008">float</span><span style=3D"color:#000"> b</span><span =
style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">float</span><span style=3D"color:#000"> c</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </span><span style=
=3D"color:#008">switch</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">(</span><span style=3D"color:#000">i</span><span style=3D"c=
olor:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660">{</span><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><sp=
an style=3D"color:#008">case</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#066">0</span><span style=3D"color:#660">:</span><span styl=
e=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008"=
>return</span><span style=3D"color:#000"> a</span><span style=3D"color:#660=
">;</span><span style=3D"color:#000"></span></code><code><span style=3D"col=
or:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#066">1</span><span st=
yle=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:#00=
0"> b</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><=
/span></code><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><spa=
n style=3D"color:#008">case</span><span style=3D"color:#000"> </span><span =
style=3D"color:#066">2</span><span style=3D"color:#660">:</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">=
return</span><span style=3D"color:#000"> c</span><span style=3D"color:#660"=
>;</span><span style=3D"color:#000"></span></code><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:#660">}</span><span style=3D"color:#=
000"><br></span></div></code></div><br>The delayed evaluation is important =
to allow a parameter with side effects not to be executed if not needed, av=
oiding undefined behaviors:<br><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:#606">float *p;<br><br>if (p &amp;&amp; *p &gt;=
 0) { ... } // this is valid<br><br>bool AND(bool a, bool b) {<br>=C2=A0 re=
turn a &amp;&amp; b;<br>}<br><br>if (AND(p, *p &gt; 0)) { ... } // This is =
not<br></span><span style=3D"color:#660"></span></div></code></div><br><br>=
I thought of 4 ways to express that:<br><br>Type qualifier + implicit evalu=
ation:<br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(=
187,187,187);border-style:solid;border-width:1px"><code><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">float</span=
><span style=3D"color:#000"> </span><span style=3D"color:#008">select</span=
><span style=3D"color:#660">(</span><span style=3D"color:#008">int</span><s=
pan style=3D"color:#000"> i</span><span style=3D"color:#660">,</span><span =
style=3D"color:#000"> </span><span style=3D"color:#008">float @</span><span=
 style=3D"color:#000"> a</span><span style=3D"color:#660">,</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#008">float</span><span styl=
e=3D"color:#000"> @ b</span><span style=3D"color:#660">,</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">float</span><span style=
=3D"color:#000"> @ c</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"c=
olor:#000"><br>=C2=A0 </span><span style=3D"color:#008">switch</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">)</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660">{</span><code><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#066">0</span><span=
 style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:=
#000"> a</span><span style=3D"color:#660">;</span><span style=3D"color:#000=
"></span></code><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><=
span style=3D"color:#008">case</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#066">1</span><span style=3D"color:#660">:</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#00=
8">return</span><span style=3D"color:#000"> b</span><span style=3D"color:#6=
60">;</span><span style=3D"color:#000"></span></code><code><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><=
span style=3D"color:#000"> </span><span style=3D"color:#066">2</span><span =
style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:=
#000"> c</span><span style=3D"color:#660">;</span><span style=3D"color:#000=
"></span></code><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"c=
olor:#660">}</span><span style=3D"color:#000"><br></span></div></code></div=
><span style=3D"color:#660"></span></div></code></div><br>Type qualifier + =
operator:<br><div style=3D"background-color:rgb(250,250,250);border-color:r=
gb(187,187,187);border-style:solid;border-width:1px"><code><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">float</=
span><span style=3D"color:#000"> </span><span style=3D"color:#008">select</=
span><span style=3D"color:#660">(</span><span style=3D"color:#008">int</spa=
n><span style=3D"color:#000"> i</span><span style=3D"color:#660">,</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#008">float @</span><=
span style=3D"color:#000"> a</span><span style=3D"color:#660">,</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#008">float</span><span =
style=3D"color:#000"> @ b</span><span style=3D"color:#660">,</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#008">float</span><span sty=
le=3D"color:#000"> @ c</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"c=
olor:#000"><br>=C2=A0 </span><span style=3D"color:#008">switch</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">)</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660">{</span><code><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#066">0</span><span=
 style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:=
#000"> @a</span><span style=3D"color:#660">;</span><span style=3D"color:#00=
0"></span></code><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span>=
<span style=3D"color:#008">case</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#066">1</span><span style=3D"color:#660">:</span><span s=
tyle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#0=
08">return</span><span style=3D"color:#000"> @b</span><span style=3D"color:=
#660">;</span><span style=3D"color:#000"></span></code><code><span style=3D=
"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span=
><span style=3D"color:#000"> </span><span style=3D"color:#066">2</span><spa=
n style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 =C2=A0 </span><span style=3D"color:#008">return</span><span style=3D"color=
:#000"> @c</span><span style=3D"color:#660">;</span><span style=3D"color:#0=
00"></span></code><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:#660">}</span><span style=3D"color:#000"><br></span></div></code>=
</div><span style=3D"color:#660"></span></div></code></div><br>Type qualifi=
er + callable:<div style=3D"background-color:rgb(250,250,250);border-color:=
rgb(187,187,187);border-style:solid;border-width:1px"><code><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">float</=
span><span style=3D"color:#000"> </span><span style=3D"color:#008">select</=
span><span style=3D"color:#660">(</span><span style=3D"color:#008">int</spa=
n><span style=3D"color:#000"> i</span><span style=3D"color:#660">,</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#008">float</span><sp=
an style=3D"color:#000"> @ a</span><span style=3D"color:#660">,</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#008">float @</span><spa=
n style=3D"color:#000"> b</span><span style=3D"color:#660">,</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#008">float @</span><span s=
tyle=3D"color:#000"> c</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"c=
olor:#000"><br>=C2=A0 </span><span style=3D"color:#008">switch</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">)</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660">{</span><code><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#066">0</span><span=
 style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color:#008">return</span><span style=3D"color:=
#000"> a</span><span style=3D"color:#660">();</span><span style=3D"color:#0=
00"></span></code><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span=
><span style=3D"color:#008">case</span><span style=3D"color:#000"> </span><=
span style=3D"color:#066">1</span><span style=3D"color:#660">:</span><span =
style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#=
008">return</span><span style=3D"color:#000"> b</span><span style=3D"color:=
#660">();</span><span style=3D"color:#000"></span></code><code><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#066">2</span><=
span style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span style=3D"co=
lor:#000"> c</span><span style=3D"color:#660">();</span><span style=3D"colo=
r:#000"></span></code><span style=3D"color:#000"><br>=C2=A0 </span><span st=
yle=3D"color:#660">}</span><span style=3D"color:#000"><br></span><span styl=
e=3D"color:#660">}</span><span style=3D"color:#000"><br></span></div></code=
></div><span style=3D"color:#660"></span></div></code></div><br>STL type:<b=
r><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">float</span><span style=3D"color:#000"> </span><span style=3D"color:#0=
08">select</span><span style=3D"color:#660">(</span><span style=3D"color:#0=
08">int</span><span style=3D"color:#000"> i</span><span style=3D"color:#660=
">,</span><span style=3D"color:#000"> </span><code><span style=3D"color:#00=
8">std::expression&lt;float&gt;</span><span style=3D"color:#000"></span></c=
ode><span style=3D"color:#000"> a</span><span style=3D"color:#660">,</span>=
<span style=3D"color:#000"> </span><code><code><span style=3D"color:#008">s=
td::expression&lt;float&gt;</span><span style=3D"color:#000"></span></code>=
<span style=3D"color:#000"></span></code><span style=3D"color:#000"> b</spa=
n><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span><co=
de><code><span style=3D"color:#008">std::expression&lt;float&gt;</span><spa=
n style=3D"color:#000"></span></code><span style=3D"color:#000"></span></co=
de><span style=3D"color:#000"> c</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">switch</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#660">(</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><code><span=
 style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">c=
ase</span><span style=3D"color:#000"> </span><span style=3D"color:#066">0</=
span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span styl=
e=3D"color:#000"> a</span><span style=3D"color:#660">();</span><span style=
=3D"color:#000"></span></code><code><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#066">1</span><span style=3D"color:#660">:=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">return</span><span style=3D"color:#000"> b</span><span st=
yle=3D"color:#660">();</span><span style=3D"color:#000"></span></code><code=
><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#=
008">case</span><span style=3D"color:#000"> </span><span style=3D"color:#06=
6">2</span><span style=3D"color:#660">:</span><span style=3D"color:#000"><b=
r>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span=
 style=3D"color:#000"> c</span><span style=3D"color:#660">();</span><span s=
tyle=3D"color:#000"></span></code><span style=3D"color:#000"><br>=C2=A0 </s=
pan><span style=3D"color:#660">}</span><span style=3D"color:#000"><br></spa=
n><span style=3D"color:#660">}</span><span style=3D"color:#000"><br></span>=
</div></code></div><br><br>In all the 3 cases, when the <span style=3D"font=
-family:courier new,monospace">select</span> function is called, a functor-=
like object is created computing the expression, and this object is then pa=
ssed to the function.<br><div style=3D"background-color:rgb(250,250,250);bo=
rder-color:rgb(187,187,187);border-style:solid;border-width:1px"><code><div=
><span style=3D"color:#606">float* p;<br>int i;<br><br>float r =3D select(i=
, 1.f, *p, std::sqrt(*p));<br><br>// equivalent to:<br><br>float r;<br>swit=
ch (i) {<br>=C2=A0 case 0:<br>=C2=A0=C2=A0=C2=A0 r =3D 1.f;<br>=C2=A0=C2=A0=
=C2=A0 break;</span><code><span style=3D"color:#606"><br>=C2=A0 case 1:<br>=
=C2=A0=C2=A0=C2=A0 r =3D *p;<br>=C2=A0=C2=A0=C2=A0 break;</span></code><spa=
n style=3D"color:#606"><code><span style=3D"color:#606"><br>=C2=A0 case 2:<=
br>=C2=A0=C2=A0=C2=A0 r =3D std::sqrt(*p);<br>=C2=A0=C2=A0=C2=A0 break;</sp=
an></code></span></div><div><span style=3D"color:#606"><code><span style=3D=
"color:#606"></span></code>}<br></span><span style=3D"color:#660"></span></=
div></code></div><br>I really have the impression this could be very intere=
sting in some corner cases where there is currently no alternatives to do t=
hat safely (and efficiently).<br><br>Would this be sensible? Were there any=
 attempt to formalize passing by expression?<br>Which way of expressing thi=
s should be preferred?<br><br>I would be glad to answer any question.<br><b=
r>Florian<br></div></blockquote></div></div></blockquote></div></blockquote=
></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/34dc7d4d-d655-49cd-8ebd-356fec230cc9%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/34dc7d4d-d655-49cd-8ebd-356fec230cc9=
%40isocpp.org</a>.<br />

------=_Part_7174_1526934452.1529058972139--

------=_Part_7173_990987082.1529058972137--

.


Author: florian.csdt@gmail.com
Date: Fri, 15 Jun 2018 04:42:59 -0700 (PDT)
Raw View
------=_Part_7421_2125087075.1529062979441
Content-Type: multipart/alternative;
 boundary="----=_Part_7422_1505583873.1529062979443"

------=_Part_7422_1505583873.1529062979443
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable


>
> I understand that there was hard to see my conclusion here, but I showed=
=20
> an example earlier in this thread where a shortcut operation, as part of=
=20
> its implementation, logs the incoming parameter value by forwarding it to=
 a=20
> logging function that may, or may not, actually evaluate the parameter.=
=20
> Thus when log returns, the main callee does not know if the parameter has=
=20
> already been evaluated as it depend on whether logging is enabled. Thus i=
f=20
> it requires the parameter value it must be able to do so even if log() al=
so=20
> did.
>
> 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!
> }
>
> First, the optional destruction is easy to solve at the call site with a=
=20
flag the the lazy expression can manipulate.
And this flag can be optimized away if every temporary is trivially=20
destructible (the callee should not be aware of such a flag).

For the multiple evaluation, I showed that allowing lazy parameters to be=
=20
captured could solve the problem:
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();
}

You could even say it is possible ta lazy expressions in variables and=20
members and create a wrapper to do that automatically:
template <class T>
class multiple_execution {
  private:
    [] -> T lazy;
    std::optional<T> val;
    void execute() {
      if (!val) {
        val =3D lazy();
      }
    }
  public:
    multiple_execution([] -> T lazy) : lazy(lazy) {}
    multiple_execution() =3D delete;
    multiple_execution(const multiple execution&) =3D delete;
    multiple_execution& operator=3D(const multiple_execution&) =3D delete;
    ~multiple_execution() =3D default;

    T& operator()() & {
      execute();
      return val.value();
    }
    T&& operator()() && {
      execute();
      return *std::move(val)
    }
};=20

And your logging example would look like:
bool andand([] -> bool lhs_lazy, [] -> bool rhs_lazy) {
  multiple_execution<bool> lhs(lhs_lazy()), rhs(rhs_lazy());
  Log("performing andand on ", lhs(), " and ", rhs());
  return lhs() && rhs();
}=20



Le vendredi 15 juin 2018 12:36:12 UTC+2, Bengt Gustafsson a =C3=A9crit :
>
>
>
> Den torsdag 14 juni 2018 kl. 13:37:16 UTC+2 skrev floria...@gmail.com:
>>
>> I don't clearly get your point.
>>
>> If in your second use case, you don't want multiple evaluations, then=20
>> both use cases are possible within a single feature (as I already showed=
=20
>> earlier).
>>
>
> The problem is that if the first use case is for a by value parameter and=
=20
> evaluates it multiple times the type must be copyable. So we can't combin=
e=20
> allowing multiple usage with  allowing non-copyability.
> If you consider the code that the compiler has to generate for the lazy=
=20
> parameter thunk I can't see that we can get both in the same feature. The=
=20
> only possibility would be for the compiler to generate different code=20
> depending on whether the
> parameter type is copyable. This could be possible but I don't have time=
=20
> right now to think that trhough.
>

You forget and third possibility: recreate the object several times allows=
=20
both non-copyability and multiple executions. However, I think that=20
shouldn't be a goal for such a feature.
In that case, I would much prefer having an actual callable part of the=20
interface.

We don't want magic that tries to be clever, and has different behaviors=20
depending on what the type supports (copyability, non-throw, moveability...=
)
The rules should be the same for every types.
=20

>
> =20
>
>> If you do, std::function_ref would be the answer.
>>
>
>
> =20
>
>>
>> There is a case that would be improved with=20
>> struct Foo {
>>   int i;
>>   Foo(const Foo&) =3D delete;
>> };
>>
>> template <class T>
>> struct Bar {
>>   T* p =3D nullptr;
>>   ~Bar() { delete p; }
>>
>>   void set(T const& v) { p =3D new T(v); }
>>   void set_lazy([] -> T v) { p =3D new T(v()); }
>>   void set_func(std::function_ref<T()> f) { return new T(f()); }
>>   template <class... Args>
>>   void emplace(Args&&... args) { p =3D new T(std::forward<Args>(args)...=
);=20
>> }
>> };
>>
>> Bar<Foo> bar;
>> // We want to construct Foo from { .i =3D 1 } // designated initializer =
list
>> bar.set({ .i =3D 1 }); // Foo is not copyable
>> bar.set_lazy({ .i =3D 1 }); // this is fine
>> bar.emplace(/* what here? */); // designated initializer list=20
>> construction is not a constructor
>> bar.set_func([]() -> Foo { return { .i =3D 1 }; }); // name has to be=20
>> mentionned here
>>
>> In this case, set cannot work because Foo is non-copyable.
>> emplace cannot work because it is not a constructor (and it is not=20
>> type-erased).
>> And you would need to name the type to make set_func works (even with an=
=20
>> hypothetical terse lamb=20
>>
> da syntax). While set_lazy would have all the good properties we want=20
>> here.
>>
> =20
> Yes, I know. This is the second use case. I don't see it as important at=
=20
> all compared to the first use case. I would like someone to come up with =
a=20
> situation where this is actually interesting. Is it even legal to=20
> initialize a class with a constructor (albeit deleted) from a braced init=
=20
> list. If it is: Can you come up with a class which as good reason to be=
=20
> non-movable but where the constructor does absolutely nothing. If so, how=
=20
> can it be important to not have a constructor instead of the braced init=
=20
> list. If there is a constructor it would be much more logical to send the=
=20
> constructor parameters than a "fake" object as the parameter type. After=
=20
> all it is very odd to pass an object of a non-copyable type as a BY VALUE=
=20
> parameter. This feels like a totally academic excecise devised just to=20
> prevent a perfectly good feature (lazy parameters) from getting a=20
> reasonable and easy to understand definition.
>

My point here was I can address all your issues, but you cannot address all=
=20
mines. So which approach is more powerful?
A bit more explanation on this (cumbersome) example:
Here Foo is an aggregate, so it can be aggregate initialized: I don't call=
=20
any constructor in the example.
std::atomic<> is a valid class that is trivially constructible, and that is=
=20
neither copyable nor movable.
Now, imagine I have this:
struct Point {
  float x, y, z;
};

Bar<std::atomic<Point>> bar;
bar.set_lazy({{ .x =3D 1.f, .y =3D 1.f, .z =3D 1.f }});
Here, of course you could make Point having a constructor taking 3 floats,=
=20
but designated initializer is much clearer (that's why it has been=20
standardize in the first place).


In the end, my approach is easy to understand: if you need multiple=20
evaluations: wrap the lazy expression, or put a callable in the interface=
=20
(depending on the use case).
The lifetime is the same as regular parameters.
From the caller point of view, the only thing to remember: the evaluation=
=20
might not appear, but cannot appear more than once.
From the callee point of view: cannot evaluate more than once. If this it=
=20
is needed: wrapping is possible.
In case of exceptions in the lazy expression, the callee will see (and be=
=20
able to catch) the exception before the caller can, but that's also what=20
you would expect from a delayed expression.
Really, I fail to see where my approach is unintuitive.
=20

> =20
>
>>
>> Le jeudi 14 juin 2018 09:19:25 UTC+2, Bengt Gustafsson a =C3=A9crit :
>>>
>>> I have been pondering this proposal and P0927 for a while to see if I=
=20
>>> could reconcile the two use cases of P0927 into one decent feature. I=
=20
>>> failed, and I think that they must be served by different features.
>>>
>>> The first use case is to avoid evaluating argument expressions if not=
=20
>>> needed, which may be a performance optimization such as in a logging ca=
se=20
>>> or semantically important as in a shortcut operator. The parameter of=
=20
>>> std::optional::value_or would also be a good use case if it wasn't too =
late=20
>>> for that. Here an important property is that the call site does not hav=
e to=20
>>> care whether the parameter is lazy and that the argument can be forward=
ed=20
>>> to another lazy parameter without problems. These two requirements mean=
=20
>>> that temporaries of the argument expression must be preserved until the=
=20
>>> callee returns and that the parameter must be allowed to be evaluatated=
=20
>>> more than once (or forwarding would be ridiculously useless).
>>>
>>> The second use case is for a nullary lambda which is usable inside the=
=20
>>> callee by returning values when called. A primary feature is that the=
=20
>>> callee should not have to be a template function. Thanks to guaranteed=
=20
>>> return value elison this can allow initiating non-movable types as if=
=20
>>> values by that type were magically passed into the callee. This would a=
lso=20
>>> benefit from allowing an argument expression to be transformed to such =
a=20
>>> nullary lambda but this is not a really important property compared to =
the=20
>>> general need for a non-templated way of passing callables to functions.=
 The=20
>>> proposed std::function_ref class serves this purpose well.
>>>
>>> With this in mind I argue for a lazy parameter passing method, maybe=20
>>> using a void func([]->int x) syntax. This is still to be viewed as a=20
>>> parameter by both caller and callee and not as a terse lambda.
>>>
>>> The other use case I think is served well enough by std::function_ref. =
I=20
>>> tried the idea of allowing a function_ref<T()> to have a constructor fr=
om a=20
>>> []->T but I couldn't get the semantics intiutive enough due to the=20
>>> requirement that it should be able to return a non-copyable type.
>>>
>>>
>>> Den m=C3=A5ndag 14 maj 2018 kl. 15:16:07 UTC+2 skrev floria...@gmail.co=
m:
>>>>
>>>> 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.
>>>> But this would be useful in some cases: for example overloading=20
>>>> operator&& and operator|| (and also operator?: when it will be=20
>>>> overloadable).
>>>> It could also be used to implement a select function defined like this=
:
>>>> float select(int i, float a, float b, float c) {
>>>>   switch (i) {
>>>>     case 0:
>>>>       return a;
>>>>     case 1:
>>>>       return b;
>>>>     case 2:
>>>>       return c;
>>>>   }
>>>> }
>>>>
>>>> The delayed evaluation is important to allow a parameter with side=20
>>>> effects not to be executed if not needed, avoiding undefined behaviors=
:
>>>> float *p;
>>>>
>>>> if (p && *p > 0) { ... } // this is valid
>>>>
>>>> bool AND(bool a, bool b) {
>>>>   return a && b;
>>>> }
>>>>
>>>> if (AND(p, *p > 0)) { ... } // This is not
>>>>
>>>>
>>>> I thought of 4 ways to express that:
>>>>
>>>> Type qualifier + implicit evaluation:
>>>> float select(int i, float @ a, float @ b, float @ c) {
>>>>   switch (i) {
>>>>     case 0:
>>>>       return a;
>>>>     case 1:
>>>>       return b;
>>>>     case 2:
>>>>       return c;
>>>>   }
>>>> }
>>>>
>>>> Type qualifier + operator:
>>>> float select(int i, float @ a, float @ b, float @ c) {
>>>>   switch (i) {
>>>>     case 0:
>>>>       return @a;
>>>>     case 1:
>>>>       return @b;
>>>>     case 2:
>>>>       return @c;
>>>>   }
>>>> }
>>>>
>>>> Type qualifier + callable:
>>>> float select(int i, float @ a, float @ b, float @ c) {
>>>>   switch (i) {
>>>>     case 0:
>>>>       return a();
>>>>     case 1:
>>>>       return b();
>>>>     case 2:
>>>>       return c();
>>>>   }
>>>> }
>>>>
>>>> STL type:
>>>> float select(int i, std::expression<float> a, std::expression<float> b=
,=20
>>>> std::expression<float> c) {
>>>>   switch (i) {
>>>>     case 0:
>>>>       return a();
>>>>     case 1:
>>>>       return b();
>>>>     case 2:
>>>>       return c();
>>>>   }
>>>> }
>>>>
>>>>
>>>> In all the 3 cases, when the select function is called, a functor-like=
=20
>>>> object is created computing the expression, and this object is then pa=
ssed=20
>>>> to the function.
>>>> float* p;
>>>> int i;
>>>>
>>>> float r =3D select(i, 1.f, *p, std::sqrt(*p));
>>>>
>>>> // equivalent to:
>>>>
>>>> float r;
>>>> switch (i) {
>>>>   case 0:
>>>>     r =3D 1.f;
>>>>     break;
>>>>   case 1:
>>>>     r =3D *p;
>>>>     break;
>>>>   case 2:
>>>>     r =3D std::sqrt(*p);
>>>>     break;
>>>> }
>>>>
>>>> I really have the impression this could be very interesting in some=20
>>>> corner cases where there is currently no alternatives to do that safel=
y=20
>>>> (and efficiently).
>>>>
>>>> Would this be sensible? Were there any attempt to formalize passing by=
=20
>>>> expression?
>>>> Which way of expressing this should be preferred?
>>>>
>>>> I would be glad to answer any question.
>>>>
>>>> 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/aa6821c0-7e90-4bbd-bc70-5a774ae73ad9%40isocpp.or=
g.

------=_Part_7422_1505583873.1529062979443
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; borde=
r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div>I understand=
 that there was hard to see my conclusion here, but I=20
showed an example earlier in this thread where a shortcut operation, as=20
part of its implementation, logs the incoming parameter value by=20
forwarding it to a logging function that may, or may not, actually=20
evaluate the parameter. Thus when log returns, the main callee does not=20
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=20
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);backg=
round-color:rgb(250,250,250);word-wrap:break-word"><code><span style=3D"col=
or: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)">([]-&gt;</span><span style=3D"col=
or:rgb(0,0,136)">bool</span><span style=3D"color:rgb(0,0,0)">=C2=A0lhs</spa=
n><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)">[]-&gt;</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:rgb(102,102,0)">{</sp=
an><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0=C2=A0</span><span sty=
le=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&quot;=
</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rg=
b(0,0,0)">=C2=A0lhs</span><span style=3D"color:rgb(102,102,0)">,</span><spa=
n style=3D"color:rgb(0,0,0)">=C2=A0</span><span style=3D"color:rgb(0,136,0)=
">&quot; and &quot;</span><span style=3D"color:rgb(102,102,0)">,</span><spa=
n style=3D"color:rgb(0,0,0)">=C2=A0rhs</span><span style=3D"color:rgb(102,1=
02,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)"><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"color:rgb(=
102,102,0)">()</span><span style=3D"color:rgb(0,0,0)">=C2=A0</span><span st=
yle=3D"color:rgb(102,102,0)">&amp;&amp;</span><span style=3D"color:rgb(0,0,=
0)">=C2=A0rhs</span><span style=3D"color:rgb(102,102,0)">();</span><span st=
yle=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 s=
tyle=3D"color:rgb(0,0,0)"><br><br></span></code></div></div></blockquote><d=
iv>First, the optional destruction is easy to solve at the call site with a=
 flag the the lazy expression can manipulate.</div><div>And this flag can b=
e optimized away if every temporary is trivially destructible (the callee s=
hould not be aware of such a flag).<br></div><div><br></div><div>For the mu=
ltiple evaluation, I showed that allowing lazy parameters to be captured co=
uld solve the problem:</div><div><div><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:#008">bool</span><span style=3D"color:#0=
00"> andand</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">bool</span><span style=3D"color:#0=
00"> lhs_lazy</span><span style=3D"color:#660">,</span><span style=3D"color=
:#000"> </span><span style=3D"color:#660">[]</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">-&gt;</span><span style=3D"color:#000=
"> </span><span style=3D"color:#008">bool</span><span style=3D"color:#000">=
 rhs_lazy</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"><b=
r>=C2=A0 std</span><span style=3D"color:#660">::</span><span style=3D"color=
:#000">optional</span><span style=3D"color:#080">&lt;bool&gt;</span><span s=
tyle=3D"color:#000"> lhs_v</span><span style=3D"color:#660">,</span><span s=
tyle=3D"color:#000"> rhs_v</span><span style=3D"color:#660">;</span><code><=
span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">auto=
</span><span style=3D"color:#000"> lhs </span><span style=3D"color:#660">=
=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#660">[&a=
mp;]</span><span style=3D"color:#000"> </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">bool</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#660">{</span><=
span style=3D"color:#000"> </span><span style=3D"color:#008">if</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#660">(!</span><span sty=
le=3D"color:#000">lhs_v</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"> lhs_v </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> lhs_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"> </span><span style=3D"color:#008">return</span><span style=
=3D"color:#000"> lhs_v</span><span style=3D"color:#660">.</span><span style=
=3D"color:#000">value</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"><br></span></code><code><span style=3D"color:#000">=C2=A0 </sp=
an><span style=3D"color:#008">auto</span><span style=3D"color:#000"> rhs </=
span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </spa=
n><span style=3D"color:#660">[&amp;]</span><span style=3D"color:#000"> </sp=
an><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><s=
pan style=3D"color:#008">bool</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#660">{</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#008">if</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">(!</span><span style=3D"color:#000">rhs_v</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">{</span><span style=3D"color:#000"> rhs_v </span><span style=3D"=
color:#660">=3D</span><span style=3D"color:#000"> rhs_lazy</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"> </span><span style=3D"c=
olor:#008">return</span><span style=3D"color:#000"> rhs_v</span><span style=
=3D"color:#660">.</span><span style=3D"color:#000">value</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></code><span st=
yle=3D"color:#000">=C2=A0 </span><br><span style=3D"color:#000"><code><span=
 style=3D"color:#606">=C2=A0 Log</span><span style=3D"color:#660">(</span><=
span style=3D"color:#080">&quot;Performing andand on&quot;</span><span styl=
e=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">&quot; and &quot;</span><span style=3D"color:#660">,</span><sp=
an style=3D"color:#000"> rhs</span><span style=3D"color:#660">());</span></=
code><br>=C2=A0 return lhs() &amp;&amp; rhs();<br></span><span style=3D"col=
or:#660">}</span><span style=3D"color:#000"><br></span></div></code></div><=
/div></div><br>You could even say it is possible ta lazy expressions in var=
iables and members and create a wrapper to do that automatically:<br><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: #008;" class=3D"styled-by-prettify">template</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">class</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> T</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">class</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> multiple_execution </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">private</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">:</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: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">-&gt;=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> T lazy</s=
pan><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 std<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">optional</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">T</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> val</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: #008;" cla=
ss=3D"styled-by-prettify">void</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> execute</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: #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: #008;" class=3D"styled-by-pr=
ettify">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">val</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 val </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=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"><br>=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 </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"colo=
r: #008;" class=3D"styled-by-prettify">public</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 =C2=A0 multiple_execution</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">-&gt;</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> T 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-b=
y-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> lazy</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">lazy</span>=
<span 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: #660;" class=3D"styled-by-prettify">{}</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 multiple_execution</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">delete</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 multiple_execution</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">const</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> multiple execution</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">&amp;)</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;" class=3D"styled-by-pretti=
fy">delete</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 multiple_execution</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">&amp;</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">operator</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">=3D(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">con=
st</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> multipl=
e_execution</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>&amp;)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">delete</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"c=
olor: #660;" class=3D"styled-by-prettify">~</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">multiple_execution</span><span style=3D"co=
lor: #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">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">default</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
<br>=C2=A0 =C2=A0 T</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">&amp;</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">opera=
tor</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()()</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">&amp;</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"color: #000;"=
 class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 execute</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 </s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">return</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> val</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"=
color: #000;" 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"><br>=C2=A0 =C2=A0 </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 T</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">&amp;&amp;</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;"=
 class=3D"styled-by-prettify">operator</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"style=
d-by-prettify">&amp;&amp;</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 =C2=A0 =C2=A0 execute</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 =C2=A0 </span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">return</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">std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">:=
:</span><span style=3D"color: #000;" class=3D"styled-by-prettify">move</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">val</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: #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"=
styled-by-prettify"> <br></span></div></code></div><br>And your logging exa=
mple would look like:<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"prettypri=
nt"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">bool</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> andand</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">-&gt;</s=
pan><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"> lhs_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><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">-&gt;</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">bo=
ol</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> rhs_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 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 multiple_execution</span>=
<span style=3D"color: #080;" class=3D"styled-by-prettify">&lt;bool&gt;</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> lhs</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">lhs_lazy</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">()),</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> rhs</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" cla=
ss=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"st=
yled-by-prettify"><br>=C2=A0 </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: #080;" class=3D"styled-by-prettif=
y">&quot;performing andand on &quot;</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> lhs</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: #080;" class=3D"styled-by-prettify">&quot=
; and &quot;</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> rhs</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">());</span><s=
pan 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;" class=3D"styled-by-prettify"> lhs</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">&amp;&amp;</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"sty=
led-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></span></div></code></div><br><br><br>Le vendredi 15 juin 2018 12:36=
:12 UTC+2, Bengt Gustafsson a =C3=A9crit=C2=A0:<blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;"><div dir=3D"ltr"><br><br>Den torsdag 14 juni 2018 kl. 13:3=
7:16 UTC+2 skrev <a>floria...@gmail.com</a>:<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">I don&#39;t clearly get your point.<br><br>If in =
your second use case, you don&#39;t want multiple evaluations, then both us=
e cases are possible within a single feature (as I already showed earlier).=
<br></div></blockquote><div><br></div><div>The problem is that if the first=
 use case is for a by value parameter and evaluates it multiple times the t=
ype must be copyable. So we can&#39;t combine allowing multiple usage with=
=C2=A0 allowing non-copyability.</div><div>If you consider the code that th=
e compiler has to generate for the lazy parameter thunk I can&#39;t see tha=
t we can get both in the same feature. The only possibility would be for th=
e compiler to generate different code depending on whether the</div><div>pa=
rameter type is copyable. This could be possible but I don&#39;t have time =
right now to think that trhough.</div></div></blockquote><div><br></div><di=
v>You forget and third possibility: recreate the object several times allow=
s both non-copyability and multiple executions. However, I think that shoul=
dn&#39;t be a goal for such a feature.</div><div>In that case, I would much=
 prefer having an actual callable part of the interface.</div><div><br></di=
v><div>We don&#39;t want magic that tries to be clever, and has different b=
ehaviors depending on what the type supports (copyability, non-throw, movea=
bility...)</div><div>The rules should be the same for every types.<br></div=
><div>=C2=A0</div><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"><div><br></div><div>=C2=A0</div><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">If you do, std::function_ref would be the answer.<br></d=
iv></blockquote><div><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"><br>There is a case that would=
 be improved with <br><div style=3D"background-color:rgb(250,250,250);borde=
r-color:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><s=
pan style=3D"color:#008">struct</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#606">Foo</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"> i</span><s=
pan style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 </sp=
an><span style=3D"color:#606">Foo</span><span style=3D"color:#660">(</span>=
<span style=3D"color:#008">const</span><span style=3D"color:#000"> </span><=
span style=3D"color:#606">Foo</span><span style=3D"color:#660">&amp;)</span=
><span style=3D"color:#000"> </span><span style=3D"color:#660">=3D</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#008">delete</span><s=
pan style=3D"color:#660">;</span><span style=3D"color:#000"><br></span><spa=
n style=3D"color:#660">};</span><span style=3D"color:#000"><br><br></span><=
span style=3D"color:#008">template</span><span style=3D"color:#000"> </span=
><span style=3D"color:#660">&lt;</span><span style=3D"color:#008">class</sp=
an><span style=3D"color:#000"> T</span><span style=3D"color:#660">&gt;</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#008">struct</=
span><span style=3D"color:#000"> </span><span style=3D"color:#606">Bar</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#660">{</span><sp=
an style=3D"color:#000"><br>=C2=A0 T</span><span style=3D"color:#660">*</sp=
an><span style=3D"color:#000"> p </span><span style=3D"color:#660">=3D</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#008">nullptr</sp=
an><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:#606">Bar</=
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><spa=
n style=3D"color:#008">delete</span><span style=3D"color:#000"> p</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:#000"><br><br>=C2=A0 </span=
><span style=3D"color:#008">void</span><span style=3D"color:#000"> </span><=
span style=3D"color:#008">set</span><span style=3D"color:#660">(</span><spa=
n style=3D"color:#000">T </span><span style=3D"color:#008">const</span><spa=
n style=3D"color:#660">&amp;</span><span style=3D"color:#000"> v</span><spa=
n style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span sty=
le=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:#000"> T</span><span style=3D"c=
olor:#660">(</span><span style=3D"color:#000">v</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">void</span><span style=3D"color:#000"> set_lazy</span><span style=3D=
"color:#660">([]</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#660">-&gt;</span><span style=3D"color:#000"> T v</span><span style=3D"=
color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color=
:#660">{</span><span style=3D"color:#000"> p </span><span style=3D"color:#6=
60">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#008"=
>new</span><span style=3D"color:#000"> T</span><span style=3D"color:#660">(=
</span><span style=3D"color:#000">v</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">voi=
d</span><span style=3D"color:#000"> set_func</span><span style=3D"color:#66=
0">(</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">&lt;</span><span style=3D"color:#000">T</span><span style=3D"color:#=
660">()<wbr>&gt;</span><span style=3D"color:#000"> f</span><span style=3D"c=
olor:#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"> </span><span style=3D"color:#008"=
>new</span><span style=3D"color:#000"> T</span><span style=3D"color:#660">(=
</span><span style=3D"color:#000">f</span><span style=3D"color:#660">());</=
span><span style=3D"color:#000"> </span><span style=3D"color:#660">}</span>=
<span style=3D"color:#000"><code><span style=3D"color:#000"><br>=C2=A0 </sp=
an><span style=3D"color:#008">template</span><span style=3D"color:#000"> </=
span><span style=3D"color:#660">&lt;</span><span style=3D"color:#008">class=
</span><span style=3D"color:#660">...</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#606">Args</span><span style=3D"color:#660">&gt;</=
span><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008=
">void</span><span style=3D"color:#000"> emplace</span><span style=3D"color=
:#660">(</span><span style=3D"color:#606">Args</span><span style=3D"color:#=
660">&amp;&amp;...</span><span style=3D"color:#000"> args</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">{</span><span style=3D"color:#000"> p </span><span style=3D"colo=
r:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#=
008">new</span><span style=3D"color:#000"> T</span><span style=3D"color:#66=
0">(</span><span style=3D"color:#000">std</span><span style=3D"color:#660">=
::</span><span style=3D"color:#000">forward</span><span style=3D"color:#660=
">&lt;</span><span style=3D"color:#606">Args</span><span style=3D"color:#66=
0">&gt;(</span><span style=3D"color:#000">args</span><span style=3D"color:#=
660">)...)<wbr>;</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#660">}</span><span style=3D"color:#000"><br></span></code></span><span=
 style=3D"color:#660">};</span><span style=3D"color:#000"><br><br></span><s=
pan style=3D"color:#606">Bar</span><span style=3D"color:#660">&lt;</span><s=
pan style=3D"color:#606">Foo</span><span style=3D"color:#660">&gt;</span><s=
pan style=3D"color:#000"> bar</span><span style=3D"color:#660">;</span><spa=
n style=3D"color:#000"><br></span><span style=3D"color:#800">// We want to =
construct Foo from { .i =3D 1 } // designated initializer list</span><span =
style=3D"color:#000"><br>bar</span><span style=3D"color:#660">.</span><span=
 style=3D"color:#008">set</span><span style=3D"color:#660">({</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#660">.</span><span style=
=3D"color:#000">i </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> </span><span style=3D"color:#066">1</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660">});</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#800">// Foo is not copyable</span><sp=
an style=3D"color:#000"><br>bar</span><span style=3D"color:#660">.</span><s=
pan style=3D"color:#000">set_lazy</span><span style=3D"color:#660">({</span=
><span style=3D"color:#000"> </span><span style=3D"color:#660">.</span><spa=
n style=3D"color:#000">i </span><span style=3D"color:#660">=3D</span><span =
style=3D"color:#000"> </span><span style=3D"color:#066">1</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">});</span><span style=3D=
"color:#000"> </span><span style=3D"color:#800">// this is fine</span><span=
 style=3D"color:#000"><br>bar</span><span style=3D"color:#660">.</span><spa=
n style=3D"color:#000">emplace</span><span style=3D"color:#660">(</span><sp=
an style=3D"color:#800">/* what here? */</span><span style=3D"color:#660">)=
;</span><span style=3D"color:#000"> </span><span style=3D"color:#800">// de=
signated initializer list construction is not a constructor</span><span sty=
le=3D"color:#000"><br>bar</span><span style=3D"color:#660">.</span><span st=
yle=3D"color:#000">set_func</span><span style=3D"color:#660">([]()</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">-&gt;</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#606">Foo</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"> </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">i </span><span style=3D"color:#660">=3D</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#066">1</span><span style=3D"color:#000"> =
</span><span style=3D"color:#660">};</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#660">});</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#800">// name has to be mentionned here</span><span st=
yle=3D"color:#000"><br></span></div></code></div><br>In this case, <span st=
yle=3D"font-family:courier new,monospace">set </span>cannot work because <s=
pan style=3D"font-family:courier new,monospace">Foo</span> is non-copyable.=
<br><span style=3D"font-family:courier new,monospace">emplace</span> cannot=
 work because it is not a constructor (and it is not type-erased).<br>And y=
ou would need to name the type to make <span style=3D"font-family:courier n=
ew,monospace">set_func</span> works (even with an hypothetical terse lamb=
=C2=A0</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">da syntax). While <span style=3D"font-family:&quot;courier new&quo=
t;,monospace">set_lazy</span> would have all the good properties we want he=
re.</div></blockquote><div>=C2=A0</div><div>Yes, I know. This is the second=
 use case. I don&#39;t see it as important at all compared to the first use=
 case. I would like someone to come up with a situation where this is actua=
lly interesting. Is it even legal to initialize a class with a constructor =
(albeit deleted) from a braced init list. If it is: Can you come up with a =
class which as good reason to be non-movable but where the constructor does=
 absolutely nothing. If so, how can it be important to not have a construct=
or instead of the braced init list. If there is a constructor it would be m=
uch more logical to send the constructor parameters than a &quot;fake&quot;=
 object as the parameter type. After all it is very odd to pass an object o=
f a non-copyable type as a BY VALUE parameter. This feels like a totally ac=
ademic excecise devised just to prevent a perfectly good feature (lazy para=
meters) from getting a reasonable and easy to understand definition.</div><=
/div></blockquote><div><br></div><div>My point here was I can address all y=
our issues, but you cannot address all mines. So which approach is more pow=
erful?</div><div>A bit more explanation on this (cumbersome) example:</div>=
<div>Here Foo is an aggregate, so it can be aggregate initialized: I don&#3=
9;t call any constructor in the example.</div><div>std::atomic&lt;&gt; is a=
 valid class that is trivially constructible, and that is neither copyable =
nor movable.</div><div>Now, imagine I have this:</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">struct</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">Point</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 </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">float</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> x</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> y</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> z</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"color: #606;" class=3D"s=
tyled-by-prettify">Bar</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">&lt;</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">:=
:</span><span style=3D"color: #000;" class=3D"styled-by-prettify">atomic</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><s=
pan style=3D"color: #606;" class=3D"styled-by-prettify">Point</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">&gt;&gt;</span><span sty=
le=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: #0=
00;" class=3D"styled-by-prettify"><br>bar</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">set_lazy</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: #660;" class=3D"styled-by-pr=
ettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">x=
 </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 st=
yle=3D"color: #066;" class=3D"styled-by-prettify">1.f</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: #000;" class=3D"styl=
ed-by-prettify">y </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">1.f</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: #00=
0;" class=3D"styled-by-prettify">z </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-p=
rettify">1.f</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </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></=
div></code></div>Here, of course you could make Point having a constructor =
taking 3 floats, but designated initializer is much clearer (that&#39;s why=
 it has been standardize in the first place).<br><br></div><div><br></div><=
div>In the end, my approach is easy to understand: if you need multiple eva=
luations: wrap the lazy expression, or put a callable in the interface (dep=
ending on the use case).</div><div>The lifetime is the same as regular para=
meters.</div><div>From the caller point of view, the only thing to remember=
: the evaluation might not appear, but cannot appear more than once.</div><=
div>From the callee point of view: cannot evaluate more than once. If this =
it is needed: wrapping is possible.</div><div>In case of exceptions in the =
lazy expression, the callee will see (and be able to catch) the exception b=
efore the caller can, but that&#39;s also what you would expect from a dela=
yed expression.<br></div><div>Really, I fail to see where my approach is un=
intuitive.<br></div><div>=C2=A0</div><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>=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"><br>Le jeudi 14 juin 2018 09:19:25 UTC+2, Bengt Gust=
afsson 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">I have been pondering this proposal and P0927 for a while to see i=
f I could reconcile the two use cases of P0927 into one decent feature. I f=
ailed, and I think that they must be served by different features.<div><br>=
</div><div>The first use case is to avoid evaluating argument expressions i=
f 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&#39;t too =
late for that. Here an important property is that the call site does not ha=
ve to care whether the parameter is lazy and that the argument can be forwa=
rded to another lazy parameter without problems. These two requirements mea=
n that temporaries of the argument expression must be preserved until the c=
allee returns and that the parameter must be allowed to be evaluatated more=
 than once (or forwarding would be ridiculously useless).</div><div><br></d=
iv><div>The second use case is for a nullary lambda which is usable inside =
the callee by returning values when called. A primary feature is that the c=
allee should not have to be a template function. Thanks to guaranteed retur=
n value elison this can allow initiating non-movable types as if values by =
that type were magically passed into the callee. This would also benefit fr=
om allowing an argument expression to be transformed to such a nullary lamb=
da but this is not a really important property compared to the general need=
 for a non-templated way of passing callables to functions. The proposed st=
d::function_ref class serves this purpose well.</div><div><br></div><div>Wi=
th this in mind I argue for a lazy parameter passing method, maybe using a =
void func([]-&gt;int x) syntax. This is still to be viewed as a parameter b=
y both caller and callee and not as a terse lambda.</div><div><br></div><di=
v>The other use case I think is served well enough by std::function_ref. I =
tried the idea of allowing a function_ref&lt;T()&gt; to have a constructor =
from a []-&gt;T but I couldn&#39;t get the semantics intiutive enough due t=
o the requirement that it should be able to return a non-copyable type.</di=
v><div><br><br>Den m=C3=A5ndag 14 maj 2018 kl. 15:16:07 UTC+2 skrev <a>flor=
ia...@gmail.com</a>:<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>But this would be useful in some cases: for example overloading <span s=
tyle=3D"font-family:courier new,monospace">operator&amp;&amp;</span> and <s=
pan style=3D"font-family:courier new,monospace">operator||</span> (and also=
 <span style=3D"font-family:courier new,monospace">operator?:</span> when i=
t will be overloadable).<br>It could also be used to implement a <span styl=
e=3D"font-family:courier new,monospace">select</span> function defined like=
 this:<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">float</span><span style=3D"color:#000"> </span><span style=3D"=
color:#008">select</span><span style=3D"color:#660">(</span><span style=3D"=
color:#008">int</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:#=
008">float</span><span style=3D"color:#000"> a</span><span style=3D"color:#=
660">,</span><span style=3D"color:#000"> </span><span style=3D"color:#008">=
float</span><span style=3D"color:#000"> b</span><span style=3D"color:#660">=
,</span><span style=3D"color:#000"> </span><span style=3D"color:#008">float=
</span><span style=3D"color:#000"> c</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">switc=
h</span><span style=3D"color:#000"> </span><span style=3D"color:#660">(</sp=
an><span style=3D"color:#000">i</span><span style=3D"color:#660">)</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">{</span><code><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#00=
8">case</span><span style=3D"color:#000"> </span><span style=3D"color:#066"=
>0</span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span s=
tyle=3D"color:#000"> a</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"></span></code><code><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#066">1</span><span style=3D"color:#660">:=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">return</span><span style=3D"color:#000"> b</span><span st=
yle=3D"color:#660">;</span><span style=3D"color:#000"></span></code><code><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#00=
8">case</span><span style=3D"color:#000"> </span><span style=3D"color:#066"=
>2</span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span s=
tyle=3D"color:#000"> c</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"></span></code><span style=3D"color:#000"><br>=C2=A0 </span>=
<span style=3D"color:#660">}</span><span style=3D"color:#000"><br></span><s=
pan style=3D"color:#660">}</span><span style=3D"color:#000"><br></span></di=
v></code></div><br>The delayed evaluation is important to allow a parameter=
 with side effects not to be executed if not needed, avoiding undefined beh=
aviors:<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:#606">float *p;<br><br>if (p &amp;&amp; *p &gt; 0) { ... } // thi=
s is valid<br><br>bool AND(bool a, bool b) {<br>=C2=A0 return a &amp;&amp; =
b;<br>}<br><br>if (AND(p, *p &gt; 0)) { ... } // This is not<br></span><spa=
n style=3D"color:#660"></span></div></code></div><br><br>I thought of 4 way=
s to express that:<br><br>Type qualifier + implicit evaluation:<br><div sty=
le=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);borde=
r-style:solid;border-width:1px"><code><div><div style=3D"background-color:r=
gb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-wid=
th:1px"><code><div><span style=3D"color:#008">float</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#008">select</span><span style=3D"co=
lor:#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"color:#00=
0"> </span><span style=3D"color:#008">float @</span><span style=3D"color:#0=
00"> a</span><span style=3D"color:#660">,</span><span style=3D"color:#000">=
 </span><span style=3D"color:#008">float</span><span style=3D"color:#000"> =
@ b</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </=
span><span style=3D"color:#008">float</span><span style=3D"color:#000"> @ c=
</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">switch</span><span style=3D"color:#000"> =
</span><span style=3D"color:#660">(</span><span style=3D"color:#000">i</spa=
n><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#660">{</span><code><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"color:#=
000"> </span><span style=3D"color:#066">0</span><span style=3D"color:#660">=
:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span st=
yle=3D"color:#008">return</span><span style=3D"color:#000"> a</span><span s=
tyle=3D"color:#660">;</span><span style=3D"color:#000"></span></code><code>=
<span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#0=
08">case</span><span style=3D"color:#000"> </span><span style=3D"color:#066=
">1</span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span =
style=3D"color:#000"> b</span><span style=3D"color:#660">;</span><span styl=
e=3D"color:#000"></span></code><code><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#066">2</span><span style=3D"color:#660">:=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">return</span><span style=3D"color:#000"> c</span><span st=
yle=3D"color:#660">;</span><span style=3D"color:#000"></span></code><span s=
tyle=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#660">}</span><s=
pan style=3D"color:#000"><br></span><span style=3D"color:#660">}</span><spa=
n style=3D"color:#000"><br></span></div></code></div><span style=3D"color:#=
660"></span></div></code></div><br>Type qualifier + operator:<br><div style=
=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-=
style:solid;border-width:1px"><code><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">float</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#008">select</span><span style=3D"colo=
r:#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"color:#000"=
> </span><span style=3D"color:#008">float @</span><span style=3D"color:#000=
"> a</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#008">float</span><span style=3D"color:#000"> @ =
b</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#008">float</span><span style=3D"color:#000"> @ c</=
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">switch</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">)</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#660">{</span><code><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#066">0</span><span style=3D"color:#660">:=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">return</span><span style=3D"color:#000"> @a</span><span s=
tyle=3D"color:#660">;</span><span style=3D"color:#000"></span></code><code>=
<span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#0=
08">case</span><span style=3D"color:#000"> </span><span style=3D"color:#066=
">1</span><span style=3D"color:#660">:</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span =
style=3D"color:#000"> @b</span><span style=3D"color:#660">;</span><span sty=
le=3D"color:#000"></span></code><code><span style=3D"color:#000"><br>=C2=A0=
 =C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"color:#=
000"> </span><span style=3D"color:#066">2</span><span style=3D"color:#660">=
:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span st=
yle=3D"color:#008">return</span><span style=3D"color:#000"> @c</span><span =
style=3D"color:#660">;</span><span style=3D"color:#000"></span></code><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:#660">}</span><s=
pan style=3D"color:#000"><br></span></div></code></div><span style=3D"color=
:#660"></span></div></code></div><br>Type qualifier + callable:<div style=
=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-=
style:solid;border-width:1px"><code><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">float</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#008">select</span><span style=3D"colo=
r:#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"color:#000"=
> </span><span style=3D"color:#008">float</span><span style=3D"color:#000">=
 @ a</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#008">float @</span><span style=3D"color:#000"> =
b</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#008">float @</span><span style=3D"color:#000"> c</=
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">switch</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">)</span><span style=3D"color:#000"> </span><span=
 style=3D"color:#660">{</span><code><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#066">0</span><span style=3D"color:#660">:=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">return</span><span style=3D"color:#000"> a</span><span st=
yle=3D"color:#660">();</span><span style=3D"color:#000"></span></code><code=
><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#=
008">case</span><span style=3D"color:#000"> </span><span style=3D"color:#06=
6">1</span><span style=3D"color:#660">:</span><span style=3D"color:#000"><b=
r>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span=
 style=3D"color:#000"> b</span><span style=3D"color:#660">();</span><span s=
tyle=3D"color:#000"></span></code><code><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#066">2</span><span style=3D"color:#66=
0">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span=
 style=3D"color:#008">return</span><span style=3D"color:#000"> c</span><spa=
n style=3D"color:#660">();</span><span style=3D"color:#000"></span></code><=
span style=3D"color:#000"><br>=C2=A0 </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></span></div></code></div><span style=3D"c=
olor:#660"></span></div></code></div><br>STL type:<br><div style=3D"backgro=
und-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid=
;border-width:1px"><code><div><span style=3D"color:#008">float</span><span =
style=3D"color:#000"> </span><span style=3D"color:#008">select</span><span =
style=3D"color:#660">(</span><span style=3D"color:#008">int</span><span sty=
le=3D"color:#000"> i</span><span style=3D"color:#660">,</span><span style=
=3D"color:#000"> </span><code><span style=3D"color:#008">std::expression&lt=
;float&gt;</span><span style=3D"color:#000"></span></code><span style=3D"co=
lor:#000"> a</span><span style=3D"color:#660">,</span><span style=3D"color:=
#000"> </span><code><code><span style=3D"color:#008">std::expression&lt;flo=
at&gt;</span><span style=3D"color:#000"></span></code><span style=3D"color:=
#000"></span></code><span style=3D"color:#000"> b</span><span style=3D"colo=
r:#660">,</span><span style=3D"color:#000"> </span><code><code><span style=
=3D"color:#008">std::expression&lt;float&gt;</span><span style=3D"color:#00=
0"></span></code><span style=3D"color:#000"></span></code><span style=3D"co=
lor:#000"> c</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">switch</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660">(</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><code><span style=3D"color:#000=
"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#066">0</span><span style=3D"=
color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">return</span><span style=3D"color:#000"> a</=
span><span style=3D"color:#660">();</span><span style=3D"color:#000"></span=
></code><code><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span sty=
le=3D"color:#008">case</span><span style=3D"color:#000"> </span><span style=
=3D"color:#066">1</span><span style=3D"color:#660">:</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">retur=
n</span><span style=3D"color:#000"> b</span><span style=3D"color:#660">();<=
/span><span style=3D"color:#000"></span></code><code><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">case</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#066">2</span><span style=
=3D"color:#660">:</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 </span><span style=3D"color:#008">return</span><span style=3D"color:#000">=
 c</span><span style=3D"color:#660">();</span><span style=3D"color:#000"></=
span></code><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"col=
or:#660">}</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=
><br>In all the 3 cases, when the <span style=3D"font-family:courier new,mo=
nospace">select</span> function is called, a functor-like object is created=
 computing the expression, and this object is then passed to the function.<=
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:=
#606">float* p;<br>int i;<br><br>float r =3D select(i, 1.f, *p, std::sqrt(*=
p));<br><br>// equivalent to:<br><br>float r;<br>switch (i) {<br>=C2=A0 cas=
e 0:<br>=C2=A0=C2=A0=C2=A0 r =3D 1.f;<br>=C2=A0=C2=A0=C2=A0 break;</span><c=
ode><span style=3D"color:#606"><br>=C2=A0 case 1:<br>=C2=A0=C2=A0=C2=A0 r =
=3D *p;<br>=C2=A0=C2=A0=C2=A0 break;</span></code><span style=3D"color:#606=
"><code><span style=3D"color:#606"><br>=C2=A0 case 2:<br>=C2=A0=C2=A0=C2=A0=
 r =3D std::sqrt(*p);<br>=C2=A0=C2=A0=C2=A0 break;</span></code></span></di=
v><div><span style=3D"color:#606"><code><span style=3D"color:#606"></span><=
/code>}<br></span><span style=3D"color:#660"></span></div></code></div><br>=
I really have the impression this could be very interesting in some corner =
cases where there is currently no alternatives to do that safely (and effic=
iently).<br><br>Would this be sensible? Were there any attempt to formalize=
 passing by expression?<br>Which way of expressing this should be preferred=
?<br><br>I would be glad to answer any question.<br><br>Florian<br></div></=
blockquote></div></div></blockquote></div></blockquote></div></blockquote>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/aa6821c0-7e90-4bbd-bc70-5a774ae73ad9%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/aa6821c0-7e90-4bbd-bc70-5a774ae73ad9=
%40isocpp.org</a>.<br />

------=_Part_7422_1505583873.1529062979443--

------=_Part_7421_2125087075.1529062979441--

.


Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Fri, 12 Oct 2018 11:11:17 -0400
Raw View
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__) // ?
  #define signal protected
  #define with(x) if(x; true)

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.

.


Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Fri, 12 Oct 2018 14:30:46 -0400
Raw View
On 12/10/2018 12.41, Corentin wrote:
> the thing we must be careful with is to keep in mind that some usages for
> macros are _not_ worth replacing

If by that, you mean that the preprocessor is not a terrible evil that
must be replaced at all costs... then I'd have to agree :-). Sure, there
are some things that maybe can be done *better* in other ways, but I've
never really understood the anti-PP crowd.

> On Fri, 12 Oct 2018 at 17:11 Matthew Woehlke wrote:
>> 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.

Yes, this was probably not the best example. In the case that the macro
argument is definitely a single "thing", then I would hope reflection
can potentially replace such uses.

I'm less convinced we can replace e.g.:

  #define EXPECT_EQUAL(a, b) \
    ::testing::expect_equal(a, b, #a, #b, __FILE__, __LINE__, true)

>>   #define signal protected
>
> A better solution would be [[qt::signal]] void my signal.

Plausible, though annoying to have to mark *every* signal and slot. This
makes me wonder if being able to apply an attribute to an access
specifier (which would implicitly "percolate" to everything so affected)
would be desirable?

> I think means to defining dialects should be specifically a non-goal in
> this problem space

....but if that's the case, will you still use the preprocessor? (BTW,
I'm fine with that!)

>>   #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.

Right. And by folks that really, really want a `with` statement ;-).
OTOH, some of the more useful cases of this form are being replaced with
real grammar, e.g. range-based for.

--
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/c15109d8-960b-2316-dcd7-255bcbc2e151%40gmail.com.

.


Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Tue, 16 Oct 2018 11:40:26 -0400
Raw View
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.

.


Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Tue, 16 Oct 2018 13:20:28 -0400
Raw View
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.

.