Topic: Address of bound member function
Author: Matthew <matt.fagan@muonenterprises.com>
Date: Sun, 20 Sep 2015 04:04:44 -0700 (PDT)
Raw View
------=_Part_4278_320398435.1442747084669
Content-Type: multipart/alternative;
boundary="----=_Part_4279_33519718.1442747084670"
------=_Part_4279_33519718.1442747084670
Content-Type: text/plain; charset=UTF-8
Hi,
I'm new to this list. I was wondering if there have been any proposals or
interest in taking address of bound member functions to return a lambda.
For example:
&object->memfun
would be shorthand for the following lambda:
[object](params_of_memfun...)->return_type_of_memfun {
return object->memfun(std::fwd<>(params_of_memfun...));
}
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_4279_33519718.1442747084670
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi,<br><br>I'm new to this list. I was wondering if th=
ere have been any proposals or interest in taking address of bound member f=
unctions to return a lambda.<br><br>For example:<br><div class=3D"prettypri=
nt" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 1=
87, 187); border-style: solid; border-width: 1px; word-wrap: break-word;"><=
code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">&</span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">object</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">-></span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">memfun<br>would be shorthand </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">for</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> the following </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">lambda</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: #008;" class=3D"s=
tyled-by-prettify">object</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">](</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">params_of_memfun</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">...)-></span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">return_type_of_memfun </span><span style=3D"color: #660;" 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: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">object</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">-></span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">memfun</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">fwd</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify"><>(</span><co=
de class=3D"prettyprint"><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify">params_of_memfun</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">...</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify"></span></code><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">));<br>}</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br></span></div></code></div><br><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_4279_33519718.1442747084670--
------=_Part_4278_320398435.1442747084669--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 20 Sep 2015 06:39:05 -0700 (PDT)
Raw View
------=_Part_3944_1683905031.1442756345154
Content-Type: multipart/alternative;
boundary="----=_Part_3945_1132145728.1442756345154"
------=_Part_3945_1132145728.1442756345154
Content-Type: text/plain; charset=UTF-8
I'll ignore the syntax and instead focus on the general idea.
It's way too narrowly focused. There is already a general desire to take an
arbitrary callable name (not a function/member pointer, but a name) and
convert it into a functor that forwards its arguments and return values,
keeping intact any and all overloading that might exist, with the exact
access controls (public/private/protected) that are available at the cite
where the functor was created.
The only advantage your suggestion has is the automatic binding of the
object pointer. And to be frank, automatic binding like that is dangerous,
since it can lead to resource issues. Binding ought to be more explicit.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3945_1132145728.1442756345154
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I'll ignore the syntax and instead focus on the genera=
l idea.<br><br>It's way too narrowly focused. There is already a genera=
l desire to take an arbitrary callable name (not a function/member pointer,=
but a name) and convert it into a functor that forwards its arguments and =
return values, keeping intact any and all overloading that might exist, wit=
h the exact access controls (public/private/protected) that are available a=
t the cite where the functor was created.<br><br>The only advantage your su=
ggestion has is the automatic binding of the object pointer. And to be fran=
k, automatic binding like that is dangerous, since it can lead to resource =
issues. Binding ought to be more explicit.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3945_1132145728.1442756345154--
------=_Part_3944_1683905031.1442756345154--
.
Author: David Krauss <potswa@gmail.com>
Date: Sun, 20 Sep 2015 22:37:17 +0800
Raw View
--Apple-Mail=_C22A3A80-02B3-4AC0-A0C6-DE9889121F1F
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9309=E2=80=9320, at 9:39 PM, Nicol Bolas <jmckesson@gmail.c=
om> wrote:
>=20
> I'll ignore the syntax and instead focus on the general idea.
>=20
> It's way too narrowly focused. There is already a general desire to take =
an arbitrary callable name (not a function/member pointer, but a name) and =
convert it into a functor that forwards its arguments and return values, ke=
eping intact any and all overloading that might exist, with the exact acces=
s controls (public/private/protected) that are available at the cite where =
the functor was created.
>=20
> The only advantage your suggestion has is the automatic binding of the ob=
ject pointer. And to be frank, automatic binding like that is dangerous, si=
nce it can lead to resource issues. Binding ought to be more explicit.
Namely, we have std::bind( &class::member, obj );
Any overload set reification proposal should account for member functions, =
though. They=E2=80=99re easy to forget about.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_C22A3A80-02B3-4AC0-A0C6-DE9889121F1F
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9309=
=E2=80=9320, at 9:39 PM, Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.=
com" class=3D"">jmckesson@gmail.com</a>> wrote:</div><br class=3D"Apple-=
interchange-newline"><div class=3D""><div dir=3D"ltr" class=3D"">I'll ignor=
e the syntax and instead focus on the general idea.<br class=3D""><br class=
=3D"">It's way too narrowly focused. There is already a general desire to t=
ake an arbitrary callable name (not a function/member pointer, but a name) =
and convert it into a functor that forwards its arguments and return values=
, keeping intact any and all overloading that might exist, with the exact a=
ccess controls (public/private/protected) that are available at the cite wh=
ere the functor was created.<br class=3D""><br class=3D"">The only advantag=
e your suggestion has is the automatic binding of the object pointer. And t=
o be frank, automatic binding like that is dangerous, since it can lead to =
resource issues. Binding ought to be more explicit.<br class=3D""></div></d=
iv></blockquote><br class=3D""></div><div>Namely, we have <font face=3D"Cou=
rier" class=3D"">std::bind( &class::member, obj );</font></div><br clas=
s=3D""><div class=3D"">Any overload set reification proposal should account=
for member functions, though. They=E2=80=99re easy to forget about.</div><=
div class=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_C22A3A80-02B3-4AC0-A0C6-DE9889121F1F--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 20 Sep 2015 10:00:11 -0700 (PDT)
Raw View
------=_Part_172_1842513930.1442768411079
Content-Type: multipart/alternative;
boundary="----=_Part_173_1443355437.1442768411080"
------=_Part_173_1443355437.1442768411080
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Sunday, September 20, 2015 at 10:37:28 AM UTC-4, David Krauss wrote:
>
>
> On 2015=E2=80=9309=E2=80=9320, at 9:39 PM, Nicol Bolas <jmck...@gmail.com=
<javascript:>>=20
> wrote:
>
> I'll ignore the syntax and instead focus on the general idea.
>
> It's way too narrowly focused. There is already a general desire to take=
=20
> an arbitrary callable name (not a function/member pointer, but a name) an=
d=20
> convert it into a functor that forwards its arguments and return values,=
=20
> keeping intact any and all overloading that might exist, with the exact=
=20
> access controls (public/private/protected) that are available at the cite=
=20
> where the functor was created.
>
> The only advantage your suggestion has is the automatic binding of the=20
> object pointer. And to be frank, automatic binding like that is dangerous=
,=20
> since it can lead to resource issues. Binding ought to be more explicit.
>
>
> Namely, we have std::bind( &class::member, obj );
>
> Any overload set reification proposal should account for member functions=
,=20
> though. They=E2=80=99re easy to forget about.
>
At first, I was going to say that it's unnecessary once we have the ability=
=20
to call member functions without member syntax (automatically converting=20
member(object) into object.member() if the first doesn't match). But then I=
=20
realized that this would unfairly bias reification towards non-member=20
functions, allowing you to override overload sets externally to a class.
That may be what you want, and it should be possible. But you may want the=
=20
other way around, and the automatic conversion is supposed to go both ways=
=20
(converting object.member() into member(object) if the first doesn't=20
match). And it's reasonable to let the user decide which to bias=20
reification in favor of: member or non-member.
And of course we'll need both ways if we don't get this automatic=20
conversion syntax ;)
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_173_1443355437.1442768411080
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Sunday, September 20, 2015 at 10:37:28 AM UTC-4, David Krauss wrote:<blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-=
left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word=
"><br><div><blockquote type=3D"cite"><div>On 2015=E2=80=9309=E2=80=9320, at=
9:39 PM, Nicol Bolas <<a href=3D"javascript:" target=3D"_blank" gdf-obf=
uscated-mailto=3D"7tEuhhVyBQAJ" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'javascript:';return true;" onclick=3D"this.href=3D'javascri=
pt:';return true;">jmck...@gmail.com</a>> wrote:</div><br><div><div =
dir=3D"ltr">I'll ignore the syntax and instead focus on the general ide=
a.<br><br>It's way too narrowly focused. There is already a general des=
ire to take an arbitrary callable name (not a function/member pointer, but =
a name) and convert it into a functor that forwards its arguments and retur=
n values, keeping intact any and all overloading that might exist, with the=
exact access controls (public/private/protected) that are available at the=
cite where the functor was created.<br><br>The only advantage your suggest=
ion has is the automatic binding of the object pointer. And to be frank, au=
tomatic binding like that is dangerous, since it can lead to resource issue=
s. Binding ought to be more explicit.<br></div></div></blockquote><br></div=
><div>Namely, we have <font face=3D"Courier">std::bind( &class::member,=
obj );</font></div><br><div>Any overload set reification proposal should a=
ccount for member functions, though. They=E2=80=99re easy to forget about.<=
/div></div></blockquote><div><br>At first, I was going to say that it's=
unnecessary once we have the ability to call member functions without memb=
er syntax (automatically converting member(object) into object.member() if =
the first doesn't match). But then I realized that this would unfairly =
bias reification towards non-member functions, allowing you to override ove=
rload sets externally to a class.<br><br>That may be what you want, and it =
should be possible. But you may want the other way around, and the automati=
c conversion is supposed to go both ways (converting object.member() into m=
ember(object) if the first doesn't match). And it's reasonable to l=
et the user decide which to bias reification in favor of: member or non-mem=
ber.<br><br>And of course we'll need both ways if we don't get this=
automatic conversion syntax ;)<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_173_1443355437.1442768411080--
------=_Part_172_1842513930.1442768411079--
.
Author: Viacheslav Usov <via.usov@gmail.com>
Date: Tue, 27 Oct 2015 04:43:29 -0700 (PDT)
Raw View
------=_Part_6080_574519377.1445946209221
Content-Type: multipart/alternative;
boundary="----=_Part_6081_836754198.1445946209222"
------=_Part_6081_836754198.1445946209222
Content-Type: text/plain; charset=UTF-8
>
>
>
I am referencing a related discussion on another forum:
https://isocpp.org/forums/iso-c-standard-discussion?place=topic%2Fstd-discussion%2Fox9gsvgKgEc%2Fdiscussion
That discussion was in itself a spin-off of an earlier (non)discussion in
yet another forum:
https://groups.google.com/d/topic/comp.std.c++/NyViDQRDHR8/discussion
Cheers,
V.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_6081_836754198.1445946209222
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><br></div></blockquote><div><br></div><div>I am referencing a related d=
iscussion on another forum: https://isocpp.org/forums/iso-c-standard-discus=
sion?place=3Dtopic%2Fstd-discussion%2Fox9gsvgKgEc%2Fdiscussion<br></div><di=
v><br></div><div>That discussion was in itself a spin-off of an earlier (no=
n)discussion in yet another forum: https://groups.google.com/d/topic/comp.s=
td.c++/NyViDQRDHR8/discussion=C2=A0</div><div><br></div><div>Cheers,<br></d=
iv><div>V.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_6081_836754198.1445946209222--
------=_Part_6080_574519377.1445946209221--
.
Author: Brent Friedman <fourthgeek@gmail.com>
Date: Tue, 27 Oct 2015 09:39:05 -0500
Raw View
--089e015374ec3374a20523170a4f
Content-Type: text/plain; charset=UTF-8
sg14 is interested in being able to take a virtual function + object and
resolve the specific function that would be called. We could use such a
feature to do manual devirtualization and other efficiency optimizations.
The bound member function syntax is one of our ideas for how to express
"what function will this resolve to?".
auto obj_func = &(obj->fun);
if (obj_func == &derived::fun)
{
obj->derived::fun();
}
else
{
obj->fun();
}
On Tue, Oct 27, 2015 at 6:43 AM, Viacheslav Usov <via.usov@gmail.com> wrote:
>
>>
> I am referencing a related discussion on another forum:
> https://isocpp.org/forums/iso-c-standard-discussion?place=topic%2Fstd-discussion%2Fox9gsvgKgEc%2Fdiscussion
>
> That discussion was in itself a spin-off of an earlier (non)discussion in
> yet another forum:
> https://groups.google.com/d/topic/comp.std.c++/NyViDQRDHR8/discussion
>
> Cheers,
> V.
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e015374ec3374a20523170a4f
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">sg14 is interested in being able to take a virtual functio=
n + object and resolve the specific function that would be called. We could=
use such a feature to do manual devirtualization and other efficiency opti=
mizations.<div><br></div><div>The bound member function syntax is one of ou=
r ideas for how to express "what function will this resolve to?".=
</div><div><br></div><div>auto obj_func =3D &(obj->fun);</div><div>i=
f (obj_func =3D=3D &derived::fun)</div><div>{</div><div>=C2=A0 =C2=A0ob=
j->derived::fun();</div><div>}</div><div>else</div><div>{</div><div>=C2=
=A0 =C2=A0obj->fun();</div><div>}</div></div><div class=3D"gmail_extra">=
<br><div class=3D"gmail_quote">On Tue, Oct 27, 2015 at 6:43 AM, Viacheslav =
Usov <span dir=3D"ltr"><<a href=3D"mailto:via.usov@gmail.com" target=3D"=
_blank">via.usov@gmail.com</a>></span> wrote:<br><blockquote class=3D"gm=
ail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:=
0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><br></div></blockquote><div><br></div><div>I am referencing a rela=
ted discussion on another forum: <a href=3D"https://isocpp.org/forums/iso-c=
-standard-discussion?place=3Dtopic%2Fstd-discussion%2Fox9gsvgKgEc%2Fdiscuss=
ion" target=3D"_blank">https://isocpp.org/forums/iso-c-standard-discussion?=
place=3Dtopic%2Fstd-discussion%2Fox9gsvgKgEc%2Fdiscussion</a><br></div><div=
><br></div><div>That discussion was in itself a spin-off of an earlier (non=
)discussion in yet another forum: <a href=3D"https://groups.google.com/d/to=
pic/comp.std.c++/NyViDQRDHR8/discussion" target=3D"_blank">https://groups.g=
oogle.com/d/topic/comp.std.c++/NyViDQRDHR8/discussion</a>=C2=A0</div><div><=
br></div><div>Cheers,<br></div><div>V.</div></div><div class=3D"HOEnZb"><di=
v class=3D"h5">
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e015374ec3374a20523170a4f--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 27 Oct 2015 08:02:37 -0700 (PDT)
Raw View
------=_Part_131_1876789590.1445958157975
Content-Type: multipart/alternative;
boundary="----=_Part_132_1903007631.1445958157975"
------=_Part_132_1903007631.1445958157975
Content-Type: text/plain; charset=UTF-8
On Tuesday, October 27, 2015 at 10:39:08 AM UTC-4, Brent Friedman wrote:
>
> sg14 is interested in being able to take a virtual function + object and
> resolve the specific function that would be called. We could use such a
> feature to do manual devirtualization and other efficiency optimizations.
>
I'm curious as to how, exactly. A virtual call involves getting the vtable,
followed by fetching the function pointer through an offset.
In order to do devirtualization within a hierarchy, you would have to have
each instance of different derived classes store function objects to the
actual function to be called. But since the storage for that functor is in
the base class, the object being stored has to be able to store any such
member pointer. I'm not sure if it's possible to do that without type
erasure or some other kind of virtual call.
Maybe I'm misunderstanding what you mean by "devirtualization".
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_132_1903007631.1445958157975
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, October 27, 2015 at 10:39:08 AM UTC-4, Brent F=
riedman wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
>sg14 is interested in being able to take a virtual function + object and r=
esolve the specific function that would be called. We could use such a feat=
ure to do manual devirtualization and other efficiency optimizations.</div>=
</blockquote><div><br>I'm curious as to how, exactly. A virtual call in=
volves getting the vtable, followed by fetching the function pointer throug=
h an offset.<br><br>In order to do devirtualization within a hierarchy, you=
would have to have each instance of different derived classes store functi=
on objects to the actual function to be called. But since the storage for t=
hat functor is in the base class, the object being stored has to be able to=
store any such member pointer. I'm not sure if it's possible to do=
that without type erasure or some other kind of virtual call.<br><br>Maybe=
I'm misunderstanding what you mean by "devirtualization".</d=
iv></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_132_1903007631.1445958157975--
------=_Part_131_1876789590.1445958157975--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 27 Oct 2015 08:18:15 -0700 (PDT)
Raw View
------=_Part_714_30151318.1445959095322
Content-Type: multipart/alternative;
boundary="----=_Part_715_1995388645.1445959095323"
------=_Part_715_1995388645.1445959095323
Content-Type: text/plain; charset=UTF-8
On Tuesday, October 27, 2015 at 7:08:35 AM UTC-4, Edward Catmur wrote:
>
> Most recent discussion on std-proposals:
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/eltqBVyh5H0/discussion
> - should we move to there?
>
> On Monday, 26 October 2015 20:24:35 UTC, Nicol Bolas wrote:
>>
>> On Monday, October 26, 2015 at 2:54:54 PM UTC-4, Miro Knejp wrote:
>>>
>>> Am 26.10.2015 um 19:03 schrieb Nicol Bolas:
>>>
>>> On Monday, October 26, 2015 at 1:01:46 PM UTC-4, Viacheslav Usov wrote:
>>>>
>>>> I'm pretty sure this is missing a number of `std::forward` calls and
>>>> `&&` syntax.
>>>>
>>> Which just strengthens his position that the "proper" way to do it is
>>> difficult to get right and suffers from boilerplate.
>>>
>>
>> I wasn't contesting the need for the general idea. My problem was with
>> his chosen form.
>>
>> C++ does need some way to say "give me a functor that will call this
>> function as if I typed that name." But this ought to be separate from
>> binding to variables, since that's way too easy to get wrong.
>>
>
> If you don't provide object binding, people are going to use std::bind or
> some partial applicator, which is just as easy to get wrong.
>
And what about the people who *don't* want to have binding mixed into it?
Who just want the overload member function set, callable on any appropriate
object? Whatever syntax gets used has to account for all of the viable
options.
We already want overload syntax, for member functions *and* non-member
functions. The obvious implementation is a lambda, so simply allow lambdas
to do it cleanly, without the boilerplate:
[]Class::Funcname; //Functor that calls the named member function, which
takes as a first parameter a Class reference/pointer/object.
[d]d.Funcname; //Functor that calls the named member function, using a
variable bound by lambda rules.
[]d.Funcname; //A compile error. You must explicitly bind the variable.
[]Funcname; //Functor calling a non-member function.
[this]Funcname; //Functor possibly calling a member function or
non-member function, depending on the type of `this`.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_715_1995388645.1445959095323
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, October 27, 2015 at 7:08:35 AM UTC-4, Edward Catmur wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Most recent d=
iscussion on std-proposals:=C2=A0<a href=3D"https://groups.google.com/a/iso=
cpp.org/d/topic/std-proposals/eltqBVyh5H0/discussion" target=3D"_blank" rel=
=3D"nofollow">https://groups.<wbr>google.com/a/isocpp.org/d/<wbr>topic/std-=
proposals/<wbr>eltqBVyh5H0/discussion</a> - should we move to there?</div><=
div><br></div>On Monday, 26 October 2015 20:24:35 UTC, Nicol Bolas wrote:<=
blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border=
-left:1px #ccc solid;padding-left:1ex">On Monday, October 26, 2015 at 2:54:=
54 PM UTC-4, Miro Knejp wrote:<blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">
=20
=20
=20
<div bgcolor=3D"#FFFFFF">
Am 26.10.2015 um 19:03 schrieb Nicol Bolas:<br>
<blockquote type=3D"cite">
<div dir=3D"ltr">On Monday, October 26, 2015 at 1:01:46 PM UTC-4,
Viacheslav Usov wrote:
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir=3D"ltr">I'm pretty sure this is missing a number of =
`std::forward`
calls and `&&` syntax.<br></div></blockquote></div></bloc=
kquote>
Which just strengthens his position that the "proper" way to =
do it
is difficult to get right and suffers from boilerplate.</div></blockquo=
te><div><br>I wasn't contesting the need for the general idea. My probl=
em was with his chosen form.<br><br>C++
does need some way to say "give me a functor that will call this=20
function as if I typed that name." But this ought to be separate from=
=20
binding to variables, since that's way too easy to get wrong.</div></bl=
ockquote><div><br></div><div>If you don't provide object binding, peopl=
e are going to use <font face=3D"courier new, monospace">std::bind</font> o=
r some partial applicator, which is just as easy to get wrong.</div></div><=
/blockquote><div><br>And what about the people who <i>don't</i> want to=
have binding mixed into it? Who just want the overload member function set=
, callable on any appropriate object? Whatever syntax gets used has to acco=
unt for all of the viable options.<br><br>We already want overload syntax, =
for member functions <i>and</i> non-member functions. The obvious implement=
ation is a lambda, so simply allow lambdas to do it cleanly, without the bo=
ilerplate:<br><br><div class=3D"prettyprint" style=3D"background-color: rgb=
(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bor=
der-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div cl=
ass=3D"subprettyprint"><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">[]</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Cl=
ass</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</spa=
n><span style=3D"color: #606;" class=3D"styled-by-prettify">Funcname</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: #800;" class=3D"styled-by-prettify">//Functor that calls the named memb=
er function, which takes as a first parameter a Class reference/pointer/obj=
ect.</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">[</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">d</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">]</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">d</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">.</span><span style=3D"color: #606;" class=3D"=
styled-by-prettify">Funcname</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> =C2=A0 =C2=A0 </span><span style=3D"color: #800;" class=3D"styled=
-by-prettify">//Functor that calls the named member function, using a varia=
ble bound by lambda rules.</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=
">d</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span=
><span style=3D"color: #606;" class=3D"styled-by-prettify">Funcname</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> =C2=A0 =C2=A0 =C2=A0</span=
><span style=3D"color: #800;" class=3D"styled-by-prettify">//A compile erro=
r. You must explicitly bind the variable.</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">[]</span><span style=3D"color: #606;" class=3D"sty=
led-by-prettify">Funcname</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">//Functor calling a non-member function.</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">[</span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">this</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">]</span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">Funcname</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> =C2=A0 =C2=A0</span><span style=3D"color: #800;" class=3D"s=
tyled-by-prettify">//Functor possibly calling a member function or non-memb=
er function, depending on the type of `this`.</span></div></code></div></di=
v><br>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_715_1995388645.1445959095323--
------=_Part_714_30151318.1445959095322--
.
Author: Brent Friedman <fourthgeek@gmail.com>
Date: Tue, 27 Oct 2015 10:45:45 -0500
Raw View
--089e0153687295eae3052317f861
Content-Type: text/plain; charset=UTF-8
>
> I'm curious as to how, exactly. A virtual call involves getting the
> vtable, followed by fetching the function pointer through an offset.
>
Right - the thought behind this is that &(obj->fun) would get the vtable
for obj and fetch the function pointer. It effectively separates the
virtual lookup step from the virtual call step. The result of the
expression is the concrete member function (or overload resolution set)
that *would* be called. We don't entirely know if it's feasible, sort of a
brainstorm at the moment.
On Tue, Oct 27, 2015 at 10:02 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Tuesday, October 27, 2015 at 10:39:08 AM UTC-4, Brent Friedman wrote:
>>
>> sg14 is interested in being able to take a virtual function + object and
>> resolve the specific function that would be called. We could use such a
>> feature to do manual devirtualization and other efficiency optimizations.
>>
>
> I'm curious as to how, exactly. A virtual call involves getting the
> vtable, followed by fetching the function pointer through an offset.
>
> In order to do devirtualization within a hierarchy, you would have to have
> each instance of different derived classes store function objects to the
> actual function to be called. But since the storage for that functor is in
> the base class, the object being stored has to be able to store any such
> member pointer. I'm not sure if it's possible to do that without type
> erasure or some other kind of virtual call.
>
> Maybe I'm misunderstanding what you mean by "devirtualization".
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0153687295eae3052317f861
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px =
0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-l=
eft-style:solid;padding-left:1ex">I'm curious as to how, exactly. A vir=
tual call involves getting the vtable, followed by fetching the function po=
inter through an offset.<br></blockquote><div><br></div><div>Right - the th=
ought behind this is that &(obj->fun) would get the vtable for obj a=
nd fetch the function pointer. It effectively separates the virtual lookup =
step from the virtual call step. The result of the expression is the concre=
te member function (or overload resolution set) that <b>would</b> be called=
.. We don't entirely know if it's feasible, sort of a brainstorm at =
the moment.</div></div><div class=3D"gmail_extra"><br><div class=3D"gmail_q=
uote">On Tue, Oct 27, 2015 at 10:02 AM, Nicol Bolas <span dir=3D"ltr"><<=
a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com=
</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin=
:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><=
span class=3D"">On Tuesday, October 27, 2015 at 10:39:08 AM UTC-4, Brent Fr=
iedman wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-lef=
t:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">sg14 =
is interested in being able to take a virtual function + object and resolve=
the specific function that would be called. We could use such a feature to=
do manual devirtualization and other efficiency optimizations.</div></bloc=
kquote></span><div><br>I'm curious as to how, exactly. A virtual call i=
nvolves getting the vtable, followed by fetching the function pointer throu=
gh an offset.<br><br>In order to do devirtualization within a hierarchy, yo=
u would have to have each instance of different derived classes store funct=
ion objects to the actual function to be called. But since the storage for =
that functor is in the base class, the object being stored has to be able t=
o store any such member pointer. I'm not sure if it's possible to d=
o that without type erasure or some other kind of virtual call.<br><br>Mayb=
e I'm misunderstanding what you mean by "devirtualization".</=
div></div><div class=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0153687295eae3052317f861--
.
Author: Viacheslav Usov <via.usov@gmail.com>
Date: Tue, 27 Oct 2015 19:02:30 +0100
Raw View
--089e013c66b4a4d574052319e18d
Content-Type: text/plain; charset=UTF-8
>
> We already want overload syntax, for member functions *and* non-member
> functions. The obvious implementation is a lambda, so simply allow lambdas
> to do it cleanly, without the boilerplate:
>
> []Class::Funcname; //Functor that calls the named member function, which
> takes as a first parameter a Class reference/pointer/object.
> [d]d.Funcname; //Functor that calls the named member function, using
> a variable bound by lambda rules.
> []d.Funcname; //A compile error. You must explicitly bind the
> variable.
> []Funcname; //Functor calling a non-member function.
> [this]Funcname; //Functor possibly calling a member function or
> non-member function, depending on the type of `this`.
>
How would we wrap static member functions with this?
I think this could be generalized further by introducing a placeholder
syntax. Something like the following: * forwards one argument, and ...
forwards any number, and it would not need to be at the end of the argument
list.
[a]a.f(...) // functor that calls member f, forwarding any number of
arguments
[a, b]a.f(b, ...) // functor that calls member f, with captured b and any
number of other arguments
[a, b, c]a.f(*, b, ..., c) // functor that calls member f, with one
placeholder, captured b and any number of other arguments in between
[b, c]*.f(b, ..., c) // functor that calls member f of first placeholder,
with captured b and any number of other arguments in between
In principle, the above does not need to be limited to "callable" names,
any expression should work just fine, but then dealing with placeholders
becomes messier. In principle again, nothing speaks against allowing
lambda-declarator_opt of [expr.prim.lambda] in such lambdas, but that will
re-introduce boilerplate. This needs more thinking.
Cheers,
V.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e013c66b4a4d574052319e18d
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left=
-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;paddi=
ng-left:1ex"><div>We already want overload syntax, for member functions <i>=
and</i> non-member functions. The obvious implementation is a lambda, so si=
mply allow lambdas to do it cleanly, without the boilerplate:<br><br><div s=
tyle=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;background-c=
olor:rgb(250,250,250)"><code><div><span style=3D"color:rgb(102,102,0)">[]</=
span><span style=3D"color:rgb(102,0,102)">Class</span><span style=3D"color:=
rgb(102,102,0)">::</span><span style=3D"color:rgb(102,0,102)">Funcname</spa=
n><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0=
,0)"> </span><span style=3D"color:rgb(136,0,0)">//Functor that calls the na=
med member function, which takes as a first parameter a Class reference/poi=
nter/object.</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=
=3D"color:rgb(102,102,0)">[</span><span style=3D"color:rgb(0,0,0)">d</span>=
<span style=3D"color:rgb(102,102,0)">]</span><span style=3D"color:rgb(0,0,0=
)">d</span><span style=3D"color:rgb(102,102,0)">.</span><span style=3D"colo=
r:rgb(102,0,102)">Funcname</span><span style=3D"color:rgb(102,102,0)">;</sp=
an><span style=3D"color:rgb(0,0,0)"> =C2=A0 =C2=A0 </span><span style=3D"co=
lor:rgb(136,0,0)">//Functor that calls the named member function, using a v=
ariable bound by lambda rules.</span><span style=3D"color:rgb(0,0,0)"><br><=
/span><span style=3D"color:rgb(102,102,0)">[]</span><span style=3D"color:rg=
b(0,0,0)">d</span><span style=3D"color:rgb(102,102,0)">.</span><span style=
=3D"color:rgb(102,0,102)">Funcname</span><span style=3D"color:rgb(102,102,0=
)">;</span><span style=3D"color:rgb(0,0,0)"> =C2=A0 =C2=A0 =C2=A0</span><sp=
an style=3D"color:rgb(136,0,0)">//A compile error. You must explicitly bind=
the variable.</span><span style=3D"color:rgb(0,0,0)"><br></span><span styl=
e=3D"color:rgb(102,102,0)">[]</span><span style=3D"color:rgb(102,0,102)">Fu=
ncname</span><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"co=
lor:rgb(0,0,0)"> =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:rgb=
(136,0,0)">//Functor calling a non-member function.</span><span style=3D"co=
lor:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)">[</span><sp=
an style=3D"color:rgb(0,0,136)">this</span><span style=3D"color:rgb(102,102=
,0)">]</span><span style=3D"color:rgb(102,0,102)">Funcname</span><span styl=
e=3D"color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"> =C2=A0=
=C2=A0</span><span style=3D"color:rgb(136,0,0)">//Functor possibly calling=
a member function or non-member function, depending on the type of `this`.=
</span></div></code></div></div></blockquote><div><br></div><div>How would =
we wrap static member functions with this?</div><div><br></div><div>I think=
this could be generalized further by introducing a placeholder syntax. Som=
ething like the following: * forwards one argument, and ... forwards any nu=
mber, and it would not need to be at the end of the argument list.</div><di=
v><br></div><div>[a]a.f(...) // functor that calls member f, forwarding any=
number of arguments</div><div>[a, b]a.f(b, ...) // functor that calls memb=
er f, with captured b and any number of other arguments</div><div>[a, b, c]=
a.f(*, b, ..., c) // functor that calls member f, with one placeholder, cap=
tured b and any number of other arguments in between</div><div><div>[b, c]*=
..f(b, ..., c) // functor that calls member f of first placeholder, with cap=
tured b and any number of other arguments=C2=A0in between</div></div><div><=
br></div><div>In principle, the above does not need to be limited to "=
callable" names, any expression should work just fine, but then dealin=
g with placeholders becomes messier. In principle again, nothing speaks aga=
inst allowing lambda-declarator_opt of [expr.prim.lambda] in such lambdas, =
but that will re-introduce boilerplate. This needs more thinking.</div><div=
><br></div><div>Cheers,</div><div>V.</div></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e013c66b4a4d574052319e18d--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 27 Oct 2015 11:36:16 -0700 (PDT)
Raw View
------=_Part_970_1885732590.1445970976452
Content-Type: multipart/alternative;
boundary="----=_Part_971_798309319.1445970976453"
------=_Part_971_798309319.1445970976453
Content-Type: text/plain; charset=UTF-8
On Tuesday, October 27, 2015 at 2:02:31 PM UTC-4, Viacheslav Usov wrote:
>
> We already want overload syntax, for member functions *and* non-member
>> functions. The obvious implementation is a lambda, so simply allow lambdas
>> to do it cleanly, without the boilerplate:
>>
>> []Class::Funcname; //Functor that calls the named member function, which
>> takes as a first parameter a Class reference/pointer/object.
>> [d]d.Funcname; //Functor that calls the named member function, using
>> a variable bound by lambda rules.
>> []d.Funcname; //A compile error. You must explicitly bind the
>> variable.
>> []Funcname; //Functor calling a non-member function.
>> [this]Funcname; //Functor possibly calling a member function or
>> non-member function, depending on the type of `this`.
>>
>
> How would we wrap static member functions with this?
>
If `Class::Function` is a static member, then the resulting functor calls
that.
> I think this could be generalized further by introducing a placeholder
> syntax. Something like the following: * forwards one argument, and ...
> forwards any number, and it would not need to be at the end of the argument
> list.
>
I'd much rather start small and expand it later than try to cram arbitrary
and universal binding syntax into this. By focusing on the biggest problem
(wrapping a function overload set), you can then extend it as needed later.
Just having the basic overload set stuff I outlined above solves about 90%
of uses of std::bind.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_971_798309319.1445970976453
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, October 27, 2015 at 2:02:31 PM UTC-4, Viacheslav Usov wrote:<bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=
=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px =
0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-l=
eft-style:solid;padding-left:1ex"><div>We already want overload syntax, for=
member functions <i>and</i> non-member functions. The obvious implementati=
on is a lambda, so simply allow lambdas to do it cleanly, without the boile=
rplate:<br><br><div style=3D"border:1px solid rgb(187,187,187);word-wrap:br=
eak-word;background-color:rgb(250,250,250)"><code><div><span style=3D"color=
:rgb(102,102,0)">[]</span><span style=3D"color:rgb(102,0,102)">Class</span>=
<span style=3D"color:rgb(102,102,0)">::</span><span style=3D"color:rgb(102,=
0,102)">Funcname</span><span style=3D"color:rgb(102,102,0)">;</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(136,0,0)">//Func=
tor that calls the named member function, which takes as a first parameter =
a Class reference/pointer/object.</span><span style=3D"color:rgb(0,0,0)"><b=
r></span><span style=3D"color:rgb(102,102,0)">[</span><span style=3D"color:=
rgb(0,0,0)">d</span><span style=3D"color:rgb(102,102,0)">]</span><span styl=
e=3D"color:rgb(0,0,0)">d</span><span style=3D"color:rgb(102,102,0)">.</span=
><span style=3D"color:rgb(102,0,102)">Funcname</span><span style=3D"color:r=
gb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"> =C2=A0 =C2=A0 </sp=
an><span style=3D"color:rgb(136,0,0)">//Functor that calls the named member=
function, using a variable bound by lambda rules.</span><span style=3D"col=
or:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)">[]</span><sp=
an style=3D"color:rgb(0,0,0)">d</span><span style=3D"color:rgb(102,102,0)">=
..</span><span style=3D"color:rgb(102,0,102)">Funcname</span><span style=3D"=
color:rgb(102,102,0)">;</span><span style=3D"color:rgb(0,0,0)"> =C2=A0 =C2=
=A0 =C2=A0</span><span style=3D"color:rgb(136,0,0)">//A compile error. You =
must explicitly bind the variable.</span><span style=3D"color:rgb(0,0,0)"><=
br></span><span style=3D"color:rgb(102,102,0)">[]</span><span style=3D"colo=
r:rgb(102,0,102)">Funcname</span><span style=3D"color:rgb(102,102,0)">;</sp=
an><span style=3D"color:rgb(0,0,0)"> =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><spa=
n style=3D"color:rgb(136,0,0)">//Functor calling a non-member function.</sp=
an><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102=
,102,0)">[</span><span style=3D"color:rgb(0,0,136)">this</span><span style=
=3D"color:rgb(102,102,0)">]</span><span style=3D"color:rgb(102,0,102)">Func=
name</span><span style=3D"color:rgb(102,102,0)">;</span><span style=3D"colo=
r:rgb(0,0,0)"> =C2=A0 =C2=A0</span><span style=3D"color:rgb(136,0,0)">//Fun=
ctor possibly calling a member function or non-member function, depending o=
n the type of `this`.</span></div></code></div></div></blockquote><div><br>=
</div><div>How would we wrap static member functions with this?</div></div>=
</div></div></blockquote><div><br>If `Class::Function` is a static member, =
then the resulting functor calls that.<br>=C2=A0</div><blockquote class=3D"=
gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc so=
lid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><d=
iv></div><div>I think this could be generalized further by introducing a pl=
aceholder syntax. Something like the following: * forwards one argument, an=
d ... forwards any number, and it would not need to be at the end of the ar=
gument list.</div></div></div></div></blockquote><div><br>I'd much rath=
er start small and expand it later than try to cram arbitrary and universal=
binding syntax into this. By focusing on the biggest problem (wrapping a f=
unction overload set), you can then extend it as needed later.<br><br>Just =
having the basic overload set stuff I outlined above solves about 90% of us=
es of std::bind.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_971_798309319.1445970976453--
------=_Part_970_1885732590.1445970976452--
.
Author: Sean Middleditch <sean.middleditch@gmail.com>
Date: Tue, 27 Oct 2015 21:10:48 -0700 (PDT)
Raw View
------=_Part_117_458376557.1446005448694
Content-Type: multipart/alternative;
boundary="----=_Part_118_1824787541.1446005448694"
------=_Part_118_1824787541.1446005448694
Content-Type: text/plain; charset=UTF-8
On Tuesday, October 27, 2015 at 8:18:15 AM UTC-7, Nicol Bolas wrote:
>
> We already want overload syntax, for member functions *and* non-member
> functions. The obvious implementation is a lambda, so simply allow lambdas
> to do it cleanly, without the boilerplate:
>
> []Class::Funcname; //Functor that calls the named member function, which
> takes as a first parameter a Class reference/pointer/object.
> [d]d.Funcname; //Functor that calls the named member function, using
> a variable bound by lambda rules.
> []d.Funcname; //A compile error. You must explicitly bind the
> variable.
> []Funcname; //Functor calling a non-member function.
> [this]Funcname; //Functor possibly calling a member function or
> non-member function, depending on the type of `this`.
>
>
That looks a lot like an extended variation on
https://isocpp.org/files/papers/n3617.txt for what it's worth.
It's an active EWG issue
(http://cplusplus.github.io/EWG/ewg-active.html#65) and so far as I can
tell has never been thoroughly reviewed or voted on.
Someone with an interest should write a followup paper and take it to
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_118_1824787541.1446005448694
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, October 27, 2015 at 8:18:15 AM UTC-7, Nicol Bolas wrote:<blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div>We already want overload syntax,=
for member functions <i>and</i> non-member functions. The obvious implemen=
tation is a lambda, so simply allow lambdas to do it cleanly, without the b=
oilerplate:<br><br><div style=3D"background-color:rgb(250,250,250);border-c=
olor:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break-w=
ord"><code><div><span style=3D"color:#660">[]</span><span style=3D"color:#6=
06">Class</span><span style=3D"color:#660">::</span><span style=3D"color:#6=
06">Funcname</span><span style=3D"color:#660">;</span><span style=3D"color:=
#000"> </span><span style=3D"color:#800">//Functor that calls the named mem=
ber function, which takes as a first parameter a Class reference/pointer/ob=
ject.</span><span style=3D"color:#000"><br></span><span style=3D"color:#660=
">[</span><span style=3D"color:#000">d</span><span style=3D"color:#660">]</=
span><span style=3D"color:#000">d</span><span style=3D"color:#660">.</span>=
<span style=3D"color:#606">Funcname</span><span style=3D"color:#660">;</spa=
n><span style=3D"color:#000"> =C2=A0 =C2=A0 </span><span style=3D"color:#80=
0">//Functor that calls the named member function, using a variable bound b=
y lambda rules.</span><span style=3D"color:#000"><br></span><span style=3D"=
color:#660">[]</span><span style=3D"color:#000">d</span><span style=3D"colo=
r:#660">.</span><span style=3D"color:#606">Funcname</span><span style=3D"co=
lor:#660">;</span><span style=3D"color:#000"> =C2=A0 =C2=A0 =C2=A0</span><s=
pan style=3D"color:#800">//A compile error. You must explicitly bind the va=
riable.</span><span style=3D"color:#000"><br></span><span style=3D"color:#6=
60">[]</span><span style=3D"color:#606">Funcname</span><span style=3D"color=
:#660">;</span><span style=3D"color:#000"> =C2=A0 =C2=A0 =C2=A0 =C2=A0</spa=
n><span style=3D"color:#800">//Functor calling a non-member function.</span=
><span style=3D"color:#000"><br></span><span style=3D"color:#660">[</span><=
span style=3D"color:#008">this</span><span style=3D"color:#660">]</span><sp=
an style=3D"color:#606">Funcname</span><span style=3D"color:#660">;</span><=
span style=3D"color:#000"> =C2=A0 =C2=A0</span><span style=3D"color:#800">/=
/Functor possibly calling a member function or non-member function, dependi=
ng on the type of `this`.</span></div></code></div></div><br></blockquote><=
div><br></div><div>That looks a lot like an extended variation on https://i=
socpp.org/files/papers/n3617.txt for what it's worth.</div><div><br></d=
iv><div>It's an active EWG issue (http://cplusplus.github.io/EWG/ewg-ac=
tive.html#65) and so far as I can tell has never been thoroughly reviewed o=
r voted on.</div><div><br></div><div>Someone with an interest should write =
a followup paper and take it to Jacksonville. :)</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_118_1824787541.1446005448694--
------=_Part_117_458376557.1446005448694--
.
Author: Matthew <matt.fagan@muonenterprises.com>
Date: Tue, 27 Oct 2015 22:17:43 -0700 (PDT)
Raw View
------=_Part_7124_719329200.1446009463672
Content-Type: multipart/alternative;
boundary="----=_Part_7125_1745998436.1446009463673"
------=_Part_7125_1745998436.1446009463673
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
=20
Proposal for address of bound function:
=20
I want to give a more concrete proposal for how I think the address of=20
bound function operation would work. These ideas are based on two very=20
specific use cases, so I will state those up-front because it appears from=
=20
reading people's comments that there are other use cases which I haven't=20
given much consideration to. Note also, I will use the syntax (&object.fun)=
=20
as example syntax. Other syntax may be more appropriate. I've just thrown=
=20
this together for now, as I would like feedback before getting more=20
specific/detailed.
=20
Use case 1: "Native C++" callback functions:
C currently has a fairly standard callback function system, which consists=
=20
of the following type of registration function:
=20
typedef RetType(Callback*)(void* UserData, params=E2=80=A6)
void RegisterCallback(Callback* CallbackFunc, void* UserData);
=20
This works well for C where data/functions are not linked. However, in many=
=20
cases C++ programs want UserData to point to an object, and callbackfunc to=
=20
be a member function of that object. That is, we want to be able to have:
=20
typedef RetType(*::MemCallback*)(params)
void RegisterCallback(MemCallback* CallbackMemberFunction);
=20
which could be called using the following or similar syntax:
RegisterCallback(&object.memfunc)
=20
I think that this could be described as the "native C++" equivalent to=20
C-style callback functions. Note that it is possible for this to work=20
without dynamic memory allocation and by utilizing only the memory space of=
=20
2 pointers for storing the function call. However, it is not possible with=
=20
the current C++ spec.
=20
Use case 2: Wrapping C-style callbacks
=20
The second related use case is for wrapping C-style callback function=20
syntax in the native C++ syntax. So if we are using a C library in C++, we=
=20
should be able to have a wrapper to which we can pass=20
RegisterCallback(&object.memfunc), and have it internally prepare a=20
non-member function pointer and void* pointer which contain all of the=20
necessary information to have a member function called by the callback=20
function. In my proposal, this is possible and fairly efficient via the=20
indirect use of stub functions.
=20
Just a special note of consideration for this use case is that we cannot=20
rely on the C library always passing the void* userdata argument as the=20
first argument in a function or in a way that is compatible with the=20
thiscall calling convention.
=20
Problems with Current C++:
The current C++ spec has a number of problems, the most severe of which is=
=20
the implementation of member function pointers. (Note I'm basing this on=20
the MSVC implementation, but I believe these problems are common to GCC,=20
etc.)=20
=20
Problem 1:
There are 3 different and completely incompatible types of member function=
=20
pointers based on the class of which the function is a member. If the class=
=20
is purely singly inherited, the member pointer is implemented as a single=
=20
pointer to the function code, which is something that is relatively easy to=
=20
work with. However, if the class contains multiple inheritance or virtual=
=20
inheritance in the hierarchy, then the member pointer additionally has=20
information relating to adjusting the offset of the object pointer, and=20
these three different structures are incompatible. In the case of callback=
=20
functions, however, the object and function pointer are always supplied=20
together. There should be no need to have different size structures when=20
the object is known in advance.
=20
Problem 2:
The second problem is that the current system is error prone. Take the=20
following example for the case of trying to implement a member function=20
callback system:
=20
template<class Obj_t, class MemObj_t>
void RegisterCallback(Obj_t* obj, void (MemObj_t::mem_fun*)(params=E2=80=A6=
))
=20
class Base1 {
};
class Derived1 : Base1 {
virtual void DoStuff();
};
=20
class Base2 {
virtual void DoStuff();
};
class Derived2 : Base2 {
virtual void DoStuff();
};
=20
Base1 b1;
RegisterCallback(&b1, &Derived1::DoStuff);
=20
Base2 b2;
RegisterCallback(&b2, &Derived2::DoStuff);
=20
The first example is broken, but we do not get any compile-time errors.
The second example is fine, and is the reason we need to allow different=20
classes in the object and member function definitions.
=20
Problem 3:
The third problem is related to passing virtual functions to C-style=20
callback systems. It is basically impossible to do without implementing=20
stub objects that store additional information.
=20
Notation:
I first want to introduce special notation I want to use to describe the=20
proposal.
THISCALL(func*, object*, params=E2=80=A6)
This is pseudo-code to represent the compilation code that actually makes a=
=20
function call given a pointer to the actual function code, and the pointer=
=20
to the this object. Note that the object* pointer here is required to be=20
already offset-adjusted to point to the correct location within the=20
inheritance hierarchy. It is expected to be a void* at runtime.
=20
func* VTABLOOKUP(object*, index)
This is pseudo-code for taking an object (as before, already=20
offset-adjusted to point to the correct vtable for the function being=20
called) and the index within that table, and returning a pointer to the=20
function that will actually run. The function returned from the vtable will=
=20
take an object* as the this pointer without adjustment because of the way=
=20
vtables are constructed.
=20
Returned structure:
Because of the differences between virtual member functions and non-virtual=
=20
member functions, the structures returned by (&obj.fun) will need to be=20
slightly different but only in terms of type information. The actual data=
=20
stored in the structures will be identically usable.
=20
For virtual functions, &obj.fun returns:
=20
template<int virtindex, class object_t, class RetType(Params=E2=80=A6)>
struct VirtualMemFunc {
object_t* callobject;
func* functionentrypoint;
=20
// For "native C++" callback
RetType operator(Params=E2=80=A6) {
return THISCALL(functionentrypoint, callobject,=
=20
Params=E2=80=A6);
}
=20
// For "C-style" callback
typedef RetType(Param0Callback*)(void* object, Params=E2=80=
=A6);
typedef RetType(Param1Callback*)(Param0_t Param0, void*=20
object, Params=E2=80=A6);
=20
Param0Callback* GetCCallbackStub0() {
return &VirtualMemFuncCStub<virtindex,=20
RetType(Params=E2=80=A6)>::Stub0;
}
Param1Callback* GetCCallbackStub1() {
return &VirtualMemFuncCStub<virtindex,=20
RetType(Params=E2=80=A6)>::Stub1;
}
void* GetCCallbackUserData() {
return (void*) callobject;
}
};
=20
template<int virtindex, class RetType(Params=E2=80=A6)>
struct VirtualMemFuncCStub {
static RetType Stub0(void* UserData, Params=E2=80=A6) {
return THISCALL(VTABLOOKUP(UserData,=20
virtindex), UserData, Params=E2=80=A6);
}
static RetType Stub1(Param0_t Param0, void* UserData,=20
Params=E2=80=A6) {
return THISCALL(VTABLOOKUP(UserData,=20
virtindex), UserData, Param0, Params=E2=80=A6);
}
}
=20
For non-virtual member functions, &obj.fun returns:
template<uint64_t funcaddr, class object_t, class RetType(Params=E2=80=A6)>
struct NonVirtualMemFunc {
object_t* callobject;
func* functionentrypoint;
=20
// For "native C++" callback
RetType operator(Params=E2=80=A6) {
return THISCALL(functionentrypoint, callobject,=
=20
Params=E2=80=A6);
}
=20
// For "C-style" callback
typedef RetType(Param0Callback*)(void* object, Params=E2=80=
=A6);
typedef RetType(Param1Callback*)(Param0_t Param0, void*=20
object, Params=E2=80=A6);
=20
Param0Callback* GetCCallbackStub0() {
return &NonVirtualMemFuncCStub<funcaddr,=20
RetType(Params=E2=80=A6)>::Stub0;
}
Param1Callback* GetCCallbackStub1() {
return &NonVirtualMemFuncCStub<funcaddr,=20
RetType(Params=E2=80=A6)>::Stub1;
}
void* GetCCallbackUserData() {
return (void*) callobject;
}
};
=20
template<uint64_t funcaddr, class RetType(Params=E2=80=A6)>
struct NonVirtualMemFuncCStub {
static RetType Stub0(void* UserData, Params=E2=80=A6) {
return THISCALL(funcaddr, UserData, Params=E2=
=80=A6);
}
static RetType Stub1(Param0_t Param0, void* UserData,=20
Params=E2=80=A6) {
return THISCALL(funcaddr, UserData, Param0,=20
Params=E2=80=A6);
}
}
=20
Notes on Abstraction/Reification:
The basic idea is that any offset-adjustment is performed at the time that=
=20
(&obj.fun) is called. That is, for the following:
=20
class Base1 {
int dat;
}
class Base2 {
virtual DoStuff() {};
}
class Derived : Base1, Base2 {
};
Derived d;
auto PtrToMemFun =3D (&d.DoStuff);
=20
In this case, at compile time the compiler sees that DoStuff is defined in=
=20
Base2. Thus, the structure returned is:
VirtualMemFunc<0, Base2, RetType(Params=E2=80=A6)>
That is, the object stored in the structure points to Base2, not to=20
Derived. There is no further need for pointer adjustment, and so the type=
=20
information is no longer needed in terms of actually calling the function.=
=20
The same is true of non-virtual member functions. That is, we can use a=20
common base class:
=20
template<class RetType(Params=E2=80=A6)>
struct CommonMemFunc {
void* callobject;
void* functionentrypoint;
=20
RetType operator(Params=E2=80=A6) {
return THISCALL(functionentrypoint, callobject,=
=20
Params=E2=80=A6);
}
}
=20
For C-style callbacks, we have a similar situation. We can extract the=20
function call and void* UserData pointers to get a common set of data.
=20
Usage:
For "native C++" callbacks, it would be sufficient to define:
=20
void RegisterCallback(CommonMemFunc<RetType(Params=E2=80=A6)> callbackfunc)=
{
}
=20
The structure is purely a set of 2 pointers that do not need type=20
information.
=20
For C-style callback wrappers things are slightly more complicated since we=
=20
need to have access the reified structures to get the correct stub function=
:
=20
template<int virtindex, class object_t>
void RegisterCallback(VirtualMemFunc<virtindex, object_t, RetType(Params=E2=
=80=A6)>=20
callbackfunc) {
CCodeRegisterCallback(callbackfunc.GetCCallbackStub0(),=20
callbackfunc.GetCCallbackUserData());
}
=20
template<uint64_t funcaddr, class object_t>
void RegisterCallback(NonVirtualMemFunc<funcaddr, object_t,=20
RetType(Params=E2=80=A6)> callbackfunc) {
CCodeRegisterCallback(callbackfunc.GetCCallbackStub0(),=20
callbackfunc.GetCCallbackUserData());
}
=20
=20
OK, this has gotten quite long. I hope this gives an idea of what I was=20
looking for. Suggestions/questions welcome.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_7125_1745998436.1446009463673
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><!--[if gte mso 9]><xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
</o:OfficeDocumentSettings>
</xml><![endif]-->
<p class=3D"MsoNormal"><span lang=3D"EN-US">Proposal for address of bound f=
unction:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">I want to give a more concrete =
proposal for
how I think the address of bound function operation would work. These ideas=
are
based on two very specific use cases, so I will state those up-front becaus=
e it
appears from reading people's comments that there are other use cases w=
hich I
haven't given much consideration to. Note also, I will use the syntax
(&object.fun) as example syntax. Other syntax may be more appropriate. =
I've
just thrown this together for now, as I would like feedback before getting =
more
specific/detailed.</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">Use case 1: "Native C++&qu=
ot; callback
functions:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">C currently has a fairly standa=
rd callback
function system, which consists of the following type of registration funct=
ion:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">typedef RetType(Callback*)(void=
* UserData,
params=E2=80=A6)</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">void RegisterCallback(Callback*=
CallbackFunc,
void* UserData);</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">This works well for C where dat=
a/functions
are not linked. However, in many cases C++ programs want UserData to point =
to
an object, and callbackfunc to be a member function of that object. That is=
, we
want to be able to have:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">typedef RetType(*::MemCallback*=
)(params)</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">void RegisterCallback(MemCallba=
ck*
CallbackMemberFunction);</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">which could be called using the=
following
or similar syntax:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">RegisterCallback(&object.me=
mfunc)</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">I think that this could be desc=
ribed as the
"native C++" equivalent to C-style callback functions. Note that =
it
is possible for this to work without dynamic memory allocation and by utili=
zing
only the memory space of 2 pointers for storing the function call. However,=
it
is not possible with the current C++ spec.</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">Use case 2: Wrapping C-style ca=
llbacks</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">The second related use case is =
for wrapping
C-style callback function syntax in the native C++ syntax. So if we are usi=
ng a
C library in C++, we should be able to have a wrapper to which we can pass
RegisterCallback(&object.memfunc), and have it internally prepare a non=
-member
function pointer and void* pointer which contain all of the necessary
information to have a member function called by the callback function. In m=
y
proposal, this is possible and fairly efficient via the indirect use of stu=
b
functions.</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">Just a special note of consider=
ation for
this use case is that we cannot rely on the C library always passing the vo=
id*
userdata argument as the first argument in a function or in a way that is
compatible with the thiscall calling convention.</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">Problems with Current C++:</spa=
n></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">The current C++ spec has a numb=
er of
problems, the most severe of which is the implementation of member function
pointers. (Note I'm basing this on the MSVC implementation, but I belie=
ve these
problems are common to GCC, etc.) </span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">Problem 1:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">There are 3 different and compl=
etely
incompatible types of member function pointers based on the class of which =
the
function is a member. If the class is purely singly inherited, the member p=
ointer
is implemented as a single pointer to the function code, which is something
that is relatively easy to work with. However, if the class contains multip=
le inheritance
or virtual inheritance in the hierarchy, then the member pointer additional=
ly
has information relating to adjusting the offset of the object pointer, and
these three different structures are incompatible. In the case of callback
functions, however, the object and function pointer are always supplied
together. There should be no need to have different size structures when th=
e
object is known in advance.</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">Problem 2:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">The second problem is that the =
current
system is error prone. Take the following example for the case of trying to
implement a member function callback system:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">template<class Obj_t, class =
MemObj_t></span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">void RegisterCallback(Obj_t* ob=
j, void (MemObj_t::mem_fun*)(params=E2=80=A6))</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">class Base1 {<br>
};</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">class Derived1 : Base1 {</span>=
</p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-spacerun:yes=
">=C2=A0=C2=A0=C2=A0 </span>virtual
void DoStuff();</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">};</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">class Base2 {<br>
<span style=3D"mso-spacerun:yes">=C2=A0=C2=A0=C2=A0 </span>virtual void DoS=
tuff();</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">};</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">class Derived2 : Base2 {</span>=
</p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-spacerun:yes=
">=C2=A0=C2=A0=C2=A0 </span>virtual
void DoStuff();</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">};</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">Base1 b1;</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">RegisterCallback(&b1, &=
Derived1::DoStuff);</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">Base2 b2;</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">RegisterCallback(&b2, &=
Derived2::DoStuff);</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">The first example is broken, bu=
t we do not
get any compile-time errors.</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">The second example is fine, and=
is the
reason we need to allow different classes in the object and member function
definitions.</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">Problem 3:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">The third problem is related to=
passing
virtual functions to C-style callback systems. It is basically impossible t=
o do
without implementing stub objects that store additional information.</span>=
</p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">Notation:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">I first want to introduce speci=
al notation
I want to use to describe the proposal.</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">THISCALL(func*, object*, params=
=E2=80=A6)</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">This is pseudo-code to represen=
t the
compilation code that actually makes a function call given a pointer to the
actual function code, and the pointer to the this object. Note that the obj=
ect*
pointer here is required to be already offset-adjusted to point to the corr=
ect
location within the inheritance hierarchy. It is expected to be a void* at
runtime.</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">func* VTABLOOKUP(object*, index=
)</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">This is pseudo-code for taking =
an object
(as before, already offset-adjusted to point to the correct vtable for the
function being called) and the index within that table, and returning a poi=
nter
to the function that will actually run. The function returned from the vtab=
le will
take an object* as the this pointer without adjustment because of the way
vtables are constructed.</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">Returned structure:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">Because of the differences betw=
een virtual member
functions and non-virtual member functions, the structures returned by (&am=
p;obj.fun)
will need to be slightly different but only in terms of type information. T=
he
actual data stored in the structures will be identically usable.</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">For virtual functions, &obj=
..fun
returns:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">template<int virtindex, clas=
s object_t,
class RetType(Params=E2=80=A6)></span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">struct VirtualMemFunc {</span><=
/p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>object_t*
callobject;</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>func*
functionentrypoint;</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span></span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>//
For "native C++" callback</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>RetType
operator(Params=E2=80=A6) {</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:2"=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 </span>return
THISCALL(functionentrypoint, callobject, Params=E2=80=A6);</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>//
For "C-style" callback</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>typedef
RetType(Param0Callback*)(void* object, Params=E2=80=A6);</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>typedef
RetType(Param1Callback*)(Param0_t Param0, void* object, Params=E2=80=A6);</=
span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>Param0Callback*
GetCCallbackStub0() {</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:2"=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 </span>return
&VirtualMemFuncCStub<virtindex, RetType(Params=E2=80=A6)>::Stub0;=
</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>Param1Callback*
GetCCallbackStub1() {</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:2"=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 </span>return
&VirtualMemFuncCStub<virtindex, RetType(Params=E2=80=A6)>::Stub1;=
</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>void*
GetCCallbackUserData() {</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:2"=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 </span>return
(void*) callobject;</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">};</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">template<int virtindex, clas=
s
RetType(Params=E2=80=A6)></span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">struct VirtualMemFuncCStub {</s=
pan></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>static
RetType Stub0(void* UserData, Params=E2=80=A6) {</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:2"=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 </span>return
THISCALL(VTABLOOKUP(UserData, virtindex), UserData, Params=E2=80=A6);</span=
></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>static
RetType Stub1(Param0_t Param0, void* UserData, Params=E2=80=A6) {</span></p=
>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:2"=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 </span>return
THISCALL(VTABLOOKUP(UserData, virtindex), UserData, Param0, Params=E2=80=A6=
);</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">For non-virtual member function=
s, &obj.fun
returns:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">template<uint64_t funcaddr, =
class object_t,
class RetType(Params=E2=80=A6)></span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">struct NonVirtualMemFunc {</spa=
n></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>object_t*
callobject;</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>func*
functionentrypoint;</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span></span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>//
For "native C++" callback</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>RetType
operator(Params=E2=80=A6) {</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:2"=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 </span>return
THISCALL(functionentrypoint, callobject, Params=E2=80=A6);</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>//
For "C-style" callback</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>typedef
RetType(Param0Callback*)(void* object, Params=E2=80=A6);</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>typedef
RetType(Param1Callback*)(Param0_t Param0, void* object, Params=E2=80=A6);</=
span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>Param0Callback*
GetCCallbackStub0() {</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:2"=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 </span>return
&NonVirtualMemFuncCStub<funcaddr, RetType(Params=E2=80=A6)>::Stub=
0;</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>Param1Callback*
GetCCallbackStub1() {</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:2"=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 </span>return
&NonVirtualMemFuncCStub<funcaddr, RetType(Params=E2=80=A6)>::Stub=
1;</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>void*
GetCCallbackUserData() {</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:2"=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 </span>return
(void*) callobject;</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">};</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">template<uint64_t funcaddr, =
class
RetType(Params=E2=80=A6)></span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">struct NonVirtualMemFuncCStub {=
</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>static
RetType Stub0(void* UserData, Params=E2=80=A6) {</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:2"=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 </span>return
THISCALL(funcaddr, UserData, Params=E2=80=A6);</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>static
RetType Stub1(Param0_t Param0, void* UserData, Params=E2=80=A6) {</span></p=
>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:2"=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 </span>return
THISCALL(funcaddr, UserData, Param0, Params=E2=80=A6);</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">Notes on Abstraction/Reificatio=
n:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">The basic idea is that any
offset-adjustment is performed at the time that (&obj.fun) is called. T=
hat
is, for the following:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">class Base1 {</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-spacerun:yes=
">=C2=A0=C2=A0
</span>int dat;</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">class Base2 {</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-spacerun:yes=
">=C2=A0=C2=A0
</span>virtual DoStuff() {};</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">class Derived : Base1, Base2 {<=
/span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">};</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">Derived d;</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">auto PtrToMemFun =3D (&d.Do=
Stuff);</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">In this case, at compile time t=
he compiler
sees that DoStuff is defined in Base2. Thus, the structure returned is:</sp=
an></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">VirtualMemFunc<0, Base2, Ret=
Type(Params=E2=80=A6)></span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">That is, the object stored in t=
he structure
points to Base2, not to Derived. There is no further need for pointer
adjustment, and so the type information is no longer needed in terms of
actually calling the function. The same is true of non-virtual member
functions. That is, we can use a common base class:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">template<class RetType(Param=
s=E2=80=A6)></span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">struct CommonMemFunc {</span></=
p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>void*
callobject;</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>void*
functionentrypoint;</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span></span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>RetType
operator(Params=E2=80=A6) {</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:2"=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 </span>return
THISCALL(functionentrypoint, callobject, Params=E2=80=A6);</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">For C-style callbacks, we have =
a similar
situation. We can extract the function call and void* UserData pointers to =
get
a common set of data.</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">Usage:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">For "native C++" call=
backs, it
would be sufficient to define:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">void
RegisterCallback(CommonMemFunc<RetType(Params=E2=80=A6)> callbackfunc=
) {</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">The structure is purely a set o=
f 2 pointers
that do not need type information.</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">For C-style callback wrappers t=
hings are
slightly more complicated since we need to have access the reified structur=
es to
get the correct stub function:</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">template<int virtindex, clas=
s
object_t></span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">void RegisterCallback(VirtualMe=
mFunc<virtindex,
object_t, RetType(Params=E2=80=A6)> callbackfunc) {</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>CCodeRegisterCallback(callbackfunc.GetCCallbackStub0(),
callbackfunc.GetCCallbackUserData());</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">template<uint64_t funcaddr, =
class
object_t></span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">void RegisterCallback(NonVirtua=
lMemFunc<funcaddr,
object_t, RetType(Params=E2=80=A6)> callbackfunc) {</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US"><span style=3D"mso-tab-count:1"=
>=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 </span>CCodeRegisterCallback(callbackfunc.GetCCallbackStub0(),
callbackfunc.GetCCallbackUserData());</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">}</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<p class=3D"MsoNormal"><span lang=3D"EN-US">=C2=A0</span></p>
<span style=3D"font-size:10.5pt;mso-bidi-font-size:14.0pt;font-family:
"Century","serif";mso-ascii-theme-font:minor-latin;mso-=
fareast-font-family:
"=EF=BC=AD=EF=BC=B3 =E6=98=8E=E6=9C=9D";mso-fareast-theme-font:mi=
nor-fareast;mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Cordia New";mso-bidi-theme-font:minor-bidi;=
mso-ansi-language:
EN-US;mso-fareast-language:JA;mso-bidi-language:TH" lang=3D"EN-US">OK, this=
has gotten quite
long. I hope this gives an idea of what I was looking for. Suggestions/ques=
tions
welcome.</span><!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEve=
ry>
<w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>EN-US</w:LidThemeOther>
<w:LidThemeAsian>JA</w:LidThemeAsian>
<w:LidThemeComplexScript>TH</w:LidThemeComplexScript>
<w:Compatibility>
<w:SpaceForUL/>
<w:BalanceSingleByteDoubleByteWidth/>
<w:DoNotLeaveBackslashAlone/>
<w:ULTrailSpace/>
<w:DoNotExpandShiftReturn/>
<w:AdjustLineHeightInTable/>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:ApplyBreakingRules/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:EnableOpenTypeKerning/>
<w:DontFlipMirrorIndents/>
<w:OverrideTableStyleHps/>
<w:UseFELayout/>
</w:Compatibility>
<m:mathPr>
<m:mathFont m:val=3D"Cambria Math"/>
<m:brkBin m:val=3D"before"/>
<m:brkBinSub m:val=3D"--"/>
<m:smallFrac m:val=3D"off"/>
<m:dispDef/>
<m:lMargin m:val=3D"0"/>
<m:rMargin m:val=3D"0"/>
<m:defJc m:val=3D"centerGroup"/>
<m:wrapIndent m:val=3D"1440"/>
<m:intLim m:val=3D"subSup"/>
<m:naryLim m:val=3D"undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState=3D"false" DefUnhideWhenUsed=3D"true"
DefSemiHidden=3D"true" DefQFormat=3D"false" DefPriority=3D"99"
LatentStyleCount=3D"267">
<w:LsdException Locked=3D"false" Priority=3D"0" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Normal"/>
<w:LsdException Locked=3D"false" Priority=3D"9" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"heading 1"/>
<w:LsdException Locked=3D"false" Priority=3D"9" QFormat=3D"true" Name=3D"=
heading 2"/>
<w:LsdException Locked=3D"false" Priority=3D"9" QFormat=3D"true" Name=3D"=
heading 3"/>
<w:LsdException Locked=3D"false" Priority=3D"9" QFormat=3D"true" Name=3D"=
heading 4"/>
<w:LsdException Locked=3D"false" Priority=3D"9" QFormat=3D"true" Name=3D"=
heading 5"/>
<w:LsdException Locked=3D"false" Priority=3D"9" QFormat=3D"true" Name=3D"=
heading 6"/>
<w:LsdException Locked=3D"false" Priority=3D"9" QFormat=3D"true" Name=3D"=
heading 7"/>
<w:LsdException Locked=3D"false" Priority=3D"9" QFormat=3D"true" Name=3D"=
heading 8"/>
<w:LsdException Locked=3D"false" Priority=3D"9" QFormat=3D"true" Name=3D"=
heading 9"/>
<w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 1"/>
<w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 2"/>
<w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 3"/>
<w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 4"/>
<w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 5"/>
<w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 6"/>
<w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 7"/>
<w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 8"/>
<w:LsdException Locked=3D"false" Priority=3D"39" Name=3D"toc 9"/>
<w:LsdException Locked=3D"false" Priority=3D"35" QFormat=3D"true" Name=3D=
"caption"/>
<w:LsdException Locked=3D"false" Priority=3D"10" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Title"/>
<w:LsdException Locked=3D"false" Priority=3D"1" Name=3D"Default Paragraph=
Font"/>
<w:LsdException Locked=3D"false" Priority=3D"11" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Subtitle"/>
<w:LsdException Locked=3D"false" Priority=3D"22" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Strong"/>
<w:LsdException Locked=3D"false" Priority=3D"20" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Emphasis"/>
<w:LsdException Locked=3D"false" Priority=3D"59" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Table Grid"/>
<w:LsdException Locked=3D"false" UnhideWhenUsed=3D"false" Name=3D"Placeho=
lder Text"/>
<w:LsdException Locked=3D"false" Priority=3D"1" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"No Spacing"/>
<w:LsdException Locked=3D"false" Priority=3D"60" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light Shading"/>
<w:LsdException Locked=3D"false" Priority=3D"61" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light List"/>
<w:LsdException Locked=3D"false" Priority=3D"62" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light Grid"/>
<w:LsdException Locked=3D"false" Priority=3D"63" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Shading 1"/>
<w:LsdException Locked=3D"false" Priority=3D"64" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Shading 2"/>
<w:LsdException Locked=3D"false" Priority=3D"65" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium List 1"/>
<w:LsdException Locked=3D"false" Priority=3D"66" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium List 2"/>
<w:LsdException Locked=3D"false" Priority=3D"67" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 1"/>
<w:LsdException Locked=3D"false" Priority=3D"68" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 2"/>
<w:LsdException Locked=3D"false" Priority=3D"69" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 3"/>
<w:LsdException Locked=3D"false" Priority=3D"70" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Dark List"/>
<w:LsdException Locked=3D"false" Priority=3D"71" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful Shading"/>
<w:LsdException Locked=3D"false" Priority=3D"72" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful List"/>
<w:LsdException Locked=3D"false" Priority=3D"73" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful Grid"/>
<w:LsdException Locked=3D"false" Priority=3D"60" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light Shading Accent 1"/>
<w:LsdException Locked=3D"false" Priority=3D"61" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light List Accent 1"/>
<w:LsdException Locked=3D"false" Priority=3D"62" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light Grid Accent 1"/>
<w:LsdException Locked=3D"false" Priority=3D"63" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Shading 1 Accent 1"/>
<w:LsdException Locked=3D"false" Priority=3D"64" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Shading 2 Accent 1"/>
<w:LsdException Locked=3D"false" Priority=3D"65" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium List 1 Accent 1"/>
<w:LsdException Locked=3D"false" UnhideWhenUsed=3D"false" Name=3D"Revisio=
n"/>
<w:LsdException Locked=3D"false" Priority=3D"34" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"List Paragraph"/>
<w:LsdException Locked=3D"false" Priority=3D"29" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Quote"/>
<w:LsdException Locked=3D"false" Priority=3D"30" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Intense Quote"/>
<w:LsdException Locked=3D"false" Priority=3D"66" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium List 2 Accent 1"/>
<w:LsdException Locked=3D"false" Priority=3D"67" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 1 Accent 1"/>
<w:LsdException Locked=3D"false" Priority=3D"68" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 2 Accent 1"/>
<w:LsdException Locked=3D"false" Priority=3D"69" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 3 Accent 1"/>
<w:LsdException Locked=3D"false" Priority=3D"70" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Dark List Accent 1"/>
<w:LsdException Locked=3D"false" Priority=3D"71" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful Shading Accent 1"/>
<w:LsdException Locked=3D"false" Priority=3D"72" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful List Accent 1"/>
<w:LsdException Locked=3D"false" Priority=3D"73" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful Grid Accent 1"/>
<w:LsdException Locked=3D"false" Priority=3D"60" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light Shading Accent 2"/>
<w:LsdException Locked=3D"false" Priority=3D"61" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light List Accent 2"/>
<w:LsdException Locked=3D"false" Priority=3D"62" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light Grid Accent 2"/>
<w:LsdException Locked=3D"false" Priority=3D"63" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Shading 1 Accent 2"/>
<w:LsdException Locked=3D"false" Priority=3D"64" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Shading 2 Accent 2"/>
<w:LsdException Locked=3D"false" Priority=3D"65" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium List 1 Accent 2"/>
<w:LsdException Locked=3D"false" Priority=3D"66" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium List 2 Accent 2"/>
<w:LsdException Locked=3D"false" Priority=3D"67" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 1 Accent 2"/>
<w:LsdException Locked=3D"false" Priority=3D"68" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 2 Accent 2"/>
<w:LsdException Locked=3D"false" Priority=3D"69" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 3 Accent 2"/>
<w:LsdException Locked=3D"false" Priority=3D"70" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Dark List Accent 2"/>
<w:LsdException Locked=3D"false" Priority=3D"71" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful Shading Accent 2"/>
<w:LsdException Locked=3D"false" Priority=3D"72" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful List Accent 2"/>
<w:LsdException Locked=3D"false" Priority=3D"73" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful Grid Accent 2"/>
<w:LsdException Locked=3D"false" Priority=3D"60" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light Shading Accent 3"/>
<w:LsdException Locked=3D"false" Priority=3D"61" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light List Accent 3"/>
<w:LsdException Locked=3D"false" Priority=3D"62" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light Grid Accent 3"/>
<w:LsdException Locked=3D"false" Priority=3D"63" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Shading 1 Accent 3"/>
<w:LsdException Locked=3D"false" Priority=3D"64" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Shading 2 Accent 3"/>
<w:LsdException Locked=3D"false" Priority=3D"65" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium List 1 Accent 3"/>
<w:LsdException Locked=3D"false" Priority=3D"66" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium List 2 Accent 3"/>
<w:LsdException Locked=3D"false" Priority=3D"67" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 1 Accent 3"/>
<w:LsdException Locked=3D"false" Priority=3D"68" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 2 Accent 3"/>
<w:LsdException Locked=3D"false" Priority=3D"69" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 3 Accent 3"/>
<w:LsdException Locked=3D"false" Priority=3D"70" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Dark List Accent 3"/>
<w:LsdException Locked=3D"false" Priority=3D"71" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful Shading Accent 3"/>
<w:LsdException Locked=3D"false" Priority=3D"72" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful List Accent 3"/>
<w:LsdException Locked=3D"false" Priority=3D"73" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful Grid Accent 3"/>
<w:LsdException Locked=3D"false" Priority=3D"60" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light Shading Accent 4"/>
<w:LsdException Locked=3D"false" Priority=3D"61" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light List Accent 4"/>
<w:LsdException Locked=3D"false" Priority=3D"62" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light Grid Accent 4"/>
<w:LsdException Locked=3D"false" Priority=3D"63" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Shading 1 Accent 4"/>
<w:LsdException Locked=3D"false" Priority=3D"64" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Shading 2 Accent 4"/>
<w:LsdException Locked=3D"false" Priority=3D"65" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium List 1 Accent 4"/>
<w:LsdException Locked=3D"false" Priority=3D"66" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium List 2 Accent 4"/>
<w:LsdException Locked=3D"false" Priority=3D"67" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 1 Accent 4"/>
<w:LsdException Locked=3D"false" Priority=3D"68" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 2 Accent 4"/>
<w:LsdException Locked=3D"false" Priority=3D"69" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 3 Accent 4"/>
<w:LsdException Locked=3D"false" Priority=3D"70" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Dark List Accent 4"/>
<w:LsdException Locked=3D"false" Priority=3D"71" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful Shading Accent 4"/>
<w:LsdException Locked=3D"false" Priority=3D"72" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful List Accent 4"/>
<w:LsdException Locked=3D"false" Priority=3D"73" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful Grid Accent 4"/>
<w:LsdException Locked=3D"false" Priority=3D"60" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light Shading Accent 5"/>
<w:LsdException Locked=3D"false" Priority=3D"61" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light List Accent 5"/>
<w:LsdException Locked=3D"false" Priority=3D"62" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light Grid Accent 5"/>
<w:LsdException Locked=3D"false" Priority=3D"63" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Shading 1 Accent 5"/>
<w:LsdException Locked=3D"false" Priority=3D"64" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Shading 2 Accent 5"/>
<w:LsdException Locked=3D"false" Priority=3D"65" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium List 1 Accent 5"/>
<w:LsdException Locked=3D"false" Priority=3D"66" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium List 2 Accent 5"/>
<w:LsdException Locked=3D"false" Priority=3D"67" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 1 Accent 5"/>
<w:LsdException Locked=3D"false" Priority=3D"68" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 2 Accent 5"/>
<w:LsdException Locked=3D"false" Priority=3D"69" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 3 Accent 5"/>
<w:LsdException Locked=3D"false" Priority=3D"70" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Dark List Accent 5"/>
<w:LsdException Locked=3D"false" Priority=3D"71" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful Shading Accent 5"/>
<w:LsdException Locked=3D"false" Priority=3D"72" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful List Accent 5"/>
<w:LsdException Locked=3D"false" Priority=3D"73" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful Grid Accent 5"/>
<w:LsdException Locked=3D"false" Priority=3D"60" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light Shading Accent 6"/>
<w:LsdException Locked=3D"false" Priority=3D"61" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light List Accent 6"/>
<w:LsdException Locked=3D"false" Priority=3D"62" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Light Grid Accent 6"/>
<w:LsdException Locked=3D"false" Priority=3D"63" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Shading 1 Accent 6"/>
<w:LsdException Locked=3D"false" Priority=3D"64" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Shading 2 Accent 6"/>
<w:LsdException Locked=3D"false" Priority=3D"65" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium List 1 Accent 6"/>
<w:LsdException Locked=3D"false" Priority=3D"66" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium List 2 Accent 6"/>
<w:LsdException Locked=3D"false" Priority=3D"67" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 1 Accent 6"/>
<w:LsdException Locked=3D"false" Priority=3D"68" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 2 Accent 6"/>
<w:LsdException Locked=3D"false" Priority=3D"69" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Medium Grid 3 Accent 6"/>
<w:LsdException Locked=3D"false" Priority=3D"70" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Dark List Accent 6"/>
<w:LsdException Locked=3D"false" Priority=3D"71" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful Shading Accent 6"/>
<w:LsdException Locked=3D"false" Priority=3D"72" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful List Accent 6"/>
<w:LsdException Locked=3D"false" Priority=3D"73" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" Name=3D"Colorful Grid Accent 6"/>
<w:LsdException Locked=3D"false" Priority=3D"19" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Subtle Emphasis"/>
<w:LsdException Locked=3D"false" Priority=3D"21" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Intense Emphasis"/>
<w:LsdException Locked=3D"false" Priority=3D"31" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Subtle Reference"/>
<w:LsdException Locked=3D"false" Priority=3D"32" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Intense Reference"/>
<w:LsdException Locked=3D"false" Priority=3D"33" SemiHidden=3D"false"
UnhideWhenUsed=3D"false" QFormat=3D"true" Name=3D"Book Title"/>
<w:LsdException Locked=3D"false" Priority=3D"37" Name=3D"Bibliography"/>
<w:LsdException Locked=3D"false" Priority=3D"39" QFormat=3D"true" Name=3D=
"TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:"";
mso-padding-alt:0mm 5.4pt 0mm 5.4pt;
mso-para-margin:0mm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.5pt;
mso-bidi-font-size:14.0pt;
font-family:"Century","serif";
mso-ascii-font-family:Century;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Century;
mso-hansi-theme-font:minor-latin;
mso-font-kerning:1.0pt;}
</style>
<![endif]--></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_7125_1745998436.1446009463673--
------=_Part_7124_719329200.1446009463672--
.
Author: Viacheslav Usov <via.usov@gmail.com>
Date: Wed, 28 Oct 2015 02:35:54 -0700 (PDT)
Raw View
------=_Part_1015_849744561.1446024954107
Content-Type: multipart/alternative;
boundary="----=_Part_1016_861660396.1446024954108"
------=_Part_1016_861660396.1446024954108
Content-Type: text/plain; charset=UTF-8
On Tuesday, October 27, 2015 at 7:02:31 PM UTC+1, Viacheslav Usov wrote:
> I think this could be generalized further by introducing a placeholder
syntax. Something like the following: * forwards one argument, and ...
forwards any number, and it would not need to be at the end of the argument
list.
[...]
> nothing speaks against allowing lambda-declarator_opt of
[expr.prim.lambda] in such lambdas, but that will re-introduce boilerplate.
The problem with lambda-declarator_opt is that every variable mentioned
there needs a type specifier, at least an auto. A variable that needs
perfect forwarding has to be further decorated with &&, and further used
with std::forward(). All of that bloats lambda definitions; I have also
observed that this has a psychological effect on less experienced
programmers who would perceive that as something esoteric and so to be
avoided.
So the question is, can we make the type specifier fully optional in
lambda-declarator_opt? For example, auto x = [a](b)(a + b) would mean we
create a lambda that captures a, and has one argument denoted by b; the
body of the lambda is the expression (a + b). Another example: auto x =
[a](b)f(a, b); in this case, b is forwarded perfectly to f (so this is an
example of partial application).
The semantics of an untyped variable in lambda-declarator_opt needs to be
defined, and I suspect that could be tricky. Fundamentally, such a
declaration means that the compiler should just do the Right Thing with
that variable, which includes forwarding it perfectly where needed and
possible. We obviously need well-defined behaviour, even if it cannot
satisfy every conceivable need; it is even possible that the definition of
the Right Thing needs to impose certain restrictions on the expression, the
types that the lambda can be called with, or both. Which I think is fine,
because in the more complicated cases the user can use the current
fully-typed syntax; all we really need is a way to write simple lambda
expressions in a simple way.
Another nice thing to have would be the ability to omit the type and name
of variadic variables, e.g.: auto x = [a](...)a.f(...); this is the example
of how the goal in the original post in this thread, and also in the
referenced threads, can be achieved. This is not restricted to member
functions, though, because one could equally say auto x = [a](...)f(a, ...).
With the above, I do not think we need the placeholders mentioned in my
previous message.
Comments?
Cheers,
V.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1016_861660396.1446024954108
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, October 27, 2015 at 7:02:31 PM UTC+1, Viachesl=
av Usov wrote:<div><br></div><div>> I think this could be generalized fu=
rther by introducing a placeholder syntax. Something like the following: * =
forwards one argument, and ... forwards any number, and it would not need t=
o be at the end of the argument list.</div><div><br></div><div>[...]</div><=
div><br></div><div>> nothing speaks against allowing lambda-declarator_o=
pt of [expr.prim.lambda] in such lambdas, but that will re-introduce boiler=
plate.</div><div><br></div><div>The problem with lambda-declarator_opt is t=
hat every variable mentioned there needs a type specifier, at least an auto=
.. A variable that needs perfect forwarding has to be further decorated with=
&&, and further used with std::forward(). All of that bloats lambd=
a definitions; I have also observed that this has a psychological effect on=
less experienced programmers who would perceive that as something esoteric=
and so to be avoided.</div><div><br></div><div>So the question is, can we =
make the type specifier fully optional in lambda-declarator_opt? For exampl=
e, auto x =3D [a](b)(a + b) would mean we create a lambda that captures a, =
and has one argument denoted by b; the body of the lambda is the expression=
(a + b). Another example: auto x =3D [a](b)f(a, b); in this case, b is for=
warded perfectly to f (so this is an example of partial application).</div>=
<div><br></div><div>The semantics of an untyped variable in lambda-declarat=
or_opt needs to be defined, and I suspect that could be tricky. Fundamental=
ly, such a declaration means that the compiler should just do the Right Thi=
ng with that variable, which includes forwarding it perfectly where needed =
and possible. We obviously need well-defined behaviour, even if it cannot s=
atisfy every conceivable need; it is even possible that the definition of t=
he Right Thing needs to impose certain restrictions on the expression, the =
types that the lambda can be called with, or both. Which I think is fine, b=
ecause in the more complicated cases the user can use the current fully-typ=
ed syntax; all we really need is a way to write simple lambda expressions i=
n a simple way.</div><div><br></div><div>Another nice thing to have would b=
e the ability to omit the type and name of variadic variables, e.g.: auto x=
=3D [a](...)a.f(...); this is the example of how the goal in the original =
post in this thread, and also in the referenced threads, can be achieved. T=
his is not restricted to member functions, though, because one could equall=
y say auto x =3D [a](...)f(a, ...).</div><div><br></div><div>With the above=
, I do not think we need the placeholders mentioned in my previous message.=
</div><div><br></div><div>Comments?</div><div><br></div><div>Cheers,</div><=
div>V.</div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1016_861660396.1446024954108--
------=_Part_1015_849744561.1446024954107--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 28 Oct 2015 06:18:41 -0700 (PDT)
Raw View
------=_Part_7679_1504211439.1446038321486
Content-Type: multipart/alternative;
boundary="----=_Part_7680_54703692.1446038321486"
------=_Part_7680_54703692.1446038321486
Content-Type: text/plain; charset=UTF-8
On Wednesday, October 28, 2015 at 12:10:48 AM UTC-4, Sean Middleditch wrote:
>
> On Tuesday, October 27, 2015 at 8:18:15 AM UTC-7, Nicol Bolas wrote:
>>
>> We already want overload syntax, for member functions *and* non-member
>> functions. The obvious implementation is a lambda, so simply allow lambdas
>> to do it cleanly, without the boilerplate:
>>
>> []Class::Funcname; //Functor that calls the named member function, which
>> takes as a first parameter a Class reference/pointer/object.
>> [d]d.Funcname; //Functor that calls the named member function, using
>> a variable bound by lambda rules.
>> []d.Funcname; //A compile error. You must explicitly bind the
>> variable.
>> []Funcname; //Functor calling a non-member function.
>> [this]Funcname; //Functor possibly calling a member function or
>> non-member function, depending on the type of `this`.
>>
>>
> That looks a lot like an extended variation on
> https://isocpp.org/files/papers/n3617.txt for what it's worth.
>
> It's an active EWG issue (
> http://cplusplus.github.io/EWG/ewg-active.html#65) and so far as I can
> tell has never been thoroughly reviewed or voted on.
>
> Someone with an interest should write a followup paper and take it to
> Jacksonville. :)
>
I thought I'd seen something like that before.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_7680_54703692.1446038321486
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, October 28, 2015 at 12:10:48 AM UTC-4, Sean Middleditch wrote=
:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;">On Tuesday, October 27, 2015 =
at 8:18:15 AM UTC-7, Nicol Bolas wrote:<blockquote class=3D"gmail_quote" st=
yle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1=
ex"><div>We already want overload syntax, for member functions <i>and</i> n=
on-member functions. The obvious implementation is a lambda, so simply allo=
w lambdas to do it cleanly, without the boilerplate:<br><br><div style=3D"b=
ackground-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"col=
or:#660">[]</span><span style=3D"color:#606">Class</span><span style=3D"col=
or:#660">::</span><span style=3D"color:#606">Funcname</span><span style=3D"=
color:#660">;</span><span style=3D"color:#000"> </span><span style=3D"color=
:#800">//Functor that calls the named member function, which takes as a fir=
st parameter a Class reference/pointer/object.</span><span style=3D"color:#=
000"><br></span><span style=3D"color:#660">[</span><span style=3D"color:#00=
0">d</span><span style=3D"color:#660">]</span><span style=3D"color:#000">d<=
/span><span style=3D"color:#660">.</span><span style=3D"color:#606">Funcnam=
e</span><span style=3D"color:#660">;</span><span style=3D"color:#000"> =C2=
=A0 =C2=A0 </span><span style=3D"color:#800">//Functor that calls the named=
member function, using a variable bound by lambda rules.</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">[]</span><span style=
=3D"color:#000">d</span><span style=3D"color:#660">.</span><span style=3D"c=
olor:#606">Funcname</span><span style=3D"color:#660">;</span><span style=3D=
"color:#000"> =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#800">//A com=
pile error. You must explicitly bind the variable.</span><span style=3D"col=
or:#000"><br></span><span style=3D"color:#660">[]</span><span style=3D"colo=
r:#606">Funcname</span><span style=3D"color:#660">;</span><span style=3D"co=
lor:#000"> =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#800">//F=
unctor calling a non-member function.</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#660">[</span><span style=3D"color:#008">this</=
span><span style=3D"color:#660">]</span><span style=3D"color:#606">Funcname=
</span><span style=3D"color:#660">;</span><span style=3D"color:#000"> =C2=
=A0 =C2=A0</span><span style=3D"color:#800">//Functor possibly calling a me=
mber function or non-member function, depending on the type of `this`.</spa=
n></div></code></div></div><br></blockquote><div><br></div><div>That looks =
a lot like an extended variation on <a href=3D"https://isocpp.org/files/pap=
ers/n3617.txt" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'https://www.google.com/url?q\75https%3A%2F%2Fisocpp.org%2Ffiles%2Fp=
apers%2Fn3617.txt\46sa\75D\46sntz\0751\46usg\75AFQjCNELc3pp-UnqFW59g8uNMNAh=
ZfesBw';return true;" onclick=3D"this.href=3D'https://www.google.co=
m/url?q\75https%3A%2F%2Fisocpp.org%2Ffiles%2Fpapers%2Fn3617.txt\46sa\75D\46=
sntz\0751\46usg\75AFQjCNELc3pp-UnqFW59g8uNMNAhZfesBw';return true;">htt=
ps://isocpp.org/files/<wbr>papers/n3617.txt</a> for what it's worth.</d=
iv><div><br></div><div>It's an active EWG issue (<a href=3D"http://cplu=
splus.github.io/EWG/ewg-active.html#65" target=3D"_blank" rel=3D"nofollow" =
onmousedown=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2F=
cplusplus.github.io%2FEWG%2Fewg-active.html%2365\46sa\75D\46sntz\0751\46usg=
\75AFQjCNHVl48-fA-eAcE-K_urUy-nrip98Q';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\75http%3A%2F%2Fcplusplus.github.io%2F=
EWG%2Fewg-active.html%2365\46sa\75D\46sntz\0751\46usg\75AFQjCNHVl48-fA-eAcE=
-K_urUy-nrip98Q';return true;">http://cplusplus.github.io/<wbr>EWG/ewg-=
active.html#65</a>) and so far as I can tell has never been thoroughly revi=
ewed or voted on.</div><div><br></div><div>Someone with an interest should =
write a followup paper and take it to Jacksonville. :)</div></blockquote><d=
iv><br>I thought I'd seen something like that before.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_7680_54703692.1446038321486--
------=_Part_7679_1504211439.1446038321486--
.
Author: maurice barnum <pixi@burble.org>
Date: Sat, 31 Oct 2015 10:55:23 -0700
Raw View
On 2015-10-27 8:45 , Brent Friedman wrote:
> I'm curious as to how, exactly. A virtual call involves getting the
> vtable, followed by fetching the function pointer through an offset.
>
>
> Right - the thought behind this is that &(obj->fun) would get the vtable
> for obj and fetch the function pointer. It effectively separates the
> virtual lookup step from the virtual call step. The result of the
> expression is the concrete member function (or overload resolution set)
> that *would* be called. We don't entirely know if it's feasible, sort of
> a brainstorm at the moment.
The idea is feasible has been implemented by at least two compilers,
Borland (now Embarcadero) and GCC, but with differing syntax, see
http://preview.tinyurl.com/qd9pmjn and
http://preview.tinyurl.com/mlbtxs3, respectively.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Matthew <matt.fagan@muonenterprises.com>
Date: Sun, 1 Nov 2015 21:41:37 -0800 (PST)
Raw View
------=_Part_379_1918302511.1446442897405
Content-Type: multipart/alternative;
boundary="----=_Part_380_1485324679.1446442897406"
------=_Part_380_1485324679.1446442897406
Content-Type: text/plain; charset=UTF-8
On Sunday, November 1, 2015 at 3:00:11 AM UTC+9, maurice barnum wrote:
>
> On 2015-10-27 8:45 , Brent Friedman wrote:
> > I'm curious as to how, exactly. A virtual call involves getting the
> > vtable, followed by fetching the function pointer through an offset.
> >
> >
> > Right - the thought behind this is that &(obj->fun) would get the vtable
> > for obj and fetch the function pointer. It effectively separates the
> > virtual lookup step from the virtual call step. The result of the
> > expression is the concrete member function (or overload resolution set)
> > that *would* be called. We don't entirely know if it's feasible, sort of
> > a brainstorm at the moment.
>
> The idea is feasible has been implemented by at least two compilers,
> Borland (now Embarcadero) and GCC, but with differing syntax, see
> http://preview.tinyurl.com/qd9pmjn and
> http://preview.tinyurl.com/mlbtxs3, respectively.
>
>
Is there another forum/thread/newsgroup where this discussion is ongoing,
because it's hard to follow just getting snippets of the discussion.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_380_1485324679.1446442897406
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Sunday, November 1, 2015 at 3:00:11 AM UTC+9, maurice barnum wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;">On 2015-10-27 8:45 , Brent Friedman=
wrote:
<br>> =C2=A0 =C2=A0 I'm curious as to how, exactly. A virtual call i=
nvolves getting the
<br>> =C2=A0 =C2=A0 vtable, followed by fetching the function pointer th=
rough an offset.
<br>>
<br>>
<br>> Right - the thought behind this is that &(obj->fun) would g=
et the vtable
<br>> for obj and fetch the function pointer. It effectively separates t=
he
<br>> virtual lookup step from the virtual call step. The result of the
<br>> expression is the concrete member function (or overload resolution=
set)
<br>> that *would* be called. We don't entirely know if it's fea=
sible, sort of
<br>> a brainstorm at the moment.
<br>
<br>The idea is feasible has been implemented by at least two compilers,
<br>Borland (now Embarcadero) and GCC, but with differing syntax, see
<br><a href=3D"http://preview.tinyurl.com/qd9pmjn" target=3D"_blank" rel=3D=
"nofollow" onmousedown=3D"this.href=3D'http://www.google.com/url?q\75ht=
tp%3A%2F%2Fpreview.tinyurl.com%2Fqd9pmjn\46sa\75D\46sntz\0751\46usg\75AFQjC=
NFZN689xal_x9mPGZjyuY6TlCp3Zw';return true;" onclick=3D"this.href=3D=
9;http://www.google.com/url?q\75http%3A%2F%2Fpreview.tinyurl.com%2Fqd9pmjn\=
46sa\75D\46sntz\0751\46usg\75AFQjCNFZN689xal_x9mPGZjyuY6TlCp3Zw';return=
true;">http://preview.tinyurl.com/<wbr>qd9pmjn</a> and=20
<br><a href=3D"http://preview.tinyurl.com/mlbtxs3" target=3D"_blank" rel=3D=
"nofollow" onmousedown=3D"this.href=3D'http://www.google.com/url?q\75ht=
tp%3A%2F%2Fpreview.tinyurl.com%2Fmlbtxs3\46sa\75D\46sntz\0751\46usg\75AFQjC=
NFx14JkyqbYy3TH7y7z0HQUprVRYw';return true;" onclick=3D"this.href=3D=
9;http://www.google.com/url?q\75http%3A%2F%2Fpreview.tinyurl.com%2Fmlbtxs3\=
46sa\75D\46sntz\0751\46usg\75AFQjCNFx14JkyqbYy3TH7y7z0HQUprVRYw';return=
true;">http://preview.tinyurl.com/<wbr>mlbtxs3</a>, respectively.
<br>
<br></blockquote><div><br>Is there another forum/thread/newsgroup where thi=
s discussion is ongoing, because it's hard to follow just getting snipp=
ets of the discussion. <br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_380_1485324679.1446442897406--
------=_Part_379_1918302511.1446442897405--
.