Topic: Propsal(s): Capture List Type Aliases and Extended


Author: Adi Shavit <adishavit@gmail.com>
Date: Sun, 30 Oct 2016 15:09:16 +0200
Raw View
--001a113ebaa638c2be054014ce38
Content-Type: text/plain; charset=UTF-8

Hi,

  These 2 related proposals are based on a discussion with Klemens
Morgenstern on the C++ Slack #future_standard list
<https://cpplang.slack.com/archives/future_standard/p1477826208000681>.

*TL;DR*
Allow this code:

auto payload = std::tie(x,y);
auto f = [*using payload_type = decltype(payload)*, // 1.1 Capture type
alias
          *&my_static*,                             // 1.2 Capture static
by ref
          *&my_constexpr*]                          // 1.3 Capture
constexpr (at least by ref)
          (void* user_data)
{
   auto& payload = *reinterpret_cast<*payload_type**>(user_data);
  /// do smt with payload, my_static, my_constexpr
}

c_api_call_with_callback(*f*, &payload); // 2. Allow conversion of *f* to
fn-ptr as a *capture-less* lambda



*Motivation:*

Consider this code:

01 auto payload = std::tie(x,y);              // no explicit type specified
02 *using payload_type = decltype(payload); *   // create named type
payload_type
03 auto f = [](void* user_data)               // captureless lambda
04 {
05    auto& payload = *reinterpret_cast<*payload_type**>(user_data);  //
use payload_type
06   /// do smt with payload
07 }
....
28 c_api_call_with_callback(*f*, &payload);     // f converted to fn-ptr in
arg 1


It is a common C idiom to have a callback API which has an extra void*
user_data (but this is not the main point of the proposal).

The issues that I want to point out in the code are:

   1. Line 02: using declaration with decltype;
   2. Line 05: The body of f uses payload_type without it being explicitly
   captured. It is defined *outside* the lambda and still found.
   3. Line 28: The capture-less lambda f is implicitly converted to a
   function pointer.

In fact, payload_type is not used anywhere *outside* the lambda. It is only
used inside the lambda.
One might consider moving line 02 *into* the lambda.
Unfortunately, the rules for type name lookup are different from the rules
for variable name lookup for decltype and since payload is not captured it
will not found and thus using payload_type = decltype(payload); cannot be
written *inside* the lambda.

Basically, today, the type of payload needs to be wrapped in a named type
before it can pierce the capture-less lambda without being explicitly
captured.

One solution would be to extend the symbol search scope for decltype().
That may be more complicated than needed.

Klemens Morgenstern suggested a more explicit solution which is to allow
type aliases in the capture list + allow such lambas (with no other
value/ref captures) to still be convertible to function pointers.

Although this is more explicit it, it does also raise the question of why
only types?
Basically, any "thing" that can be wrapped up in an external "transient"
type  should be allowed into a lambda capture list without preventing it
from remaining convertible to a function pointers.
Thus, why not allow capturing static variables and constexpr values by
reference too?

There aren't even any lifetime/stack issues as there may be with other
captured ref values since statics live forever and constexpr are compile
time values which the compiler knows how to manage.

So in short, this could be thought of as 2 related proposals:

   1. Type aliases in the capture list
   2. Extended function-pointer conversions.

(1) by itself may be interesting standalone, e.g. by keeping the external
code clean of unnecessary symbols.
(2) with or w/o (2) will extend the fn-ptr conversion to &constexpr,
&static and w/(1) type aliases too.


Do let me know your thoughts, comments, suggestions, feedback, criticisms,
objections etc. about these ideas.

Warm regards,
Adi

--
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/CAEWUs4jc-iTz5Z1xCGakRoJs7_8rooTPBwg%3DUxEJSzjCyC%2BZOg%40mail.gmail.com.

--001a113ebaa638c2be054014ce38
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Hi,<div><br></div><div>=C2=A0 These 2 related proposals ar=
e based on a discussion with Klemens Morgenstern on the <a href=3D"https://=
cpplang.slack.com/archives/future_standard/p1477826208000681" target=3D"_bl=
ank">C++ Slack #future_standard list</a>.</div><div><br></div><div><b>TL;DR=
</b></div><div>Allow this code:</div><div><br></div><div><blockquote style=
=3D"margin:0px 0px 0px 40px;border:none;padding:0px"><div><div><font face=
=3D"monospace, monospace">auto payload =3D std::tie(x,y);</font></div><div>=
<font face=3D"monospace, monospace">auto f =3D [<b>using payload_type =3D d=
ecltype(payload)</b>,=C2=A0</font><span style=3D"font-family:monospace,mono=
space">// 1.1 Capture type alias</span></div><div><font face=3D"monospace, =
monospace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 <b>&amp;my_static</b>, =C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 // 1.2 Capture static by ref =C2=A0 =C2=A0=C2=A0</font></=
div><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 <b>&amp;my_constexpr</b>] =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// 1.3 Capture constexpr (a=
t least by ref)</font></div><div><font face=3D"monospace, monospace">=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (void* user_data)=C2=A0</font></div><div><font=
 face=3D"monospace, monospace">{</font></div><div><font face=3D"monospace, =
monospace">=C2=A0 =C2=A0auto&amp; payload =3D *reinterpret_cast&lt;<b>paylo=
ad_<wbr>type</b>*&gt;(user_data);</font></div><div><font face=3D"monospace,=
 monospace">=C2=A0 /// do smt with payload,=C2=A0</font><span style=3D"font=
-family:monospace,monospace">my_static,=C2=A0</span><span style=3D"font-fam=
ily:monospace,monospace">my_<wbr>constexpr</span></div><div><font face=3D"m=
onospace, monospace">}</font></div><div><font face=3D"monospace, monospace"=
><br></font></div><div><font face=3D"monospace, monospace">c_api_call_with_=
callback(<b>f</b>, &amp;payload); // 2. Allow conversion of <b>f</b> to fn-=
ptr as a <b>capture-less</b> lambda</font></div></div></blockquote></div><d=
iv><br></div><div><b><br></b></div><div><b>Motivation:</b></div><div><br></=
div><div>Consider this code:</div><div><br></div><blockquote style=3D"margi=
n:0px 0px 0px 40px;border:none;padding:0px"><div><font face=3D"monospace, m=
onospace">01 auto payload =3D std::tie(x,y); =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0// no explicit type specified</font></div><div><font fa=
ce=3D"monospace, monospace">02 <b>using payload_type =3D decltype(payload);=
 </b>=C2=A0 =C2=A0// create named type=C2=A0</font><span style=3D"font-fami=
ly:monospace,monospace">payload_type</span></div><div><font face=3D"monospa=
ce, monospace">03 auto f =3D [](void* user_data) =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 // captureless lambda</font></div><div><font face=
=3D"monospace, monospace">04 {</font></div><div><font face=3D"monospace, mo=
nospace">05 =C2=A0 =C2=A0auto&amp; payload =3D *reinterpret_cast&lt;<b>payl=
oad_<wbr>type</b>*&gt;(user_data); =C2=A0// use=C2=A0</font><span style=3D"=
font-family:monospace,monospace">payload_type</span></div><div><font face=
=3D"monospace, monospace">06 =C2=A0 /// do smt with payload</font></div><di=
v><font face=3D"monospace, monospace">07 }</font></div><div><font face=3D"m=
onospace, monospace">...</font></div><div><font face=3D"monospace, monospac=
e">28 c_api_call_with_callback(<b>f</b>, &amp;payload); =C2=A0 =C2=A0 // f =
converted to fn-ptr in arg 1</font></div><div><br></div></blockquote><div><=
br></div><div>It is a common C idiom to have a callback API which has an ex=
tra <font face=3D"monospace, monospace">void* user_data</font> (but this is=
 not the main point of the proposal).</div><div><br></div><div>The issues t=
hat I want to point out in the code are:</div><div><ol><li>Line 02: using d=
eclaration with decltype;</li><li>Line 05: The body of f uses=C2=A0<span st=
yle=3D"font-family:monospace,monospace">payload_type=C2=A0</span>without it=
 being explicitly captured. It is defined=C2=A0<i>outside</i>=C2=A0the lamb=
da and still found.</li><li>Line 28: The capture-less lambda f is implicitl=
y converted to a function pointer.</li></ol><div>In fact,=C2=A0<span style=
=3D"font-family:monospace,monospace">payload_type</span>=C2=A0is not used a=
nywhere <i>outside</i>=C2=A0the lambda. It is only used inside the lambda.<=
/div><div>One might consider moving line 02 <i>into</i> the lambda.</div><d=
iv>Unfortunately, the rules for type name lookup are different from the rul=
es for variable name lookup for <font face=3D"monospace, monospace">decltyp=
e</font> and since=C2=A0<span style=3D"font-family:monospace,monospace">pay=
load</span>=C2=A0is not captured it will not found and thus=C2=A0<span styl=
e=3D"font-family:monospace,monospace">using payload_type =3D decltype(paylo=
ad); </span>cannot be written <i>inside</i>=C2=A0the lambda.</div></div><di=
v><br></div><div>Basically, today, the type of=C2=A0<span style=3D"font-fam=
ily:monospace,monospace">payload</span>=C2=A0needs to be wrapped in a named=
 type before it can pierce the capture-less lambda without being explicitly=
 captured.</div><div><br></div><div>One solution would be to extend the sym=
bol search scope for=C2=A0<span style=3D"font-family:monospace,monospace">d=
ecltype()</span>.</div><div>That may be more complicated than needed.</div>=
<div><br></div><div>Klemens Morgenstern suggested a more explicit solution =
which is to allow type aliases in the capture list + allow such lambas (wit=
h no other value/ref captures) to still be convertible to function pointers=
..</div><div><br></div><div>Although this is more explicit it, it does also =
raise the question of why only types?</div><div>Basically, any &quot;thing&=
quot; that can be wrapped up in an external &quot;transient&quot; type =C2=
=A0should be allowed into a lambda capture list without preventing it from =
remaining convertible to a function pointers.=C2=A0</div><div>Thus, why not=
 allow capturing <font face=3D"monospace, monospace">static</font> variable=
s and <font face=3D"monospace, monospace">constexpr</font> values by refere=
nce too?</div><div><br></div><div>There aren&#39;t even any lifetime/stack =
issues as there may be with other captured ref values since statics live fo=
rever and constexpr are compile time values which the compiler knows how to=
 manage.</div><div><br></div><div>So in short, this could be thought of as =
2 related proposals:</div><div><ol><li>Type aliases in the capture list<br>=
</li><li>Extended function-pointer conversions.</li></ol></div><div>(1) by =
itself may be interesting standalone, e.g. by keeping the external code cle=
an of unnecessary symbols.</div><div>(2) with or w/o (2) will extend the fn=
-ptr conversion to &amp;constexpr, &amp;static and w/(1) type aliases too.<=
/div><div><br></div><div><br></div><div>Do let me know your thoughts, comme=
nts, suggestions, feedback, criticisms, objections etc. about these ideas.<=
/div><div><br></div><div>Warm regards,</div><div>Adi</div><div><br></div></=
div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&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/CAEWUs4jc-iTz5Z1xCGakRoJs7_8rooTPBwg%=
3DUxEJSzjCyC%2BZOg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAEWUs4jc-iTz=
5Z1xCGakRoJs7_8rooTPBwg%3DUxEJSzjCyC%2BZOg%40mail.gmail.com</a>.<br />

--001a113ebaa638c2be054014ce38--

.