Topic: A new stab at getting operator.() functionality: Via


Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Thu, 18 Oct 2018 19:38:27 -0700 (PDT)
Raw View
------=_Part_3466_572498352.1539916707195
Content-Type: multipart/alternative;
 boundary="----=_Part_3467_552138767.1539916707196"

------=_Part_3467_552138767.1539916707196
Content-Type: text/plain; charset="UTF-8"

There have been multiple attempts at being able to write a general Wrapper
class without having to explicitly write forwarding versions of each method
in the Wrapped class.

The obvious idea would be to allow operator.() to be overridden, but so far
this road has been blocked by difficulties in how to handle collisions
between method names in Wrapper and Wrapped.

Another attempt has been to introduce an idea of inheritance by reference
or indirect inheritance. This was shot down for philosophical reasons with
the sentiment that the Wrapper does not represent a "is-a" relationship to
the Wrapped object. Otherwise this has the nice property of inheriting(!)
the rules of method hiding from regular inheritance: Any declaration in the
"subclass" i.e. Wrapper hides the corresponding name in the "base class",
i.e. Wrapped class. This can be overridden by using Wrapped::<name>
notation as for any inheritance.

This post is a third attempt at solving this problem: Redefine the lookup
rules for cast operators. Currently cast operators are attempted to be able
to pass an object as function parameter. So in the above example a Wrapper
object can be passed to a function taking a Wrapped parameter, invoking the
cast operator. However, this does not happen for an object where a member
is to be accessed, so if Wrapped has a method a you can't invoke a on a
Wrapper. This proposal is to change this so that if no method a is found in
Wrapper a search is done in Wrapped also.

Here is a simple example:


struct A {
    void a();
};

class B {
public:
    operator A&() { return m_a; }

private:
    A m_a;
};

void fun(A& a)
{
}

int main()
{
   B b;
   fun(b); // Works by invoking the cast operator.
   b.a();   // Currently an error, but works with this proposal.
}

The problem of a class with multiple cast operators causing possible
ambiguity should be solved according to the same rules as for multiple
inheritance. Disambiguation can however not be performed using the Class::
syntax as we are not inheriting. Instead static_cast<A&>(b).a() would be
the way to explicitly invoke the cast operator and thus tell the compiler
which instance of a named entity to use.

I think the use cases and motivation for this proposal are well established
as it solves the same problems that operator.() was addressing. The
interesting question is whether there are backwards compatibility issues or
confusion created by introducing this feature into the language.



--
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/a195e287-a40b-458c-88be-e281c92e595d%40isocpp.org.

------=_Part_3467_552138767.1539916707196
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">There have been multiple attempts at being able to write a=
 general Wrapper class without having to explicitly write forwarding versio=
ns of each method in the Wrapped class.=C2=A0<div><br></div><div>The obviou=
s idea would be to allow operator.() to be overridden, but so far this road=
 has been blocked by difficulties in how to handle collisions between metho=
d names in Wrapper and Wrapped.</div><div><br></div><div>Another attempt ha=
s been to introduce an idea of inheritance by reference or indirect inherit=
ance. This was shot down for philosophical reasons with the sentiment that =
the Wrapper does not represent a &quot;is-a&quot; relationship to the Wrapp=
ed object. Otherwise this has the nice property of inheriting(!) the rules =
of method hiding from regular inheritance: Any declaration in the &quot;sub=
class&quot; i.e. Wrapper hides the corresponding name in the &quot;base cla=
ss&quot;, i.e. Wrapped class. This can be overridden by using Wrapped::&lt;=
name&gt; notation as for any inheritance.</div><div><br></div><div>This pos=
t is a third attempt at solving this problem: Redefine the lookup rules for=
 cast operators. Currently cast operators are attempted to be able to pass =
an object as function parameter. So in the above example a Wrapper object c=
an be passed to a function taking a Wrapped parameter, invoking the cast op=
erator. However, this does not happen for an object where a member is to be=
 accessed, so if Wrapped has a method a you can&#39;t invoke a on a Wrapper=
.. This proposal is to change this so that if no method a is found in Wrappe=
r a search is done in Wrapped also.</div><div><br></div><div>Here is a simp=
le example:</div><div><br></div><div><div style=3D"color: #000000;backgroun=
d-color: #fffffe;font-family: Consolas, " liberation=3D"" mono",=3D"" couri=
er,=3D"" monospace;font-weight:=3D"" normal;font-size:=3D"" 14px;line-heigh=
t:=3D"" 19px;white-space:=3D"" pre;"=3D""><br><div><span style=3D"color: #0=
000ff;">struct</span> A {</div><div>    <span style=3D"color: #0000ff;">=C2=
=A0 =C2=A0 void</span> a();</div><div>};</div><br><div><span style=3D"color=
: #0000ff;">class</span> B {</div><div><span style=3D"color: #0000ff;">publ=
ic</span>:</div><div>    <span style=3D"color: #0000ff;">=C2=A0 =C2=A0 oper=
ator</span> A&amp;() { <span style=3D"color: #0000ff;">return</span> m_a; }=
</div><br><div><span style=3D"color: #0000ff;">private</span>:</div><div>=
=C2=A0 =C2=A0 A m_a;</div><div>};</div><div><br></div><div><div liberation=
=3D"" mono",=3D"" courier,=3D"" monospace;font-weight:=3D"" normal;font-siz=
e:=3D"" 14px;line-height:=3D"" 19px;white-space:=3D"" pre;"=3D""><span styl=
e=3D"color: #0000ff;">void</span> fun(A&amp; a)=C2=A0</div><div liberation=
=3D"" mono",=3D"" courier,=3D"" monospace;font-weight:=3D"" normal;font-siz=
e:=3D"" 14px;line-height:=3D"" 19px;white-space:=3D"" pre;"=3D"">{</div><di=
v liberation=3D"" mono",=3D"" courier,=3D"" monospace;font-weight:=3D"" nor=
mal;font-size:=3D"" 14px;line-height:=3D"" 19px;white-space:=3D"" pre;"=3D"=
">}</div></div><div><br></div><div>int main()</div><div>{</div><div>=C2=A0 =
=C2=A0B b;</div><div>=C2=A0 =C2=A0fun(b); // Works by invoking the cast ope=
rator.</div><div>=C2=A0 =C2=A0b.a();=C2=A0 =C2=A0// Currently an error, but=
 works with this proposal.</div><div>}</div><div><br></div><div>The problem=
 of a class with multiple cast operators causing possible ambiguity should =
be solved according to the same rules as for multiple inheritance. Disambig=
uation can however not be performed using the Class:: syntax as we are not =
inheriting. Instead static_cast&lt;A&amp;&gt;(b).a() would be the way to ex=
plicitly invoke the cast operator and thus tell the compiler which instance=
 of a named entity to use.</div><div><br></div><div>I think the use cases a=
nd motivation for this proposal are well established as it solves the same =
problems that operator.() was addressing. The interesting question is wheth=
er there are backwards compatibility issues or confusion created by introdu=
cing this feature into the language.</div></div></div><div><br></div><div><=
br></div><div><br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/a195e287-a40b-458c-88be-e281c92e595d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/a195e287-a40b-458c-88be-e281c92e595d=
%40isocpp.org</a>.<br />

------=_Part_3467_552138767.1539916707196--

------=_Part_3466_572498352.1539916707195--

.