Topic: Proposal to "fix" operator->* overloading


Author: Mikhail Semenov <mikhailsemenov1957@gmail.com>
Date: Tue, 28 May 2013 10:31:49 -0700 (PDT)
Raw View
------=_Part_151_9149867.1369762309984
Content-Type: text/plain; charset=ISO-8859-1



When I was looking at shared pointers I came across at a rather bizarre
feature in C++:
overloading operator->* , which cannot be easily made to do what one wants.
This caused a problem with shared pointers.
If there is a pointer to member, say memb,
you may write
*((*px).*memb)(10.0);
*but you may not write:
*(px->*memb)(10.0).*

The problem is that it is not easy to overload ->* to deal with member
functions.

*In order to "fix" this problem, I propose that operator->* will
automatically
apply to member functions of the object that is used in operator->
overloading.
*I don't think that anybody will miss the old operator->* overloading: it
should
probably be removed. Or am I missing something that other developers find
useful?

Below I put the code that manages to overload ->* in class A, but
it uses std::function and is not that efficient. I would rather the
overloading of the
operator ->* could be dropped altogether.

#include<iostream>
#include <memory>
#include <functional>

class X

{
    double a;

public:

    X(double a1):a(a1) {}
    double add(double z) { a += z; return a; }
    double sub(double z) { a -= z; return a; }
    double get() const { return a; }
};

class A

{
    X x;
public:
    A(const X& x1):x(x1) {}
    X operator->() { return x; }
    X operator*() { return x; }

  *  template<class R, class ... Arg>
    std::function<R(Arg...)> operator->*(R (X::*f)(Arg ...)) { return
[f,this](Arg ... a) { return (x.*f)(std::forward<Arg>(a) ...); }; }*

*    template<class R, class ... Arg>
    std::function<R(Arg...)> operator->*(R (X::*f)(Arg ...) const) { return
[f,this](Arg ... a) { return (x.*f)(std::forward<Arg>(a) ...); }; }*

};

int main()

{
    X z(1.0);
    A a(z);
    double (X::*memb)(double) = &X::add;
    double p = (a->*memb)(2.0);
    auto memb0 = &X::get;
    double p0 = (a->*memb0)();

    // use of a shared pointer
    std::shared_ptr<X> px(new X(20));

    std::cout << p << " " << p0 << std::endl;
   * // double px1 = (px->*memb)(10.0);// not allowed*
    double px1 = ((*px).*memb)(10.0);
    std::cout << px1 <<  std::endl;

    return 0;
}

--

---
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/?hl=en.



------=_Part_151_9149867.1369762309984
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<p>When I was looking at shared pointers I came across at a rather bizarre =
feature in C++:<br>overloading operator-&gt;* , which cannot be easily made=
 to do what one wants.<br>This caused a problem with shared pointers.<br>If=
 there is a pointer to member, say memb, <br>you may write<br><strong>((*px=
).*memb)(10.0);<br></strong>but you may not write:<br><strong>(px-&gt;*memb=
)(10.0).</strong></p><p>The problem is that it is not easy to overload -&gt=
;* to deal with member functions.</p><p><strong>In order to "fix" this prob=
lem, I propose that operator-&gt;* will automatically <br>apply to member f=
unctions of the object that is used in operator-&gt; overloading.<br></stro=
ng>I don't think that anybody will miss the old operator-&gt;* overloading:=
 it should<br>probably be removed. Or am I missing something that other dev=
elopers find useful?</p><p>Below I&nbsp;put the code that manages to overlo=
ad -&gt;* in class A, but <br>it uses std::function and is not that efficie=
nt. I would rather the overloading of the <br>operator -&gt;* could be drop=
ped altogether.</p><p>#include&lt;iostream&gt;<br>#include &lt;memory&gt;<b=
r>#include &lt;functional&gt;</p><p>class X</p><p>{<br>&nbsp;&nbsp;&nbsp; d=
ouble a;</p><p>public:</p><p>&nbsp;&nbsp;&nbsp; X(double a1):a(a1) {}<br>&n=
bsp;&nbsp;&nbsp; double add(double z) { a +=3D z; return a; }<br>&nbsp;&nbs=
p;&nbsp; double sub(double z) { a -=3D z; return a; }<br>&nbsp;&nbsp;&nbsp;=
 double get() const { return a; }&nbsp;&nbsp;&nbsp; <br>};</p><p>class A</p=
><p>{<br>&nbsp;&nbsp;&nbsp; X x;<br>public:<br>&nbsp;&nbsp;&nbsp; A(const X=
&amp; x1):x(x1) {}<br>&nbsp;&nbsp;&nbsp; X operator-&gt;() { return x; }<br=
>&nbsp;&nbsp;&nbsp; X operator*() { return x; }&nbsp;&nbsp;&nbsp; </p><p>&n=
bsp;&nbsp;<strong>&nbsp; template&lt;class R, class ... Arg&gt;<br>&nbsp;&n=
bsp;&nbsp; std::function&lt;R(Arg...)&gt; operator-&gt;*(R (X::*f)(Arg ...)=
) { return [f,this](Arg ... a) { return (x.*f)(std::forward&lt;Arg&gt;(a) .=
...); }; }</strong></p><p><strong>&nbsp;&nbsp;&nbsp; template&lt;class R, cl=
ass ... Arg&gt;<br>&nbsp;&nbsp;&nbsp; std::function&lt;R(Arg...)&gt; operat=
or-&gt;*(R (X::*f)(Arg ...) const) { return [f,this](Arg ... a) { return (x=
..*f)(std::forward&lt;Arg&gt;(a) ...); }; }</strong></p><p>};</p><p>int main=
()</p><p>{<br>&nbsp;&nbsp;&nbsp; X z(1.0);<br>&nbsp;&nbsp;&nbsp; A a(z);<br=
>&nbsp;&nbsp;&nbsp; double (X::*memb)(double) =3D &amp;X::add;&nbsp;&nbsp;&=
nbsp; <br>&nbsp;&nbsp;&nbsp; double p =3D (a-&gt;*memb)(2.0);<br>&nbsp;&nbs=
p;&nbsp; auto memb0 =3D &amp;X::get;<br>&nbsp;&nbsp;&nbsp; double p0 =3D (a=
-&gt;*memb0)();<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; // use of a sh=
ared pointer<br>&nbsp;&nbsp;&nbsp; std::shared_ptr&lt;X&gt; px(new X(20));&=
nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;=
&nbsp;&nbsp; std::cout &lt;&lt; p &lt;&lt; " " &lt;&lt; p0 &lt;&lt; std::en=
dl;<br>&nbsp;&nbsp;&nbsp;<strong> // double px1 =3D (px-&gt;*memb)(10.0);//=
 not allowed</strong>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; double px1 =
=3D ((*px).*memb)(10.0);&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; std::cout=
 &lt;&lt; px1 &lt;&lt;&nbsp; std::endl;<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nb=
sp;&nbsp; return 0;<br>}<br></p>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
&nbsp;<br />
&nbsp;<br />

------=_Part_151_9149867.1369762309984--

.


Author: Jonathan Wakely <cxx@kayari.org>
Date: Tue, 28 May 2013 10:55:15 -0700 (PDT)
Raw View
------=_Part_249_22050511.1369763715994
Content-Type: text/plain; charset=ISO-8859-1



On Tuesday, May 28, 2013 6:31:49 PM UTC+1, Mikhail Semenov wrote:
>
>
> I don't think that anybody will miss the old operator->* overloading: it
> should
> probably be removed. Or am I missing something that other developers find
> useful?
>
I disagree, it's put to very good use by
https://github.com/philsquared/Catch/wiki because it has such low
precedence.


--

---
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/?hl=en.



------=_Part_249_22050511.1369763715994
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<br><br>On Tuesday, May 28, 2013 6:31:49 PM UTC+1, Mikhail Semenov wrote:<b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><br><p>I don't think that anybod=
y will miss the old operator-&gt;* overloading: it should<br>probably be re=
moved. Or am I missing something that other developers find useful?</p></bl=
ockquote><div>I disagree, it's put to very good use by https://github.com/p=
hilsquared/Catch/wiki because it has such low precedence.<br></div><br><br>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
&nbsp;<br />
&nbsp;<br />

------=_Part_249_22050511.1369763715994--

.


Author: Xeo <hivemaster@hotmail.de>
Date: Tue, 28 May 2013 11:14:28 -0700 (PDT)
Raw View
------=_Part_420_28988129.1369764868378
Content-Type: text/plain; charset=ISO-8859-1



On Tuesday, May 28, 2013 7:31:49 PM UTC+2, Mikhail Semenov wrote:

> but you may not write:
> *(px->*memb)(10.0).*
>
`(px.get()->*memb)(10.0);` is a solution, but I admit, not a clean one.


> The problem is that it is not easy to overload ->* to deal with member
> functions.
>
It actually is - it's just a bit of boilerplate, but that bit is generic
enough to deal with any and all member pointers I found.


> *In order to "fix" this problem, I propose that operator->* will
> automatically
> apply to member functions of the object that is used in operator->
> overloading.
> *I don't think that anybody will miss the old operator->* overloading: it
> should
> probably be removed. Or am I missing something that other developers find
> useful?
>
Stop. Full stop. You can't just change the behaviour of a fundamental
operator like that. Some libraries *rely* on how `operator->*` works.
Exhibit A: CATCH <https://github.com/philsquared/Catch/wiki>.


> Below I put the code that manages to overload ->* in class A, but
> it uses std::function and is not that efficient. I would rather the
> overloading of the
> operator ->* could be dropped altogether.
>

Just don't use a lambda? You can have a hand-written functor that removes
the need for the lambda and `std::function`. Even better, you can even use
`std::bind` and `decltype` for the return type!

template<class S, class C>
auto operator->*(S C::* ptm) -> decltype(easy_bind(ptm, ptr)){ returneasy_bind
(ptm, ptr); }

Should do the job (untested, with `easy_bind` automatically filling in the
placeholders, which is easy).


--

---
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/?hl=en.



------=_Part_420_28988129.1369764868378
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<br><br>On Tuesday, May 28, 2013 7:31:49 PM UTC+2, Mikhail Semenov wrote:<b=
r><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><p>but you may not write:<br=
><b>(px-&gt;*memb)(10.0).</b></p></blockquote><div>`(px.get()-&gt;*memb)(10=
..0);` is a solution, but I admit, not a clean one.<br>&nbsp;</div><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
 1px #ccc solid;padding-left: 1ex;"><p>The problem is that it is not easy t=
o overload -&gt;* to deal with member functions.</p></blockquote><div>It ac=
tually is - it's just a bit of boilerplate, but that bit is generic enough =
to deal with any and all member pointers I found.<br>&nbsp;</div><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;"><p><b>In order to "fix" this problem, I =
propose that operator-&gt;* will automatically <br>apply to member function=
s of the object that is used in operator-&gt; overloading.<br></b>I don't t=
hink that anybody will miss the old operator-&gt;* overloading: it should<b=
r>probably be removed. Or am I missing something that other developers find=
 useful?</p></blockquote><div>Stop. Full stop. You can't just change the be=
haviour of a fundamental operator like that. Some libraries *rely* on how `=
operator-&gt;*` works. Exhibit A: <a href=3D"https://github.com/philsquared=
/Catch/wiki">CATCH</a>.<br>&nbsp;<br></div><blockquote class=3D"gmail_quote=
" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding=
-left: 1ex;"><p>Below I&nbsp;put the code that manages to overload -&gt;* i=
n class A, but <br>it uses std::function and is not that efficient. I would=
 rather the overloading of the <br>operator -&gt;* could be dropped altoget=
her.</p></blockquote><div><br>Just don't use a lambda? You can have a hand-=
written functor that removes the need for the lambda and `std::function`. E=
ven better, you can even use `std::bind` and `decltype` for the return type=
!<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250=
, 250); border-color: rgb(187, 187, 187); border-style: solid; border-width=
: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"su=
bprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">tem=
plate</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;<=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">class</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> S</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: #00=
8;" class=3D"styled-by-prettify">class</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> C</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">operato=
r</span><span style=3D"color: #660;" class=3D"styled-by-prettify">-&gt;*(</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">S C</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">::*</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> ptm</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">-&gt;</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">decltype</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
easy_bind</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">ptm</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> ptr</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;" cl=
ass=3D"styled-by-prettify">return</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> easy_bind</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">ptm</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
ptr</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br></span></div></code></div><br=
>Should do the job (untested, with `easy_bind` automatically filling in the=
 placeholders, which is easy).<br>&nbsp;</div>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
&nbsp;<br />
&nbsp;<br />

------=_Part_420_28988129.1369764868378--

.


Author: Richard Smith <richard@metafoo.co.uk>
Date: Tue, 28 May 2013 15:23:51 -0700
Raw View
--20cf307ca2be4a3b5d04ddceb84d
Content-Type: text/plain; charset=ISO-8859-1

On Tue, May 28, 2013 at 10:31 AM, Mikhail Semenov <
mikhailsemenov1957@gmail.com> wrote:

> When I was looking at shared pointers I came across at a rather bizarre
> feature in C++:
> overloading operator->* , which cannot be easily made to do what one wants.
> This caused a problem with shared pointers.
> If there is a pointer to member, say memb,
> you may write
> *((*px).*memb)(10.0);
> *but you may not write:
> *(px->*memb)(10.0).*
>
> The problem is that it is not easy to overload ->* to deal with member
> functions.
>
> *In order to "fix" this problem, I propose that operator->* will
> automatically
> apply to member functions of the object that is used in operator->
> overloading.
> *I don't think that anybody will miss the old operator->* overloading: it
> should
> probably be removed. Or am I missing something that other developers find
> useful?
>
> Below I put the code that manages to overload ->* in class A, but
> it uses std::function and is not that efficient. I would rather the
> overloading of the
> operator ->* could be dropped altogether.
>
> #include<iostream>
> #include <memory>
> #include <functional>
>
> class X
>
> {
>     double a;
>
> public:
>
>     X(double a1):a(a1) {}
>     double add(double z) { a += z; return a; }
>     double sub(double z) { a -= z; return a; }
>     double get() const { return a; }
> };
>
> class A
>
> {
>     X x;
> public:
>     A(const X& x1):x(x1) {}
>     X operator->() { return x; }
>     X operator*() { return x; }
>
>   *  template<class R, class ... Arg>
>     std::function<R(Arg...)> operator->*(R (X::*f)(Arg ...)) { return
> [f,this](Arg ... a) { return (x.*f)(std::forward<Arg>(a) ...); }; }*
>
> *    template<class R, class ... Arg>
>     std::function<R(Arg...)> operator->*(R (X::*f)(Arg ...) const) {
> return [f,this](Arg ... a) { return (x.*f)(std::forward<Arg>(a) ...); }; *
>

In C++14, there's no efficiency problem:

template<typename T, typename EnableIf =
std::enable_if<std::is_member_function_pointer<T>::value>>
auto operator->*(T f) const { return [p(**this), f](auto &&...args) ->
decltype(auto) { return (p->*f)(static_cast<decltype(args)>(args)...); }; }

template<typename T, typename EnableIf =
std::enable_if<std::is_member_object_pointer<T>::value>>
decltype(auto) operator->*(T v) const { return (**this).*v; }

It would make sense to me to add something of this form to the standard
library's smart pointers for C++17. Most of that work can easily be
factored out into a helper function, so that the definition is just:

template<typename T> decltype(auto) operator->*(T v) const { return
std::arrow_star(**this, v); }

Aside from the (slight) verbosity, I can think of one disadvantage of this
compared to transparently using operator-> -- it doesn't use the caller's
context when checking access for a derived-to-base conversion on the
pointer.

> *}*
>
> };
>
> int main()
>
> {
>     X z(1.0);
>     A a(z);
>     double (X::*memb)(double) = &X::add;
>     double p = (a->*memb)(2.0);
>     auto memb0 = &X::get;
>     double p0 = (a->*memb0)();
>
>     // use of a shared pointer
>     std::shared_ptr<X> px(new X(20));
>
>     std::cout << p << " " << p0 << std::endl;
>    * // double px1 = (px->*memb)(10.0);// not allowed*
>     double px1 = ((*px).*memb)(10.0);
>     std::cout << px1 <<  std::endl;
>
>     return 0;
> }
>
> --
>
> ---
> 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/?hl=en.
>
>
>

--

---
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/?hl=en.



--20cf307ca2be4a3b5d04ddceb84d
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

On Tue, May 28, 2013 at 10:31 AM, Mikhail Semenov <span dir=3D"ltr">&lt;<a =
href=3D"mailto:mikhailsemenov1957@gmail.com" target=3D"_blank">mikhailsemen=
ov1957@gmail.com</a>&gt;</span> wrote:<br><div class=3D"gmail_quote"><block=
quote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc=
 solid;padding-left:1ex">
<p>When I was looking at shared pointers I came across at a rather bizarre =
feature in C++:<br>overloading operator-&gt;* , which cannot be easily made=
 to do what one wants.<br>This caused a problem with shared pointers.<br>
If there is a pointer to member, say memb, <br>you may write<br><strong>((*=
px).*memb)(10.0);<br></strong>but you may not write:<br><strong>(px-&gt;*me=
mb)(10.0).</strong></p><p>The problem is that it is not easy to overload -&=
gt;* to deal with member functions.</p>
<p><strong>In order to &quot;fix&quot; this problem, I propose that operato=
r-&gt;* will automatically <br>apply to member functions of the object that=
 is used in operator-&gt; overloading.<br></strong>I don&#39;t think that a=
nybody will miss the old operator-&gt;* overloading: it should<br>
probably be removed. Or am I missing something that other developers find u=
seful?</p><p>Below I=A0put the code that manages to overload -&gt;* in clas=
s A, but <br>it uses std::function and is not that efficient. I would rathe=
r the overloading of the <br>
operator -&gt;* could be dropped altogether.</p><p>#include&lt;iostream&gt;=
<br>#include &lt;memory&gt;<br>#include &lt;functional&gt;</p><p>class X</p=
><p>{<br>=A0=A0=A0 double a;</p><p>public:</p><p>=A0=A0=A0 X(double a1):a(a=
1) {}<br>
=A0=A0=A0 double add(double z) { a +=3D z; return a; }<br>=A0=A0=A0 double =
sub(double z) { a -=3D z; return a; }<br>=A0=A0=A0 double get() const { ret=
urn a; }=A0=A0=A0 <br>};</p><p>class A</p><p>{<br>=A0=A0=A0 X x;<br>public:=
<br>=A0=A0=A0 A(const X&amp; x1):x(x1) {}<br>
=A0=A0=A0 X operator-&gt;() { return x; }<br>=A0=A0=A0 X operator*() { retu=
rn x; }=A0=A0=A0 </p><p>=A0=A0<strong>=A0 template&lt;class R, class ... Ar=
g&gt;<br>=A0=A0=A0 std::function&lt;R(Arg...)&gt; operator-&gt;*(R (X::*f)(=
Arg ...)) { return [f,this](Arg ... a) { return (x.*f)(std::forward&lt;Arg&=
gt;(a) ...); }; }</strong></p>
<p><strong>=A0=A0=A0 template&lt;class R, class ... Arg&gt;<br>=A0=A0=A0 st=
d::function&lt;R(Arg...)&gt; operator-&gt;*(R (X::*f)(Arg ...) const) { ret=
urn [f,this](Arg ... a) { return (x.*f)(std::forward&lt;Arg&gt;(a) ...); };=
 </strong></p>
</blockquote><div><br></div><div>In C++14, there&#39;s no efficiency proble=
m:</div><div><br></div><div>template&lt;typename T, typename EnableIf =3D s=
td::enable_if&lt;std::is_member_function_pointer&lt;T&gt;::value&gt;&gt;</d=
iv>
<div>auto operator-&gt;*(T f) const { return [p(**this), f](auto &amp;&amp;=
....args) -&gt; decltype(auto) { return (p-&gt;*f)(static_cast&lt;decltype(a=
rgs)&gt;(args)...); }; }</div><div><br></div><div>template&lt;typename T, t=
ypename EnableIf =3D std::enable_if&lt;std::is_member_object_pointer&lt;T&g=
t;::value&gt;&gt;</div>
<div>decltype(auto) operator-&gt;*(T v) const { return (**this).*v; }</div>=
<div><br></div><div>It would make sense to me to add something of this form=
 to the standard library&#39;s smart pointers for C++17. Most of that work =
can easily be factored out into a helper function, so that the definition i=
s just:</div>
<div><br></div><div>template&lt;typename T&gt; decltype(auto) operator-&gt;=
*(T v) const { return std::arrow_star(**this, v); }</div><div><br></div><di=
v>Aside from the (slight) verbosity, I can think of one disadvantage of thi=
s compared to transparently using operator-&gt; -- it doesn&#39;t use the c=
aller&#39;s context when checking access for a derived-to-base conversion o=
n the pointer.</div>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><p><strong>}</strong></p><p>};</p><p>int mai=
n()</p><p>{<br>=A0=A0=A0 X z(1.0);<br>=A0=A0=A0 A a(z);<br>=A0=A0=A0 double=
 (X::*memb)(double) =3D &amp;X::add;=A0=A0=A0 <br>
=A0=A0=A0 double p =3D (a-&gt;*memb)(2.0);<br>=A0=A0=A0 auto memb0 =3D &amp=
;X::get;<br>=A0=A0=A0 double p0 =3D (a-&gt;*memb0)();<br>=A0=A0=A0 <br>=A0=
=A0=A0 // use of a shared pointer<br>=A0=A0=A0 std::shared_ptr&lt;X&gt; px(=
new X(20));=A0=A0=A0 <br>=A0=A0=A0=A0=A0=A0=A0 <br>=A0=A0=A0 std::cout &lt;=
&lt; p &lt;&lt; &quot; &quot; &lt;&lt; p0 &lt;&lt; std::endl;<br>
=A0=A0=A0<strong> // double px1 =3D (px-&gt;*memb)(10.0);// not allowed</st=
rong>=A0=A0=A0 <br>=A0=A0=A0 double px1 =3D ((*px).*memb)(10.0);=A0=A0=A0 <=
br>=A0=A0=A0 std::cout &lt;&lt; px1 &lt;&lt;=A0 std::endl;<br>=A0=A0=A0 <br=
>=A0=A0=A0 return 0;<br>}<span class=3D"HOEnZb"><font color=3D"#888888"><br=
>
</font></span></p><span class=3D"HOEnZb"><font color=3D"#888888">

<p></p>

-- <br>
=A0<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org" target=3D=
"_blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den" target=3D"_blank">http://groups.google.com/a/isocpp=
..org/group/std-proposals/?hl=3Den</a>.<br>
=A0<br>
=A0<br>
</font></span></blockquote></div><br>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
&nbsp;<br />
&nbsp;<br />

--20cf307ca2be4a3b5d04ddceb84d--

.


Author: Mikhail Semenov <mikhailsemenov1957@gmail.com>
Date: Wed, 29 May 2013 08:49:14 +0100
Raw View
--089e013cb81a45e2b404ddd69e19
Content-Type: text/plain; charset=ISO-8859-1

Richard.

It is a valid solution.

Perhaps there is another solution, which requires the language change:
(1) allow ->* overloading as it is at present;
(2) but if -> is defined without ->* overloading, use -> class to get ->*
members. It looks strange that -> applies to members of one class,
but ->* to another. (I know that they are different operators. It was
probably a big mistake to allow ->* overloading in the first place, it
should
have followed ->).

I noticed that problem writing a template when "a" could be a shared
pointer or an ordinary object, so a->get() was not an option,
but ((*a).*memb)(...) worked for both.

--

---
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/?hl=en.



--089e013cb81a45e2b404ddd69e19
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div>Richard.</div>
<div>=A0</div>
<div>It is a valid solution.</div>
<div>=A0</div>
<div>Perhaps there is another solution, which requires the language change:=
</div>
<div>(1) allow -&gt;* overloading as it is at present;</div>
<div>(2) but if -&gt; is defined without -&gt;* overloading, use -&gt; clas=
s to get -&gt;* members. It looks strange that -&gt;=A0applies=A0to members=
 of one class,</div>
<div>but -&gt;*=A0to another. (I know that they are different operators. It=
 was probably a big mistake to allow -&gt;* overloading in the first place,=
 it should</div>
<div>have followed -&gt;).</div>
<div>=A0</div>
<div>I noticed that problem writing a template when=A0&quot;a&quot; could b=
e a shared pointer or an ordinary object, so a-&gt;get() was not an option,=
</div>
<div>but ((*a).*memb)(...) worked for both.</div>
<div>=A0</div>
<div>=A0</div>
<div>=A0</div>
<div>=A0</div>
<div>=A0</div>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
&nbsp;<br />
&nbsp;<br />

--089e013cb81a45e2b404ddd69e19--

.


Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@gmail.com>
Date: Wed, 29 May 2013 10:12:42 +0200
Raw View
2013/5/29 Mikhail Semenov <mikhailsemenov1957@gmail.com>:
> Perhaps there is another solution, which requires the language change:
> (1) allow ->* overloading as it is at present;
> (2) but if -> is defined without ->* overloading, use -> class to get ->*
> members. It looks strange that -> applies to members of one class,
> but ->* to another. (I know that they are different operators. It was
> probably a big mistake to allow ->* overloading in the first place, it
> should
> have followed ->).

I don't think that the core language should impose such restrictions.
Coders can design classes with funny behavior, they can override unary
operator&, comma operator, etc. In many cases you won't do that, so
don't. What looks strange for you at the moment might be useful for
someone in another context. Why should we restrict them in doing so?

Keep also in mind that the same kind of problems can occur for funny
smart pointers that override operator-> which does return something
inconsistent with operator*. I don't think that just by restricting
core language rules this would help to solve such problems. Think
further and you want that operator+= and operator+ are enforced to do
the equivalent things. Where do you want to stop?

- Daniel

--

---
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/?hl=en.



.


Author: Tony V E <tvaneerd@gmail.com>
Date: Wed, 29 May 2013 10:10:49 -0400
Raw View
--001a11c365aae64a5f04dddbf298
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

On Wed, May 29, 2013 at 4:12 AM, Daniel Kr=FCgler
<daniel.kruegler@gmail.com>wrote:

> 2013/5/29 Mikhail Semenov <mikhailsemenov1957@gmail.com>:
> > Perhaps there is another solution, which requires the language change:
> > (1) allow ->* overloading as it is at present;
> > (2) but if -> is defined without ->* overloading, use -> class to get -=
>*
> > members. It looks strange that -> applies to members of one class,
> > but ->* to another. (I know that they are different operators. It was
> > probably a big mistake to allow ->* overloading in the first place, it
> > should
> > have followed ->).
>
> I don't think that the core language should impose such restrictions.
> Coders can design classes with funny behavior, they can override unary
> operator&, comma operator, etc. In many cases you won't do that, so
> don't. What looks strange for you at the moment might be useful for
> someone in another context. Why should we restrict them in doing so?
>
> Keep also in mind that the same kind of problems can occur for funny
> smart pointers that override operator-> which does return something
> inconsistent with operator*. I don't think that just by restricting
> core language rules this would help to solve such problems. Think
> further and you want that operator+=3D and operator+ are enforced to do
> the equivalent things. Where do you want to stop?
>
> - Daniel
>
>
We could, however, add some =3Ddefault magic (or whatever) that generates +=
=3D
given +, and maybe ->* given ->, and the relational operators, etc.

Tony

--=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/?hl=3Den.



--001a11c365aae64a5f04dddbf298
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><br><div class=3D"gmail=
_quote">On Wed, May 29, 2013 at 4:12 AM, Daniel Kr=FCgler <span dir=3D"ltr"=
>&lt;<a href=3D"mailto:daniel.kruegler@gmail.com" target=3D"_blank">daniel.=
kruegler@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">2013/5/29 Mikhail Semenov &lt;<a href=3D"mai=
lto:mikhailsemenov1957@gmail.com">mikhailsemenov1957@gmail.com</a>&gt;:<br>
<div class=3D"im">&gt; Perhaps there is another solution, which requires th=
e language change:<br>
&gt; (1) allow -&gt;* overloading as it is at present;<br>
&gt; (2) but if -&gt; is defined without -&gt;* overloading, use -&gt; clas=
s to get -&gt;*<br>
&gt; members. It looks strange that -&gt; applies to members of one class,<=
br>
&gt; but -&gt;* to another. (I know that they are different operators. It w=
as<br>
&gt; probably a big mistake to allow -&gt;* overloading in the first place,=
 it<br>
&gt; should<br>
&gt; have followed -&gt;).<br>
<br>
</div>I don&#39;t think that the core language should impose such restricti=
ons.<br>
Coders can design classes with funny behavior, they can override unary<br>
operator&amp;, comma operator, etc. In many cases you won&#39;t do that, so=
<br>
don&#39;t. What looks strange for you at the moment might be useful for<br>
someone in another context. Why should we restrict them in doing so?<br>
<br>
Keep also in mind that the same kind of problems can occur for funny<br>
smart pointers that override operator-&gt; which does return something<br>
inconsistent with operator*. I don&#39;t think that just by restricting<br>
core language rules this would help to solve such problems. Think<br>
further and you want that operator+=3D and operator+ are enforced to do<br>
the equivalent things. Where do you want to stop?<br>
<span class=3D"HOEnZb"><font color=3D"#888888"><br>
- Daniel<br>
</font></span><div class=3D"HOEnZb"><div class=3D"h5"><br></div></div></blo=
ckquote><div><br></div><div>We could, however, add some =3Ddefault magic (o=
r whatever) that generates +=3D given +, and maybe -&gt;* given -&gt;, and =
the relational operators, etc.<br>
<br></div><div>Tony<br><br>=A0<br></div></div></div></div>

<p></p>

-- <br />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
&nbsp;<br />
&nbsp;<br />

--001a11c365aae64a5f04dddbf298--

.


Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@gmail.com>
Date: Wed, 29 May 2013 16:16:34 +0200
Raw View
2013/5/29 Tony V E <tvaneerd@gmail.com>:
>
>
>
> On Wed, May 29, 2013 at 4:12 AM, Daniel Kr=FCgler <daniel.kruegler@gmail.=
com>
> wrote:
>>
>> 2013/5/29 Mikhail Semenov <mikhailsemenov1957@gmail.com>:
>> > Perhaps there is another solution, which requires the language change:
>> > (1) allow ->* overloading as it is at present;
>> > (2) but if -> is defined without ->* overloading, use -> class to get
>> > ->*
>> > members. It looks strange that -> applies to members of one class,
>> > but ->* to another. (I know that they are different operators. It was
>> > probably a big mistake to allow ->* overloading in the first place, it
>> > should
>> > have followed ->).
>>
>> I don't think that the core language should impose such restrictions.
>> Coders can design classes with funny behavior, they can override unary
>> operator&, comma operator, etc. In many cases you won't do that, so
>> don't. What looks strange for you at the moment might be useful for
>> someone in another context. Why should we restrict them in doing so?
>>
>> Keep also in mind that the same kind of problems can occur for funny
>> smart pointers that override operator-> which does return something
>> inconsistent with operator*. I don't think that just by restricting
>> core language rules this would help to solve such problems. Think
>> further and you want that operator+=3D and operator+ are enforced to do
>> the equivalent things. Where do you want to stop?
>>
>> - Daniel
>>
>
> We could, however, add some =3Ddefault magic (or whatever) that generates=
 +=3D
> given +, and maybe ->* given ->, and the relational operators, etc.

Sure, similar ideas had been brought up in regard for possible
defaulting of comparison functions.

- Daniel

--=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/?hl=3Den.



.