Topic: Does unified call syntax make operator.() unnecessary?


Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Tue, 28 Jul 2015 17:00:26 -0700 (PDT)
Raw View
------=_Part_2693_219879252.1438128026364
Content-Type: multipart/alternative;
 boundary="----=_Part_2694_1623643750.1438128026364"

------=_Part_2694_1623643750.1438128026364
Content-Type: text/plain; charset=UTF-8

I recently read the proposal for operator.() (
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4495.html) and
afterwads it struck me that
with the suggested automatic rewrite of a.b(c) to b(a, c) suggested in (
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4474.pdf) an
operator.() may be unnecessary:

If a.b(c) does not find any eligible function to call unified call rewrites
it to b(a, c) and then any non-explicit cast operator to whatever the
"smart reference" refers to is used during lookup. So instead of
implementing operator.() we only need a classic non-explicit cast operator
to the refered type. The case of deferring different methods to different
referred objects would be covered by having multiple cast operators, and
the current lookup rules do the rest!

I know this idea is not complete as it does not handle member access case
but I thought it was interesting enough to mention. An additional rule when
looking up the member access a.b fails could be to try user defined
conversion targets of a to find b. This seems to be just as backwards
compatible as
the unified call proposal in general.

Even if this turns out to be a dead end I think the proposals should
mention how they intereact with each other. User defined operator.() is not
mentioned at all in the unified call paper. I think there may be
interactions there worth investigating.

The unified call paper also does not mention virtual methods, I think it
should be defined how this works when rewriting from function to method
call style.

Bengt


--

---
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_2694_1623643750.1438128026364
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I recently read the proposal for operator.() (<a href=3D"h=
ttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4495.html">http://w=
ww.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4495.html</a>) and afterwa=
ds it struck me that<div>with the suggested automatic rewrite of a.b(c) to =
b(a, c) suggested in (<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/doc=
s/papers/2015/n4474.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers=
/2015/n4474.pdf</a>) an operator.() may be unnecessary:</div><div><br></div=
><div>If a.b(c) does not find any eligible function to call unified call re=
writes it to b(a, c) and then any non-explicit cast operator to whatever th=
e &quot;smart reference&quot; refers to is used during lookup. So instead o=
f</div><div>implementing operator.() we only need a classic non-explicit ca=
st operator to the refered type. The case of deferring different methods to=
 different referred objects would be covered by having multiple cast operat=
ors, and the current lookup rules do the rest!</div><div><br></div><div>I k=
now this idea is not complete as it does not handle member access case but =
I thought it was interesting enough to mention. An additional rule when loo=
king up the member access a.b fails could be to try user defined conversion=
 targets of a to find b. This seems to be just as backwards compatible as</=
div><div>the unified call proposal in general.</div><div><br></div><div>Eve=
n if this turns out to be a dead end I think the proposals should mention h=
ow they intereact with each other. User defined operator.() is not mentione=
d at all in the unified call paper. I think there may be interactions there=
 worth investigating.</div><div><br></div><div>The unified call paper also =
does not mention virtual methods, I think it should be defined how this wor=
ks when rewriting from function to method call style.</div><div><br></div><=
div>Bengt</div><div><br></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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
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_2694_1623643750.1438128026364--
------=_Part_2693_219879252.1438128026364--

.


Author: Faisal Vali <faisalv@gmail.com>
Date: Tue, 28 Jul 2015 21:37:04 -0500
Raw View
On Tue, Jul 28, 2015 at 7:00 PM, Bengt Gustafsson
<bengt.gustafsson@beamways.com> wrote:
> I recently read the proposal for operator.()
> (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4495.html) and
> afterwads it struck me that
> with the suggested automatic rewrite of a.b(c) to b(a, c) suggested in
> (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4474.pdf) an
> operator.() may be unnecessary:
>
> If a.b(c) does not find any eligible function to call unified call rewrites
> it to b(a, c) and then any non-explicit cast operator to whatever the "smart
> reference" refers to is used during lookup. So instead of
> implementing operator.() we only need a classic non-explicit cast operator
> to the refered type.
> The case of deferring different methods to different
> referred objects would be covered by having multiple cast operators, and the
> current lookup rules do the rest!
>

I'm not sure I understand - could you elaborate how this would work
with pseudo-code...

template<class T> struct Ref {
  ...
  operator T&() { return *this; }
};
Ref<A> ra;
ra.f();
ra.g();

How does UFC (unified-function-call) let you forward f and g, without
having to write non-member f's and g's - unless you had followed that
convention for all operations on A to begin with...

What am i missing?

> I know this idea is not complete as it does not handle member access case
> but I thought it was interesting enough to mention. An additional rule when
> looking up the member access a.b fails could be to try user defined
> conversion targets of a to find b. This seems to be just as backwards
> compatible as
> the unified call proposal in general.
>
> Even if this turns out to be a dead end I think the proposals should mention
> how they intereact with each other. User defined operator.() is not
> mentioned at all in the unified call paper. I think there may be
> interactions there worth investigating.

I believe the interactions are at least touched upon in N4477 section
4.7 for Bjarne and Gabby's proposal (if not in Mathias's).
Essentially if calling the chain of operator dots and applying the
member syntax to the resulting type of the dot operator fails, then
transpose/rewrite the call (is how i understand it) [Hmm, now that I
think about it, that's not how I implemented UFC for the overloaded
arrow operator, but that's easily fixable].

In regards to Mathias's proposal (N4495), if a class provides a dot
operator template, sans any SFINAE constraints placed upon it it may
never fail the resolution process (it might fail during instantiation
of the dot operator template, but that would be too late to trigger
the rewrite of the call expression).  If it SFINAE's out, then I would
expect the rewrite to occur.

>
> The unified call paper also does not mention virtual methods, I think it
> should be defined how this works when rewriting from function to method call
> style.
>

I'm not sure I see the issue here - could you please elaborate?

I assumed for a call written as
  pB->fun();
Either that call is well-formed (and if so, if the function is virtual
the call is too), and if not, the non-member syntax is attempted and
if fun(pB) is valid then it gets called (and obviously that call being
a non-member call is non-virtual).

-faisal

--

---
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: Faisal Vali <faisalv@gmail.com>
Date: Tue, 28 Jul 2015 21:47:01 -0500
Raw View
On Tue, Jul 28, 2015 at 9:37 PM, Faisal Vali <faisalv@gmail.com> wrote:
> On Tue, Jul 28, 2015 at 7:00 PM, Bengt Gustafsson
> <bengt.gustafsson@beamways.com> wrote:
>> I recently read the proposal for operator.()
>> (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4495.html) and
>> afterwads it struck me that
>> with the suggested automatic rewrite of a.b(c) to b(a, c) suggested in
>> (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4474.pdf) an
>> operator.() may be unnecessary:
>>
>> If a.b(c) does not find any eligible function to call unified call rewrites
>> it to b(a, c) and then any non-explicit cast operator to whatever the "smart
>> reference" refers to is used during lookup. So instead of
>> implementing operator.() we only need a classic non-explicit cast operator
>> to the refered type.
>> The case of deferring different methods to different
>> referred objects would be covered by having multiple cast operators, and the
>> current lookup rules do the rest!
>>
>
> I'm not sure I understand - could you elaborate how this would work
> with pseudo-code...
>
> template<class T> struct Ref {
>   ...
>   operator T&() { return *this; }
> };
> Ref<A> ra;
> ra.f();
> ra.g();
>
> How does UFC (unified-function-call) let you forward f and g, without
> having to write non-member f's and g's - unless you had followed that
> convention for all operations on A to begin with...
>
> What am i missing?
>
>> I know this idea is not complete as it does not handle member access case
>> but I thought it was interesting enough to mention. An additional rule when
>> looking up the member access a.b fails could be to try user defined
>> conversion targets of a to find b. This seems to be just as backwards
>> compatible as
>> the unified call proposal in general.
>>
>> Even if this turns out to be a dead end I think the proposals should mention
>> how they intereact with each other. User defined operator.() is not
>> mentioned at all in the unified call paper. I think there may be
>> interactions there worth investigating.
>
> I believe the interactions are at least touched upon in N4477 section
> 4.7 for Bjarne and Gabby's proposal (if not in Mathias's).
> Essentially if calling the chain of operator dots and applying the
> member syntax to the resulting type of the dot operator fails, then
> transpose/rewrite the call (is how i understand it) [Hmm, now that I
> think about it, that's not how I implemented UFC for the overloaded
> arrow operator, but that's easily fixable].
>
> In regards to Mathias's proposal (N4495), if a class provides a dot
> operator template, sans any SFINAE constraints placed upon it it may
> never fail the resolution process (it might fail during instantiation
> of the dot operator template, but that would be too late to trigger
> the rewrite of the call expression).  If it SFINAE's out, then I would
> expect the rewrite to occur.
>
>>
>> The unified call paper also does not mention virtual methods, I think it
>> should be defined how this works when rewriting from function to method call
>> style.
>>
>
> I'm not sure I see the issue here - could you please elaborate?
>
> I assumed for a call written as
>   pB->fun();
> Either that call is well-formed (and if so, if the function is virtual
> the call is too), and if not, the non-member syntax is attempted and
> if fun(pB) is valid then it gets called (and obviously that call being
> a non-member call is non-virtual).
>

Sorry, I just noticed you asked about going from non-member to member
syntax. For that I would expect the following:
First try fun(pB) (for option 4 in Bjarne & Herb's UFC paper) and if
that fails then try pB->fun() and if fun is a virtual function, the
call is too.
(or first try pB->fun() for option 6).

--

---
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: David Krauss <potswa@gmail.com>
Date: Wed, 29 Jul 2015 11:02:40 +0800
Raw View
--Apple-Mail=_8D53270F-D082-4512-A9CF-288FC89EFA21
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8


> On 2015=E2=80=9307=E2=80=9329, at 8:00 AM, Bengt Gustafsson <bengt.gustaf=
sson@beamways.com> wrote:
>=20
> I recently read the proposal for operator.() (http://www.open-std.org/jtc=
1/sc22/wg21/docs/papers/2015/n4495.html <http://www.open-std.org/jtc1/sc22/=
wg21/docs/papers/2015/n4495.html>) and afterwads it struck me that
> with the suggested automatic rewrite of a.b(c) to b(a, c) suggested in (h=
ttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4474.pdf <http://ww=
w.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4474.pdf>) an operator.() m=
ay be unnecessary:

Unified call syntax helps if you have free functions but want to use =E2=80=
=9Cobject-oriented=E2=80=9D notation. The proposal mentions doing the oppos=
ite, but that=E2=80=99s not included. (I personally think it=E2=80=99s dang=
erous to second-guess the declared interface to any such degree.)

Operator dot helps if you have a pointer but you want to use it syntactical=
ly as its referent.

> If a.b(c) does not find any eligible function to call unified call rewrit=
es it to b(a, c) and then any non-explicit cast operator to whatever the "s=
mart reference" refers to is used during lookup. So instead of
> implementing operator.() we only need a classic non-explicit cast operato=
r to the refered type. The case of deferring different methods to different=
 referred objects would be covered by having multiple cast operators, and t=
he current lookup rules do the rest!

That only works if all the members are declared as non-members, which is a =
non-starter.

What about things that aren=E2=80=99t a.b(c)? It sounds like the more strai=
ghtforward solution is to use implicit conversions as a fallback to failed =
member name lookup. (Ah, you mention this below.) This is a simple solution=
.. It=E2=80=99s not actually mentioned in N4173, but it seems to be discarde=
d as lacking access control. However, I think the access control arguments =
in N4173 are bunk:

1. The user can get a reference by calling operator.() explicitly.
2. If the referent type is supposed to be inaccessible, the user should not=
 have an accessible name for it. Then they cannot even call the conversion =
function explicitly.
3. If the referent type is private, then public interfaces shouldn=E2=80=99=
t mention it. N4173 =C2=A74.6 is presupposing poor interface design.

Compared to lookup fallback to conversion functions (with no opt-in), opera=
tor. is essentially equivalent except for leakier access. Its access protec=
tion only works if access was already leaked, which seems contrary to the u=
ser=E2=80=99s intentions.

By the way, you=E2=80=99ve just explained why unified call syntax is a brea=
king change with the potential to generate problems that would take days to=
 debug. Corner cases like user-defined conversions, deduced types, and virt=
ual functions should be scrutinized as the proposal is fleshed out. (And th=
ose aren=E2=80=99t really corner cases at all, so I am amazed that the prop=
osal wasn=E2=80=99t DOA.)

> I know this idea is not complete as it does not handle member access case=
 but I thought it was interesting enough to mention. An additional rule whe=
n looking up the member access a.b fails could be to try user defined conve=
rsion targets of a to find b. This seems to be just as backwards compatible=
 as
> the unified call proposal in general.
>=20
> Even if this turns out to be a dead end I think the proposals should ment=
ion how they intereact with each other. User defined operator.() is not men=
tioned at all in the unified call paper. I think there may be interactions =
there worth investigating.
>=20
> The unified call paper also does not mention virtual methods, I think it =
should be defined how this works when rewriting from function to method cal=
l style.
>=20
> Bengt

--=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=_8D53270F-D082-4512-A9CF-288FC89EFA21
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""><div class=3D""><b=
r class=3D""></div><div><blockquote type=3D"cite" class=3D""><div class=3D"=
">On 2015=E2=80=9307=E2=80=9329, at 8:00 AM, Bengt Gustafsson &lt;<a href=
=3D"mailto:bengt.gustafsson@beamways.com" class=3D"">bengt.gustafsson@beamw=
ays.com</a>&gt; wrote:</div><br class=3D"Apple-interchange-newline"><div cl=
ass=3D""><div dir=3D"ltr" class=3D"">I recently read the proposal for opera=
tor.() (<a href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/=
n4495.html" class=3D"">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2=
015/n4495.html</a>) and afterwads it struck me that<div class=3D"">with the=
 suggested automatic rewrite of a.b(c) to b(a, c) suggested in (<a href=3D"=
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4474.pdf" class=3D=
"">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4474.pdf</a>) a=
n operator.() may be unnecessary:</div><div class=3D""></div></div></div></=
blockquote><div><br class=3D""></div><div class=3D"">Unified call syntax he=
lps if you have free functions but want to use =E2=80=9Cobject-oriented=E2=
=80=9D notation. The proposal mentions doing the opposite, but that=E2=80=
=99s not included. (I personally think it=E2=80=99s dangerous to second-gue=
ss the declared interface to any such degree.)</div><div class=3D""><br cla=
ss=3D""></div><div class=3D"">Operator dot helps if you have a pointer but =
you want to use it syntactically as its referent.</div><div class=3D""><br =
class=3D""></div><blockquote type=3D"cite" class=3D""><div class=3D""><div =
dir=3D"ltr" class=3D""><div class=3D"">If a.b(c) does not find any eligible=
 function to call unified call rewrites it to b(a, c) and then any non-expl=
icit cast operator to whatever the "smart reference" refers to is used duri=
ng lookup. So instead of</div><div class=3D"">implementing operator.() we o=
nly need a classic non-explicit cast operator to the refered type. The case=
 of deferring different methods to different referred objects would be cove=
red by having multiple cast operators, and the current lookup rules do the =
rest!</div><div class=3D""></div></div></div></blockquote><div><br class=3D=
""></div><div>That only works if all the members are declared as non-member=
s, which is a non-starter.</div><div><br class=3D""></div><div>What about t=
hings that aren=E2=80=99t <font face=3D"Courier" class=3D"">a.b(c)</font>? =
It sounds like the more straightforward solution is to use implicit convers=
ions as a fallback to failed member name lookup. (Ah, you mention this belo=
w.) This is a simple solution. It=E2=80=99s not actually mentioned in N4173=
, but it seems to be discarded as lacking access control. However, I think =
the access control arguments in N4173 are bunk:</div><div><br class=3D""></=
div><div>1. The user can get a reference by calling <font face=3D"Courier" =
class=3D"">operator.()</font> explicitly.</div><div>2. If the referent type=
 is supposed to be inaccessible, the user should not have an accessible nam=
e for it. Then they cannot even call the conversion function explicitly.</d=
iv><div>3. If the referent type is private, then public interfaces shouldn=
=E2=80=99t mention it. N4173 =C2=A74.6 is presupposing poor interface desig=
n.</div><div><br class=3D""></div><div>Compared to lookup fallback to conve=
rsion functions (with no opt-in), <font face=3D"Courier" class=3D"">operato=
r.</font> is essentially equivalent except for leakier access. Its access p=
rotection only works if access was already leaked, which seems contrary to =
the user=E2=80=99s intentions.</div><div><br class=3D""></div><div>By the w=
ay, you=E2=80=99ve just explained why unified call syntax is a breaking cha=
nge with the potential to generate problems that would take days to debug. =
Corner cases like user-defined conversions, deduced types, and virtual func=
tions should be scrutinized as the proposal is fleshed out. (And those aren=
=E2=80=99t really corner cases at all, so I am amazed that the proposal was=
n=E2=80=99t DOA.)</div><br class=3D""><blockquote type=3D"cite" class=3D"">=
<div class=3D""><div dir=3D"ltr" class=3D""><div class=3D"">I know this ide=
a is not complete as it does not handle member access case but I thought it=
 was interesting enough to mention. An additional rule when looking up the =
member access a.b fails could be to try user defined conversion targets of =
a to find b. This seems to be just as backwards compatible as</div><div cla=
ss=3D"">the unified call proposal in general.</div><div class=3D""><br clas=
s=3D""></div><div class=3D"">Even if this turns out to be a dead end I thin=
k the proposals should mention how they intereact with each other. User def=
ined operator.() is not mentioned at all in the unified call paper. I think=
 there may be interactions there worth investigating.</div><div class=3D"">=
<br class=3D""></div><div class=3D"">The unified call paper also does not m=
ention virtual methods, I think it should be defined how this works when re=
writing from function to method call style.</div><div class=3D""><br class=
=3D""></div><div class=3D"">Bengt</div></div></div></blockquote></div><br c=
lass=3D""></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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
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=_8D53270F-D082-4512-A9CF-288FC89EFA21--

.


Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Wed, 29 Jul 2015 04:00:05 -0700 (PDT)
Raw View
------=_Part_282_16952152.1438167605993
Content-Type: multipart/alternative;
 boundary="----=_Part_283_40730229.1438167605993"

------=_Part_283_40730229.1438167605993
Content-Type: text/plain; charset=UTF-8

Faisalv: You are right, I should have made a full example, then I would
have detected the fatal flaw in my idea. To make it "work" you would have
to transform the result back to dot notation after converting the first
argument, which is a very awkward notion.

On the other hand operator.() could still be implemented via cast operators
with a new language rule:

- If processing of . or -> fails a cast operator on the lhs can be applied
and then the lookup retried. (If there are multiple cast operators where
this lookup succeds the program is ill-formed).

Note that this rule can be seen as an extension to the current rules where
upcasts are used to find members. In fact it orthogonalizes the treatment
of the lhs operand of -> and . with other function parameters from a user
perspective.

I guess this rule could have been a replacement for operator->()
overloading if it had been in place back then, but now that we have
operator-> overloading the question is how such a rule change would play
with such user defined operators? I don't see a problem there: Initially
and after each tentative application of a cast operator any operator->
overload on the current lhs type is considered just as today.

I should mention my initial motivation for looking at this at all: With the
current idea of operator.() overloading in N4495 you still can't use the
smart reference (or whatever) as an operand to an operator or as a function
parameter requiring the referred type. To do that you have to have a cast
operator in parallel to the dot operator.

I now noted that there are two competing(?) operator.() proposal, at least
the author list lacks common names. In N4477 in chapter 4.7  at the center
of page 12 (
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4477.pdf) it is
mentioned that thanks to operator.() you can write:

struct S {
  int& operator.() {return a; }
  int a;
};

S s {7};

++s; // ++s.operator.() that is ++s.a


this seems to have used operator.() as a conversion operator. It is
possible that N4477 has a special rule for this, I'm pretty sure N4495
doesn't.

Thus we have three ideas for the smart reference use case:

N4495: You need both operator.() and cast operator to cover member
reference and parameter value use cases.

N4477: operator.() acts as a cast operator when necessary (at least when an
operator is applied).

Idea above: cast operator is applied when needed to make a member
access/method call valid. There is no need for operator.() overloading.


I get an eerie feeling about the interaction risks with these two proposals
together as they both rely on doing something only when normal lookup
fails, which is a novel concept in itself. The obvious contention point is:
If there is an operator.() AND a rewrite according to unified calling finds
a free function, what happens? I think operator.() should be tried first,
but this definitely has to be defined, and it will complicate parsing.




Den onsdag 29 juli 2015 kl. 02:00:26 UTC+2 skrev Bengt Gustafsson:
>
> I recently read the proposal for operator.() (
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4495.html) and
> afterwads it struck me that
> with the suggested automatic rewrite of a.b(c) to b(a, c) suggested in (
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4474.pdf) an
> operator.() may be unnecessary:
>
> If a.b(c) does not find any eligible function to call unified call
> rewrites it to b(a, c) and then any non-explicit cast operator to whatever
> the "smart reference" refers to is used during lookup. So instead of
> implementing operator.() we only need a classic non-explicit cast operator
> to the refered type. The case of deferring different methods to different
> referred objects would be covered by having multiple cast operators, and
> the current lookup rules do the rest!
>
> I know this idea is not complete as it does not handle member access case
> but I thought it was interesting enough to mention. An additional rule when
> looking up the member access a.b fails could be to try user defined
> conversion targets of a to find b. This seems to be just as backwards
> compatible as
> the unified call proposal in general.
>
> Even if this turns out to be a dead end I think the proposals should
> mention how they intereact with each other. User defined operator.() is not
> mentioned at all in the unified call paper. I think there may be
> interactions there worth investigating.
>
> The unified call paper also does not mention virtual methods, I think it
> should be defined how this works when rewriting from function to method
> call style.
>
> Bengt
>
>
>

--

---
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_283_40730229.1438167605993
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Faisalv: You are right, I should have made a full example,=
 then I would have detected the fatal flaw in my idea. To make it &quot;wor=
k&quot; you would have to transform the result back to dot notation after c=
onverting the first argument, which is a very awkward notion.<div><br></div=
><div>On the other hand operator.() could still be implemented via cast ope=
rators with a new language rule:</div><div><br></div><div>- If processing o=
f . or -&gt; fails a cast operator on the lhs can be applied and then the l=
ookup retried. (If there are multiple cast operators where this lookup succ=
eds the program is ill-formed).</div><div><br></div><div>Note that this rul=
e can be seen as an extension to the current rules where upcasts are used t=
o find members. In fact it orthogonalizes the treatment of the lhs operand =
of -&gt; and . with other function parameters from a user perspective.</div=
><div><br></div><div>I guess this rule could have been a replacement for op=
erator-&gt;() overloading if it had been in place back then, but now that w=
e have operator-&gt; overloading the question is how such a rule change wou=
ld play with such user defined operators? I don&#39;t see a problem there: =
Initially and after each tentative application of a cast operator any opera=
tor-&gt; overload on the current lhs type is considered just as today.</div=
><div><br></div><div>I should mention my initial motivation for looking at =
this at all: With the current idea of operator.() overloading in N4495 you =
still can&#39;t use the smart reference (or whatever) as an operand to an o=
perator or as a function parameter requiring the referred type. To do that =
you have to have a cast operator in parallel to the dot operator.</div><div=
><br></div><div>I now noted that there are two competing(?) operator.() pro=
posal, at least the author list lacks common names. In N4477 in chapter 4.7=
 =C2=A0at the center of page 12 (<a href=3D"http://www.open-std.org/jtc1/sc=
22/wg21/docs/papers/2015/n4477.pdf">http://www.open-std.org/jtc1/sc22/wg21/=
docs/papers/2015/n4477.pdf</a>) it is mentioned that thanks to operator.() =
you can write:</div><div><br></div><div class=3D"prettyprint" style=3D"bord=
er: 1px solid rgb(187, 187, 187); word-wrap: break-word; background-color: =
rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subprettypri=
nt"><span style=3D"color: #008;" class=3D"styled-by-prettify">struct</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"> <br>=C2=A0 </span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #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"sty=
led-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">{</span><span style=3D"color: #008;" class=3D"styled-by-prettify">r=
eturn</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> a</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> <br>=C2=A0 </span><span style=3D"color:=
 #008;" class=3D"styled-by-prettify">int</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> a</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> <br></span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">};</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> <br><br>S s </span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">{</span><span style=3D"color: #066;" class=3D"styled-by-prettify">7</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">};</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> =C2=A0 =C2=A0<br><br=
></span><span style=3D"color: #660;" class=3D"styled-by-prettify">++</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">s</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;=
" class=3D"styled-by-prettify">// ++s.operator.() that is ++s.a</span></div=
></code></div><div><br><br></div><div>this seems to have used operator.() a=
s a conversion operator. It is possible that N4477 has a special rule for t=
his, I&#39;m pretty sure N4495 doesn&#39;t.<br></div><div><br></div><div>Th=
us we have three ideas for the smart reference use case:</div><div><br></di=
v><div>N4495: You need both operator.() and cast operator to cover member r=
eference and parameter value use cases.</div><div><br></div><div>N4477: ope=
rator.() acts as a cast operator when necessary (at least when an operator =
is applied).</div><div><br></div><div>Idea above: cast operator is applied =
when needed to make a member access/method call valid. There is no need for=
 operator.() overloading.</div><div><br></div><div><br></div><div>I get an =
eerie feeling about the interaction risks with these two proposals together=
 as they both rely on doing something only when normal lookup fails, which =
is a novel concept in itself. The obvious contention point is: If there is =
an operator.() AND a rewrite according to unified calling finds a free func=
tion, what happens? I think operator.() should be tried first, but this def=
initely has to be defined, and it will complicate parsing.</div><div><br></=
div><div><br></div><div><br><br>Den onsdag 29 juli 2015 kl. 02:00:26 UTC+2 =
skrev Bengt Gustafsson:<blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div di=
r=3D"ltr">I recently read the proposal for operator.() (<a href=3D"http://w=
ww.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4495.html" target=3D"_blan=
k" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;http://www.google.com/u=
rl?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2=
F2015%2Fn4495.html\46sa\75D\46sntz\0751\46usg\75AFQjCNFXthbk0wV6QK42MDtBcEE=
qxSZM6w&#39;;return true;" onclick=3D"this.href=3D&#39;http://www.google.co=
m/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpaper=
s%2F2015%2Fn4495.html\46sa\75D\46sntz\0751\46usg\75AFQjCNFXthbk0wV6QK42MDtB=
cEEqxSZM6w&#39;;return true;">http://www.open-std.org/jtc1/sc22/wg21/docs/p=
apers/2015/n4495.html</a>) and afterwads it struck me that<div>with the sug=
gested automatic rewrite of a.b(c) to b(a, c) suggested in (<a href=3D"http=
://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4474.pdf" target=3D"_b=
lank" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;http://www.google.co=
m/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpaper=
s%2F2015%2Fn4474.pdf\46sa\75D\46sntz\0751\46usg\75AFQjCNHFigxJItStW1U7PDXJ6=
n-EiK3h_A&#39;;return true;" onclick=3D"this.href=3D&#39;http://www.google.=
com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpap=
ers%2F2015%2Fn4474.pdf\46sa\75D\46sntz\0751\46usg\75AFQjCNHFigxJItStW1U7PDX=
J6n-EiK3h_A&#39;;return true;">http://www.open-std.org/jtc1/sc22/wg21/docs/=
papers/2015/n4474.pdf</a>) an operator.() may be unnecessary:</div><div><br=
></div><div>If a.b(c) does not find any eligible function to call unified c=
all rewrites it to b(a, c) and then any non-explicit cast operator to whate=
ver the &quot;smart reference&quot; refers to is used during lookup. So ins=
tead of</div><div>implementing operator.() we only need a classic non-expli=
cit cast operator to the refered type. The case of deferring different meth=
ods to different referred objects would be covered by having multiple cast =
operators, and the current lookup rules do the rest!</div><div><br></div><d=
iv>I know this idea is not complete as it does not handle member access cas=
e but I thought it was interesting enough to mention. An additional rule wh=
en looking up the member access a.b fails could be to try user defined conv=
ersion targets of a to find b. This seems to be just as backwards compatibl=
e as</div><div>the unified call proposal in general.</div><div><br></div><d=
iv>Even if this turns out to be a dead end I think the proposals should men=
tion how they intereact with each other. User defined operator.() is not me=
ntioned at all in the unified call paper. I think there may be interactions=
 there worth investigating.</div><div><br></div><div>The unified call paper=
 also does not mention virtual methods, I think it should be defined how th=
is works when rewriting from function to method call style.</div><div><br><=
/div><div>Bengt</div><div><br></div><div><br></div></div></blockquote></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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
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_283_40730229.1438167605993--
------=_Part_282_16952152.1438167605993--

.


Author: Faisal Vali <faisalv@gmail.com>
Date: Wed, 29 Jul 2015 10:33:35 -0500
Raw View
On Wed, Jul 29, 2015 at 6:00 AM, Bengt Gustafsson
<bengt.gustafsson@beamways.com> wrote:
> Faisalv: You are right, I should have made a full example, then I would have
> detected the fatal flaw in my idea. To make it "work" you would have to
> transform the result back to dot notation after converting the first
> argument, which is a very awkward notion.
>
> On the other hand operator.() could still be implemented via cast operators
> with a new language rule:
>
> - If processing of . or -> fails a cast operator on the lhs can be applied
> and then the lookup retried. (If there are multiple cast operators where
> this lookup succeds the program is ill-formed).
>

Yes - I can see why this solution should also be discussed in that context.

> Note that this rule can be seen as an extension to the current rules where
> upcasts are used to find members. In fact it orthogonalizes the treatment of
> the lhs operand of -> and . with other function parameters from a user
> perspective.
>
> I guess this rule could have been a replacement for operator->() overloading
> if it had been in place back then, but now that we have operator->
> overloading the question is how such a rule change would play with such user
> defined operators? I don't see a problem there: Initially and after each
> tentative application of a cast operator any operator-> overload on the
> current lhs type is considered just as today.
>
> I should mention my initial motivation for looking at this at all: With the
> current idea of operator.() overloading in N4495 you still can't use the
> smart reference (or whatever) as an operand to an operator or as a function
> parameter requiring the referred type. To do that you have to have a cast
> operator in parallel to the dot operator.
>

> I now noted that there are two competing(?) operator.() proposal, at least
> the author list lacks common names. In N4477 in chapter 4.7  at the center
> of page 12
> (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4477.pdf) it is
> mentioned that thanks to operator.() you can write:
>
> struct S {
>   int& operator.() {return a; }
>   int a;
> };
>
> S s {7};
>
> ++s; // ++s.operator.() that is ++s.a
>
>
> this seems to have used operator.() as a conversion operator. It is possible
> that N4477 has a special rule for this, I'm pretty sure N4495 doesn't.
>
> Thus we have three ideas for the smart reference use case:
>
> N4495: You need both operator.() and cast operator to cover member reference
> and parameter value use cases.
>
> N4477: operator.() acts as a cast operator when necessary (at least when an
> operator is applied).
>
> Idea above: cast operator is applied when needed to make a member
> access/method call valid. There is no need for operator.() overloading.
>
>
> I get an eerie feeling about the interaction risks with these two proposals
> together as they both rely on doing something only when normal lookup fails,
> which is a novel concept in itself.

UFC doesn't just rewrite if just lookup fails - even if name lookup
succeeds but overload resolution fails or results in a deleted
function or an inaccessible function - I suspect the rewrite attempt
is expected.

> The obvious contention point is: If
> there is an operator.() AND a rewrite according to unified calling finds a
> free function, what happens? I think operator.() should be tried first, but
> this definitely has to be defined, and it will complicate parsing.

It will certainly have to be clearly defined - but I don't believe it
will complicate parsing as much as add overhead to semantic analysis
of the function call as written.   I would not be surprised if these
features made users much more apprehensive about calls getting
silently resolved to "unknown/distant/unintended" functions - but
before panicking to the point of shutting down all discussion (i.e.
DOA) about these features - I would remind discussants that it won't
be too hard for a compiler to implement a flag that tells you if a
call was rewritten and exactly which call it resolved to (or to dump
all overloads that were considered if the call failed to resolve given
dot/arrow overloads and UFC) - which should allay some fears - but I
agree that the introduced complexity (and potential overhead on
compiler performance) should be deemed strongly worth it, before
ratifying these features.

Just my 2 cents.

>
>
>
>
> Den onsdag 29 juli 2015 kl. 02:00:26 UTC+2 skrev Bengt Gustafsson:
>>
>> I recently read the proposal for operator.()
>> (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4495.html) and
>> afterwads it struck me that
>> with the suggested automatic rewrite of a.b(c) to b(a, c) suggested in
>> (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4474.pdf) an
>> operator.() may be unnecessary:
>>
>> If a.b(c) does not find any eligible function to call unified call
>> rewrites it to b(a, c) and then any non-explicit cast operator to whatever
>> the "smart reference" refers to is used during lookup. So instead of
>> implementing operator.() we only need a classic non-explicit cast operator
>> to the refered type. The case of deferring different methods to different
>> referred objects would be covered by having multiple cast operators, and the
>> current lookup rules do the rest!
>>
>> I know this idea is not complete as it does not handle member access case
>> but I thought it was interesting enough to mention. An additional rule when
>> looking up the member access a.b fails could be to try user defined
>> conversion targets of a to find b. This seems to be just as backwards
>> compatible as
>> the unified call proposal in general.
>>
>> Even if this turns out to be a dead end I think the proposals should
>> mention how they intereact with each other. User defined operator.() is not
>> mentioned at all in the unified call paper. I think there may be
>> interactions there worth investigating.
>>
>> The unified call paper also does not mention virtual methods, I think it
>> should be defined how this works when rewriting from function to method call
>> style.
>>
>> Bengt
>>
>>
> --
>
> ---
> 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/.

.