Topic: Implement operator->* for smart pointer types
Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Date: Fri, 23 Sep 2016 19:19:34 -0700 (PDT)
Raw View
------=_Part_4960_1580567115.1474683574475
Content-Type: multipart/alternative;
boundary="----=_Part_4961_1605188686.1474683574476"
------=_Part_4961_1605188686.1474683574476
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
While listening to Herb Sutter's keynote at the end of CppCon 2016, I=20
attempted to implement a generic "free a linked list of unique_ptrs without=
=20
blowing the stack" algorithm, i.e.
template<typename ClassType, typename SmartPtr>
void pop_until_empty(ClassType *self, SmartPtr T::*next)
{
while (self->*next) {
self->*next =3D (self->*next)->*next;
}
}
struct ListNode {
std::unique_ptr<ListNode> next;
~ListNode() {
pop_until_empty(this, &ListNode::next);
}
};
However, it turned out that the above did not compile... because=20
std::unique_ptr and std::shared_ptr currently lack any overload for=20
operator->*.
I found a paper by Scott Meyers from 1999, "Implementing operator->* for=20
smart pointers" <http://www.aristeia.com/Papers/DDJ_Oct_1999.pdf>, which=20
shows how difficult it was to implement this operator in C++03. (In fact, I=
=20
think the signature that got standardized for overloading operator->* might=
=20
have been suboptimal; but that ship has long since sailed.)
Anyway, I think that as of C++14 we have enough core language features that=
=20
we can make a good stab at implementing operator->* for smart pointers. Can=
=20
anyone poke any holes in the following pair of template definitions? I=20
would propose to add both of these overloaded operators to unique_ptr and=
=20
shared_ptr in C++2w, unless there's some fatal flaw I'm not seeing.
template<typename M>
decltype(auto) operator->* (M T::*mp) const {
return (*(*this)).*mp;
}
template<typename R, typename... Args>
auto operator->* (R (T::*mfp)(Args...)) const {
return [p =3D &**this, mfp =3D mfp](auto&&... args) {
return (p->*mfp)(std::forward<decltype(args)>(args)...);
};
}
Thanks,
=E2=80=93Arthur
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/e0ea00a6-98a7-47a2-b960-8f494fb02e2c%40isocpp.or=
g.
------=_Part_4961_1605188686.1474683574476
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>While listening to Herb Sutter's keynote at the e=
nd of CppCon 2016, I attempted to implement a generic "free a linked l=
ist of unique_ptrs without blowing the stack" algorithm, i.e.</div><di=
v><br></div><div class=3D"prettyprint" style=3D"background-color: rgb(250, =
250, 250); border: 1px solid rgb(187, 187, 187); word-wrap: break-word;"><c=
ode class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">template</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">typename</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"=
styled-by-prettify">ClassType</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>typename</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #606;" class=3D"styled-by-prettify">SmartPtr</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">></span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">void</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> pop_until_empty</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D=
"color: #606;" class=3D"styled-by-prettify">ClassType</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">*</span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">self</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify"=
>SmartPtr</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::*</span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">next</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color:=
#008;" class=3D"styled-by-prettify">while</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">self</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">->*</span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">next</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">self</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">->*</span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">next</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">self</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">->*</span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">next</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">)->*</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
next</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=
=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br><br><br></span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">ListNode</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br>=C2=A0 =C2=A0 std</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">unique_ptr</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify"><</span><span style=3D"color: #606;" class=3D"style=
d-by-prettify">ListNode</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">></span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">ne=
xt</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">~</span><=
span style=3D"color: #606;" class=3D"styled-by-prettify">ListNode</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 pop_until_empt=
y</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">this</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">&</span><span style=3D"color: #606;" c=
lass=3D"styled-by-prettify">ListNode</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">::</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">next</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">};<=
/span></div></code></div><div><br></div><div>However, it turned out that th=
e above did not compile... because std::unique_ptr and std::shared_ptr curr=
ently lack any overload for operator->*.</div><div>I found a paper by Sc=
ott Meyers from 1999, <a href=3D"http://www.aristeia.com/Papers/DDJ_Oct_199=
9.pdf">"Implementing operator->* for smart pointers"</a>, whic=
h shows how difficult it was to implement this operator in C++03. (In fact,=
I think the signature that got standardized for overloading operator->*=
might have been suboptimal; but that ship has long since sailed.)</div><di=
v><br></div><div>Anyway, I think that as of C++14 we have enough core langu=
age features that we can make a good stab at implementing operator->* fo=
r smart pointers. Can anyone poke any holes in the following pair of templa=
te definitions? =C2=A0I would propose to add both of these overloaded opera=
tors to unique_ptr and shared_ptr in C++2w, unless there's some fatal f=
law I'm not seeing.</div><div><br></div><div class=3D"prettyprint" styl=
e=3D"background-color: rgb(250, 250, 250); border: 1px solid rgb(187, 187, =
187); word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"sub=
prettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettify">=C2=
=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>template</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&=
lt;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">typenam=
e</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> M</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">></span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">decltype</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">operator</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">->*</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
">M T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::*</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">mp</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">const</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:=
#008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(*(*</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">this</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">)).*</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">mp</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">tem=
plate</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">typename</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> R</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">typename</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">...</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"=
styled-by-prettify">Args</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">></span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>operator</span><span style=3D"color: #660;" class=3D"styled-by-prettify">-=
>*</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">R </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">T</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">::*</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">mfp</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">)(</span><span style=3D"color: #606;" class=3D"styled-by-pretti=
fy">Args</span><span style=3D"color: #660;" class=3D"styled-by-prettify">..=
..))</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">const</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">[</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">p </span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">&**</span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">this</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> mf=
p </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> mfp</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">](</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">&&...</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> args</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">p</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">->*</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify">mfp</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">)(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">st=
d</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">forward</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">decltype</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">args</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">)>(</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify">args</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)...);</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">};</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">}</span></div></code></div><div><=
font face=3D"courier new, monospace"><br></font></div><div>Thanks,</div><di=
v>=E2=80=93Arthur</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/e0ea00a6-98a7-47a2-b960-8f494fb02e2c%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/e0ea00a6-98a7-47a2-b960-8f494fb02e2c=
%40isocpp.org</a>.<br />
------=_Part_4961_1605188686.1474683574476--
------=_Part_4960_1580567115.1474683574475--
.
Author: inkwizytoryankes@gmail.com
Date: Sat, 24 Sep 2016 07:45:36 -0700 (PDT)
Raw View
------=_Part_109_1914418724.1474728336820
Content-Type: multipart/alternative;
boundary="----=_Part_110_1678074719.1474728336821"
------=_Part_110_1678074719.1474728336821
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, September 24, 2016 at 4:19:34 AM UTC+2, Arthur O'Dwyer wrote:
>
> While listening to Herb Sutter's keynote at the end of CppCon 2016, I=20
> attempted to implement a generic "free a linked list of unique_ptrs witho=
ut=20
> blowing the stack" algorithm, i.e.
>
> template<typename ClassType, typename SmartPtr>
> void pop_until_empty(ClassType *self, SmartPtr T::*next)
> {
> while (self->*next) {
> self->*next =3D (self->*next)->*next;
> }
> }
>
>
> struct ListNode {
> std::unique_ptr<ListNode> next;
> ~ListNode() {
> pop_until_empty(this, &ListNode::next);
> }
> };
>
> However, it turned out that the above did not compile... because=20
> std::unique_ptr and std::shared_ptr currently lack any overload for=20
> operator->*.
> I found a paper by Scott Meyers from 1999, "Implementing operator->* for=
=20
> smart pointers" <http://www.aristeia.com/Papers/DDJ_Oct_1999.pdf>, which=
=20
> shows how difficult it was to implement this operator in C++03. (In fact,=
I=20
> think the signature that got standardized for overloading operator->* mig=
ht=20
> have been suboptimal; but that ship has long since sailed.)
>
> Anyway, I think that as of C++14 we have enough core language features=20
> that we can make a good stab at implementing operator->* for smart=20
> pointers. Can anyone poke any holes in the following pair of template=20
> definitions? I would propose to add both of these overloaded operators t=
o=20
> unique_ptr and shared_ptr in C++2w, unless there's some fatal flaw I'm no=
t=20
> seeing.
>
> template<typename M>
> decltype(auto) operator->* (M T::*mp) const {
> return (*(*this)).*mp;
> }
> template<typename R, typename... Args>
> auto operator->* (R (T::*mfp)(Args...)) const {
> return [p =3D &**this, mfp =3D mfp](auto&&... args) {
> return (p->*mfp)(std::forward<decltype(args)>(args)...);
> };
> }
>
> Thanks,
> =E2=80=93Arthur
>
I think another approach could be avoid `->*` and use `std::invoke`:
template<typename ClassType, typename SmartPtr>
void pop_until_empty(ClassType *self, SmartPtr ClassType::*next)
{
while (std::invoke(next, self)) {
std::invoke(next, self) =3D std::invoke(next, std::invoke(next, sel=
f
));
}
}
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/5848a02e-f8dd-455f-b82a-edf00fb92ea1%40isocpp.or=
g.
------=_Part_110_1678074719.1474728336821
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Saturday, September 24, 2016 at 4:19:34 AM UTC+=
2, Arthur O'Dwyer wrote:<blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><d=
iv dir=3D"ltr"><div>While listening to Herb Sutter's keynote at the end=
of CppCon 2016, I attempted to implement a generic "free a linked lis=
t of unique_ptrs without blowing the stack" algorithm, i.e.</div><div>=
<br></div><div style=3D"background-color:rgb(250,250,250);border:1px solid =
rgb(187,187,187);word-wrap:break-word"><code><div><span style=3D"color:#008=
">template</span><span style=3D"color:#660"><</span><span style=3D"color=
:#008">typename</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#606">ClassType</span><span style=3D"color:#660">,</span><span style=3D"=
color:#000"> </span><span style=3D"color:#008">typename</span><span style=
=3D"color:#000"> </span><span style=3D"color:#606">SmartPtr</span><span sty=
le=3D"color:#660">></span><span style=3D"color:#000"><br></span><span st=
yle=3D"color:#008">void</span><span style=3D"color:#000"> pop_until_empty</=
span><span style=3D"color:#660">(</span><span style=3D"color:#606">ClassTyp=
e</span><span style=3D"color:#000"> </span><span style=3D"color:#660">*</sp=
an><span style=3D"color:#008">self</span><span style=3D"color:#660">,</span=
><span style=3D"color:#000"> </span><span style=3D"color:#606">SmartPtr</sp=
an><span style=3D"color:#000"> T</span><span style=3D"color:#660">::*</span=
><span style=3D"color:#008">next</span><span style=3D"color:#660">)</span><=
span style=3D"color:#000"><br></span><span style=3D"color:#660">{</span><sp=
an style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008"=
>while</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
(</span><span style=3D"color:#008">self</span><span style=3D"color:#660">-&=
gt;*</span><span style=3D"color:#008">next</span><span style=3D"color:#660"=
>)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">{</s=
pan><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span=
style=3D"color:#008">self</span><span style=3D"color:#660">->*</span><s=
pan style=3D"color:#008">next</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#660">(</span><span style=3D"color:#008">self</span><span sty=
le=3D"color:#660">->*</span><span style=3D"color:#008">next</span><span =
style=3D"color:#660">)->*</span><span style=3D"color:#008">next</span><s=
pan style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 </span><span style=3D"color:#660">}</span><span style=3D"color:#000"><b=
r></span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br>=
<br><br></span><span style=3D"color:#008">struct</span><span style=3D"color=
:#000"> </span><span style=3D"color:#606">ListNode</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#0=
00"><br>=C2=A0 =C2=A0 std</span><span style=3D"color:#660">::</span><span s=
tyle=3D"color:#000">unique_ptr</span><span style=3D"color:#660"><</span>=
<span style=3D"color:#606">ListNode</span><span style=3D"color:#660">></=
span><span style=3D"color:#000"> </span><span style=3D"color:#008">next</sp=
an><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0=
=C2=A0 </span><span style=3D"color:#660">~</span><span style=3D"color:#606=
">ListNode</span><span style=3D"color:#660">()</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#000">=
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 pop_until_empty</span><span style=3D"color:=
#660">(</span><span style=3D"color:#008">this</span><span style=3D"color:#6=
60">,</span><span style=3D"color:#000"> </span><span style=3D"color:#660">&=
amp;</span><span style=3D"color:#606">ListNode</span><span style=3D"color:#=
660">::</span><span style=3D"color:#008">next</span><span style=3D"color:#6=
60">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span styl=
e=3D"color:#660">}</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#660">};</span></div></code></div><div><br></div><div>However, it=
turned out that the above did not compile... because std::unique_ptr and s=
td::shared_ptr currently lack any overload for operator->*.</div><div>I =
found a paper by Scott Meyers from 1999, <a href=3D"http://www.aristeia.com=
/Papers/DDJ_Oct_1999.pdf" target=3D"_blank" rel=3D"nofollow" onmousedown=3D=
"this.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.aristeia.=
com%2FPapers%2FDDJ_Oct_1999.pdf\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHF0=
NewyzkH-pfEoqakJFXYod7V-Q';return true;" onclick=3D"this.href=3D'ht=
tp://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.aristeia.com%2FPapers%2FDDJ_O=
ct_1999.pdf\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHF0NewyzkH-pfEoqakJFXYo=
d7V-Q';return true;">"Implementing operator->* for smart pointe=
rs"</a>, which shows how difficult it was to implement this operator i=
n C++03. (In fact, I think the signature that got standardized for overload=
ing operator->* might have been suboptimal; but that ship has long since=
sailed.)</div><div><br></div><div>Anyway, I think that as of C++14 we have=
enough core language features that we can make a good stab at implementing=
operator->* for smart pointers. Can anyone poke any holes in the follow=
ing pair of template definitions? =C2=A0I would propose to add both of thes=
e overloaded operators to unique_ptr and shared_ptr in C++2w, unless there&=
#39;s some fatal flaw I'm not seeing.</div><div><br></div><div style=3D=
"background-color:rgb(250,250,250);border:1px solid rgb(187,187,187);word-w=
rap:break-word"><code><div><span style=3D"color:#000">=C2=A0 =C2=A0 </span>=
<span style=3D"color:#008">template</span><span style=3D"color:#660"><</=
span><span style=3D"color:#008">typename</span><span style=3D"color:#000"> =
M</span><span style=3D"color:#660">></span><span style=3D"color:#000"><b=
r>=C2=A0 =C2=A0 </span><span style=3D"color:#008">decltype</span><span styl=
e=3D"color:#660">(</span><span style=3D"color:#008">auto</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#008">operator</span><span style=3D"color:#660">->*</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#660">(</span><span style=3D=
"color:#000">M T</span><span style=3D"color:#660">::*</span><span style=3D"=
color:#000">mp</span><span style=3D"color:#660">)</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#008">const</span><span style=3D"color=
:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#000=
"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#660">(*(*</s=
pan><span style=3D"color:#008">this</span><span style=3D"color:#660">)).*</=
span><span style=3D"color:#000">mp</span><span style=3D"color:#660">;</span=
><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#=
660">}</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span styl=
e=3D"color:#008">template</span><span style=3D"color:#660"><</span><span=
style=3D"color:#008">typename</span><span style=3D"color:#000"> R</span><s=
pan style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#008">typename</span><span style=3D"color:#660">...</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#606">Args</span><span=
style=3D"color:#660">></span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 </span><span style=3D"color:#008">auto</span><span style=3D"color:#000"=
> </span><span style=3D"color:#008">operator</span><span style=3D"color:#66=
0">->*</span><span style=3D"color:#000"> </span><span style=3D"color:#66=
0">(</span><span style=3D"color:#000">R </span><span style=3D"color:#660">(=
</span><span style=3D"color:#000">T</span><span style=3D"color:#660">::*</s=
pan><span style=3D"color:#000">mfp</span><span style=3D"color:#660">)(</spa=
n><span style=3D"color:#606">Args</span><span style=3D"color:#660">...))</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#008">const</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#660">{</span><s=
pan style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color:#008">return</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">[</span><span style=3D"color:#000">p </span><span style=3D"=
color:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#660">&**</span><span style=3D"color:#008">this</span><span style=3D=
"color:#660">,</span><span style=3D"color:#000"> mfp </span><span style=3D"=
color:#660">=3D</span><span style=3D"color:#000"> mfp</span><span style=3D"=
color:#660">](</span><span style=3D"color:#008">auto</span><span style=3D"c=
olor:#660">&&...</span><span style=3D"color:#000"> args</span><span=
style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#660">(</span><span st=
yle=3D"color:#000">p</span><span style=3D"color:#660">->*</span><span st=
yle=3D"color:#000">mfp</span><span style=3D"color:#660">)(</span><span styl=
e=3D"color:#000">std</span><span style=3D"color:#660">::</span><span style=
=3D"color:#000">forward</span><span style=3D"color:#660"><</span><span s=
tyle=3D"color:#008">decltyp<wbr>e</span><span style=3D"color:#660">(</span>=
<span style=3D"color:#000">args</span><span style=3D"color:#660">)>(</sp=
an><span style=3D"color:#000">args</span><span style=3D"color:#660">)...);<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><sp=
an style=3D"color:#660">};</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 </span><span style=3D"color:#660">}</span></div></code></div><div><font=
face=3D"courier new, monospace"><br></font></div><div>Thanks,</div><div>=
=E2=80=93Arthur</div></div></blockquote><div><br><br>I think another approa=
ch could be avoid `->*` and use `std::invoke`:<br><div class=3D"prettypr=
int" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, =
187, 187); border-style: solid; border-width: 1px; word-wrap: break-word;">=
<code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">template</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">typename</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">ClassType</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">typename</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Smart=
Ptr</span><span style=3D"color: #660;" class=3D"styled-by-prettify">></s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">void</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> pop_until_empty</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">ClassType</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">*</span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">self</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-pret=
tify">SmartPtr</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><code class=3D"prettyprint"><span style=3D"color: #000;" class=
=3D"styled-by-prettify"></span><span style=3D"color: #606;" class=3D"styled=
-by-prettify">ClassType</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify"></span></code><span style=3D"color: #660;" class=3D"styled-by-=
prettify">::*</span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">next</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">while</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">(</span><code class=3D"prettyprin=
t"><span style=3D"color: #660;" class=3D"styled-by-prettify"></span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">std</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify">invoke</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">(</span><code class=3D"prettyprint"><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">next</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"></span></code><span style=3D=
"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify"></span><code class=3D"prettyprint"><span style=3D=
"color: #660;" class=3D"styled-by-prettify"></span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">self</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify"></span></code><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">)</span></code><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 std</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">invoke</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">(</span><code class=3D"prettyprint"><span style=3D"color: #008;=
" class=3D"styled-by-prettify">next</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify"></span></code><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span> <span style=3D"color: #660;" class=3D"styl=
ed-by-prettify"></span><code class=3D"prettyprint"><span style=3D"color: #6=
60;" class=3D"styled-by-prettify"></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">self</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify"></span></code><span style=3D"color: #660;" class=3D"style=
d-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">invoke</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><code class=3D"prett=
yprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">next</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify"></span></code><=
span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify"></span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">std</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">invoke</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">(</span><code class=3D"prettyprint"><span style=3D"color: #008;=
" class=3D"styled-by-prettify">next</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify"></span></code><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify"></span><code class=3D"prettyprint"><span style=3D"color: #008;" class=
=3D"styled-by-prettify">self</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify"></span></code><span style=3D"color: #660;" class=3D"style=
d-by-prettify">));</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></sp=
an></div></code></div><br><br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/5848a02e-f8dd-455f-b82a-edf00fb92ea1%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5848a02e-f8dd-455f-b82a-edf00fb92ea1=
%40isocpp.org</a>.<br />
------=_Part_110_1678074719.1474728336821--
------=_Part_109_1914418724.1474728336820--
.
Author: "'Johannes Schaub' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Sat, 24 Sep 2016 18:07:13 +0200
Raw View
2016-09-24 4:19 GMT+02:00 Arthur O'Dwyer <arthur.j.odwyer@gmail.com>:
> While listening to Herb Sutter's keynote at the end of CppCon 2016, I
> attempted to implement a generic "free a linked list of unique_ptrs without
> blowing the stack" algorithm, i.e.
>
> template<typename ClassType, typename SmartPtr>
> void pop_until_empty(ClassType *self, SmartPtr T::*next)
> {
> while (self->*next) {
> self->*next = (self->*next)->*next;
> }
> }
>
>
> struct ListNode {
> std::unique_ptr<ListNode> next;
> ~ListNode() {
> pop_until_empty(this, &ListNode::next);
> }
> };
>
> However, it turned out that the above did not compile... because
> std::unique_ptr and std::shared_ptr currently lack any overload for
> operator->*.
> I found a paper by Scott Meyers from 1999, "Implementing operator->* for
> smart pointers", which shows how difficult it was to implement this operator
> in C++03. (In fact, I think the signature that got standardized for
> overloading operator->* might have been suboptimal; but that ship has long
> since sailed.)
>
> Anyway, I think that as of C++14 we have enough core language features that
> we can make a good stab at implementing operator->* for smart pointers. Can
> anyone poke any holes in the following pair of template definitions? I
> would propose to add both of these overloaded operators to unique_ptr and
> shared_ptr in C++2w, unless there's some fatal flaw I'm not seeing.
>
> template<typename M>
> decltype(auto) operator->* (M T::*mp) const {
> return (*(*this)).*mp;
> }
> template<typename R, typename... Args>
> auto operator->* (R (T::*mfp)(Args...)) const {
> return [p = &**this, mfp = mfp](auto&&... args) {
> return (p->*mfp)(std::forward<decltype(args)>(args)...);
> };
> }
>
Probably I'm telling you what you already know, but it needs overloads
for const, const volatile, volatile, const&, const&&, .... etc.
Perhaps combining them?
template<typename M>
decltype(auto) operator->* (M T::*mp) const {
if constexpr(std::is_function_v<M>)
return [p = &*this, mfp = mfp](auto&&... args) -> decltype(auto) {
return (p->*mfp)(std::forward<decltype(args)>(args)...);
};
} else {
return (*this).*mp;
}
}
I hope I have the syntax right...
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CANu6V4U-j%2B0UmJEsHANU88r9DK8U-vQOBWZD405C7n%2BoJEWVCQ%40mail.gmail.com.
.
Author: "'Johannes Schaub' via ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Date: Sat, 24 Sep 2016 18:18:28 +0200
Raw View
2016-09-24 4:19 GMT+02:00 Arthur O'Dwyer <arthur.j.odwyer@gmail.com>:
> While listening to Herb Sutter's keynote at the end of CppCon 2016, I
> attempted to implement a generic "free a linked list of unique_ptrs without
> blowing the stack" algorithm, i.e.
>
> template<typename ClassType, typename SmartPtr>
> void pop_until_empty(ClassType *self, SmartPtr T::*next)
> {
> while (self->*next) {
> self->*next = (self->*next)->*next;
> }
> }
>
>
> struct ListNode {
> std::unique_ptr<ListNode> next;
> ~ListNode() {
> pop_until_empty(this, &ListNode::next);
> }
> };
>
> However, it turned out that the above did not compile... because
> std::unique_ptr and std::shared_ptr currently lack any overload for
> operator->*.
> I found a paper by Scott Meyers from 1999, "Implementing operator->* for
> smart pointers", which shows how difficult it was to implement this operator
> in C++03. (In fact, I think the signature that got standardized for
> overloading operator->* might have been suboptimal; but that ship has long
> since sailed.)
>
> Anyway, I think that as of C++14 we have enough core language features that
> we can make a good stab at implementing operator->* for smart pointers. Can
> anyone poke any holes in the following pair of template definitions? I
> would propose to add both of these overloaded operators to unique_ptr and
> shared_ptr in C++2w, unless there's some fatal flaw I'm not seeing.
>
I would also recomment to implement the ->* as a non-member function
and for shared_ptr+member function pointer either
- Catch the shared_ptr by value into the lambda, so that the owned
object is not destroyed while the ->* result is alive
- Forbid copying or moving the returned lambda
For unique_ptr+member function pointer, you should probably always
forbid copying or moving the returned lambda. I hope that guaranteed
copy elision will still allow us to forbid things like that.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CANu6V4VCnQFW5f_fr_KnZeWSunL5digxg6pN5E%2BF5eAmBfUHNg%40mail.gmail.com.
.