Topic: Static member operator overloads


Author: David Krauss <potswa@gmail.com>
Date: Tue, 29 Jul 2014 10:38:29 +0800
Raw View
--Apple-Mail=_330D2D3E-BFD6-4282-A083-ED89FEAD5429
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1

Most operator overloads ([over.unary], [over.binary]) may be members with t=
he first operand mapping to the implicit argument, or non-members. Since th=
e implicit first argument participates in overload resolution differently (=
user-defined conversions are disabled), non-members are preferred for algeb=
ra-like operators.

It takes a lot of boilerplate to redefine operators for every new class. Fo=
r a type hierarchy conforming to a particular interface, a non-member templ=
ate can provide a generic solution.

template< typename lhs_type, typename rhs_type >
std::enable_if_t< std::is_base_of< hierarchy_base, lhs_type >::value,
lhs_type & > operator +=3D ( lhs_type & lhs, rhs_type && rhs ) {
    lhs.do_add( std::forward< rhs_type >( rhs ) ); // or some algorithm.
    return * this;
}

This idiom lacks scalability: you can only do it once per hierarchy; derive=
d classes which are also bases cannot make their own sub-hierarchy template=
.. It's even worse if the SFINAE is omitted, certain to happen with a non-ex=
pert user.

If the same template were allowed as a static member, it would only be foun=
d in the most immediate base class. More generally, this common use-case wo=
uld also become independent of ADL, which is widely felt to be a minefield.=
 For instance, using declarations would work.

So, why not?

--=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=_330D2D3E-BFD6-4282-A083-ED89FEAD5429
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dwindows-1252"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-=
mode: space; -webkit-line-break: after-white-space;">Most operator overload=
s ([over.unary], [over.binary]) may be members with the first operand mappi=
ng to the implicit argument, or non-members. Since the implicit first argum=
ent participates in overload resolution differently (user-defined conversio=
ns are disabled), non-members are preferred for algebra-like operators.<div=
><br></div><div>It takes a lot of boilerplate to redefine operators for eve=
ry new class. For a type hierarchy conforming to a particular interface, a =
non-member template can provide a generic solution.</div><div><br></div><di=
v><font face=3D"Courier">template&lt; typename lhs_type, typename rhs_type =
&gt;</font></div><div><font face=3D"Courier">std::enable_if_t&lt; std::is_b=
ase_of&lt; hierarchy_base, lhs_type &gt;::value,</font></div><div><font fac=
e=3D"Courier">lhs_type &amp; &gt; operator +=3D ( lhs_type &amp; lhs, rhs_t=
ype &amp;&amp; rhs ) {</font></div><div><font face=3D"Courier">&nbsp; &nbsp=
; lhs.do_add( std::forward&lt; rhs_type &gt;( rhs ) ); // or some algorithm=
..</font></div><div><font face=3D"Courier">&nbsp; &nbsp; return * this;</fon=
t></div><div><font face=3D"Courier">}</font></div><div><br></div><div>This =
idiom lacks scalability: you can only do it once per hierarchy; derived cla=
sses which are also bases cannot make their own sub-hierarchy template. It&=
rsquo;s even worse if the SFINAE is omitted, certain to happen with a non-e=
xpert user.</div><div><br></div><div>If the same template were allowed as a=
 static member, it would only be found in the most immediate base class. Mo=
re generally, this common use-case would also become independent of ADL, wh=
ich is widely felt to be a minefield. For instance, using declarations woul=
d work.</div><div><br></div><div>So, why not?</div><div><br></div></body></=
html>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&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=_330D2D3E-BFD6-4282-A083-ED89FEAD5429--

.


Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Wed, 30 Jul 2014 10:37:29 -0700 (PDT)
Raw View
------=_Part_4397_624855655.1406741849547
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Doesn't this require some kind of change of the ADL rules?

Up to now ADL lookup was in the namespace of the operator parameter's type,=
=20
but now you have to also look inside that type too...

If this is so, would it be possible to extend this change to include method=
=20
parameters of methods of a class? No, that would break code, I guess. It=20
would offer a very nice possibility to reduce redundant typing of the class=
=20
name for instance for enumerator values:


class Class {
    enum Value { A, B };
    Class(Value p);
};


// Now:
Class v(Class::A);


// Then:
Class v(A);


// But:


int A =3D 3;
class Class {
    static int A =3D 17;
    Class(int p);
};


// This changes behaviour:
Class v(A);    // From 3 to 17



I just mentioned this to see if anyone could come up with a clever wording=
=20
to avoid this dilemma or if everyone thought that it is uncommon enough to=
=20
ignore. One way would be to say that the class-scope A is only looked up if=
=20
no global match is found, but this type of logic has been shunned before, I=
=20
guess this could be due to
how parsers are currently designed.



Den tisdagen den 29:e juli 2014 kl. 04:38:39 UTC+2 skrev David Krauss:
>
> Most operator overloads ([over.unary], [over.binary]) may be members with=
=20
> the first operand mapping to the implicit argument, or non-members. Since=
=20
> the implicit first argument participates in overload resolution different=
ly=20
> (user-defined conversions are disabled), non-members are preferred for=20
> algebra-like operators.
>
> It takes a lot of boilerplate to redefine operators for every new class.=
=20
> For a type hierarchy conforming to a particular interface, a non-member=
=20
> template can provide a generic solution.
>
> template< typename lhs_type, typename rhs_type >
> std::enable_if_t< std::is_base_of< hierarchy_base, lhs_type >::value,
> lhs_type & > operator +=3D ( lhs_type & lhs, rhs_type && rhs ) {
>     lhs.do_add( std::forward< rhs_type >( rhs ) ); // or some algorithm.
>     return * this;
> }
>
> This idiom lacks scalability: you can only do it once per hierarchy;=20
> derived classes which are also bases cannot make their own sub-hierarchy=
=20
> template. It=E2=80=99s even worse if the SFINAE is omitted, certain to ha=
ppen with=20
> a non-expert user.
>
> If the same template were allowed as a static member, it would only be=20
> found in the most immediate base class. More generally, this common=20
> use-case would also become independent of ADL, which is widely felt to be=
 a=20
> minefield. For instance, using declarations would work.
>
> So, why not?
>
>

--=20

---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

------=_Part_4397_624855655.1406741849547
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Doesn't this require some kind of change of the ADL rules?=
<div><br></div><div>Up to now ADL lookup was in the namespace of the operat=
or parameter's type, but now you have to also look inside that type too...<=
/div><div><br></div><div>If this is so, would it be possible to extend this=
 change to include method parameters of methods of a class? No, that would =
break code, I guess. It would offer a very nice possibility to reduce redun=
dant typing of the class name for instance for enumerator values:</div><div=
 class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187, 187); word-=
wrap: break-word; background-color: rgb(250, 250, 250);"><code class=3D"pre=
ttyprint"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br><br></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">class</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-=
prettify">Class</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &n=
bsp; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">enum<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #606;" class=3D"styled-by-prettify">Value</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">{</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"> B </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">};</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br>&nbsp; &nbsp; </span><span style=3D"color: #606;" class=3D"styled-by-pr=
ettify">Class</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">(</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Value<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> p</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">};</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br><br><br></span><span style=3D"color: =
#800;" class=3D"styled-by-prettify">// Now:</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #606;" cl=
ass=3D"styled-by-prettify">Class</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> v</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">(</span><span style=3D"color: #606;" class=3D"styled-by-pre=
ttify">Class</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">A</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br><br><br></span><spa=
n style=3D"color: #800;" class=3D"styled-by-prettify">// Then:</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Class</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> v</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">A</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br><br><br></span><span style=3D"color: #800;" class=3D"styled-by-=
prettify">// But:</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br><br><br></span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> A </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #066;" class=3D"styled-by-prettify">3</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">class</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"st=
yled-by-prettify">Class</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&=
nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">static</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</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 s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
066;" class=3D"styled-by-prettify">17</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #606;" cla=
ss=3D"styled-by-prettify">Class</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> p</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">};</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br><br><br></span><span =
style=3D"color: #800;" class=3D"styled-by-prettify">// This changes behavio=
ur:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></s=
pan><span style=3D"color: #606;" class=3D"styled-by-prettify">Class</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> v</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #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"styled-by-prettify"> &nbsp; &nbsp;</span><span style=3D"color: #800;" c=
lass=3D"styled-by-prettify">// From 3 to 17</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br><br></span></div></code></div><div><br=
><br></div><div>I just mentioned this to see if anyone could come up with a=
 clever wording to avoid this dilemma or if everyone thought that it is unc=
ommon enough to ignore. One way would be to say that the class-scope A is o=
nly looked up if no global match is found, but this type of logic has been =
shunned before, I guess this could be due to</div><div>how parsers are curr=
ently designed.</div><div><br></div><div><br><br>Den tisdagen den 29:e juli=
 2014 kl. 04:38:39 UTC+2 skrev David Krauss:<blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div style=3D"word-wrap:break-word">Most operator overloads (=
[over.unary], [over.binary]) may be members with the first operand mapping =
to the implicit argument, or non-members. Since the implicit first argument=
 participates in overload resolution differently (user-defined conversions =
are disabled), non-members are preferred for algebra-like operators.<div><b=
r></div><div>It takes a lot of boilerplate to redefine operators for every =
new class. For a type hierarchy conforming to a particular interface, a non=
-member template can provide a generic solution.</div><div><br></div><div><=
font face=3D"Courier">template&lt; typename lhs_type, typename rhs_type &gt=
;</font></div><div><font face=3D"Courier">std::enable_if_t&lt; std::is_base=
_of&lt; hierarchy_base, lhs_type &gt;::value,</font></div><div><font face=
=3D"Courier">lhs_type &amp; &gt; operator +=3D ( lhs_type &amp; lhs, rhs_ty=
pe &amp;&amp; rhs ) {</font></div><div><font face=3D"Courier">&nbsp; &nbsp;=
 lhs.do_add( std::forward&lt; rhs_type &gt;( rhs ) ); // or some algorithm.=
</font></div><div><font face=3D"Courier">&nbsp; &nbsp; return * this;</font=
></div><div><font face=3D"Courier">}</font></div><div><br></div><div>This i=
diom lacks scalability: you can only do it once per hierarchy; derived clas=
ses which are also bases cannot make their own sub-hierarchy template. It=
=E2=80=99s even worse if the SFINAE is omitted, certain to happen with a no=
n-expert user.</div><div><br></div><div>If the same template were allowed a=
s a static member, it would only be found in the most immediate base class.=
 More generally, this common use-case would also become independent of ADL,=
 which is widely felt to be a minefield. For instance, using declarations w=
ould work.</div><div><br></div><div>So, why not?</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_4397_624855655.1406741849547--

.


Author: David Krauss <potswa@gmail.com>
Date: Thu, 31 Jul 2014 07:09:39 +0800
Raw View
--Apple-Mail=_489E05E7-64D2-4710-BA66-0C06B6F6E47B
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1


On 2014-07-31, at 1:37 AM, Bengt Gustafsson <bengt.gustafsson@beamways.com>=
 wrote:

> Doesn't this require some kind of change of the ADL rules?
>=20
> Up to now ADL lookup was in the namespace of the operator parameter's typ=
e, but now you have to also look inside that type too...

No, ADL only applies to non-members. The static member would be found the s=
ame as a nonstatic member, except with the LHS placed in the argument list =
and the object expression not evaluated.

non-member: a @ b =3D> operator @ ( a, b ) // ADL
nonstatic member: a @ b =3D> a.operator @ ( b ) // no ADL
static member: a @ b =3D> decltype( a )::operator @ ( a, b ) // no ADL

The main motivation is to avoid ADL and prefer a less greedy scoping mechan=
ism. ADL equally finds functions associated with all base classes, which ma=
kes it impossible for derived classes to override features of a base. It fi=
nds functions associated with all template arguments, which requires SFINAE=
 to be precise (a SFINAE condition cannot assume that its operand is in a p=
articular class hierarchy).

ADL overloads (operators or no) are nice when the LHS operand is not actual=
ly of the class type at all, for example, stream inserters/extractors and f=
unctions operating on handles to the class object. Algebra-like operators a=
re very common however and they'd be better served by this proposal.

--=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=_489E05E7-64D2-4710-BA66-0C06B6F6E47B
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dwindows-1252"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-=
mode: space; -webkit-line-break: after-white-space;"><br><div><div>On 2014&=
ndash;07&ndash;31, at 1:37 AM, Bengt Gustafsson &lt;<a href=3D"mailto:bengt=
..gustafsson@beamways.com">bengt.gustafsson@beamways.com</a>&gt; wrote:</div=
><br class=3D"Apple-interchange-newline"><blockquote type=3D"cite"><div dir=
=3D"ltr">Doesn't this require some kind of change of the ADL rules?<div><br=
></div><div>Up to now ADL lookup was in the namespace of the operator param=
eter's type, but now you have to also look inside that type too&hellip;</di=
v></div></blockquote><div><br></div><div>No, ADL only applies to non-member=
s. The static member would be found the same as a nonstatic member, except =
with the LHS placed in the argument list and the object expression not eval=
uated.</div><div><br></div><div>non-member: <font face=3D"Courier">a @ b =
=3D&gt; operator @ ( a, b )</font> // ADL</div><div>nonstatic member: <font=
 face=3D"Courier">a @ b =3D&gt; a.operator @ ( b )</font> // no ADL</div><d=
iv>static member: <font face=3D"Courier">a @ b =3D&gt; decltype( a )::opera=
tor @ ( a, b )</font> // no ADL</div></div><br><div>The main motivation is =
to avoid ADL and prefer a less greedy scoping mechanism. ADL equally finds =
functions associated with all base classes, which makes it impossible for d=
erived classes to override features of a base. It finds functions associate=
d with all template arguments, which requires SFINAE to be precise (a SFINA=
E condition cannot assume that its operand is in a particular class hierarc=
hy).</div><div><br></div><div>ADL overloads (operators or no) are nice when=
 the LHS operand is not actually of the class type at all, for example, str=
eam inserters/extractors and functions operating on handles to the class ob=
ject. Algebra-like operators are very common however and they&rsquo;d be be=
tter served by this proposal.</div><div><br></div></body></html>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&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=_489E05E7-64D2-4710-BA66-0C06B6F6E47B--

.


Author: David Krauss <potswa@gmail.com>
Date: Thu, 31 Jul 2014 07:15:32 +0800
Raw View
--Apple-Mail=_BE64A44A-6F6D-402C-8FAD-663AE335CE87
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1


On 2014-07-31, at 7:09 AM, David Krauss <potswa@gmail.com> wrote:

> static member: a @ b =3D> decltype( a )::operator @ ( a, b ) // no ADL

Hmm, now that I write it that way, I see that this precludes conversions of=
 a because it must be the right type in the first place.

I guess the proposal needs a little more work but ADL is all but off-limits=
.. Another solution would be to try looking in the scope of decltype(b) as w=
ell. Users who really want to to opportunistically convert both operands fr=
om int can go the non-member ADL route.

--=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=_BE64A44A-6F6D-402C-8FAD-663AE335CE87
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dwindows-1252"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-=
mode: space; -webkit-line-break: after-white-space;"><br><div><div>On 2014&=
ndash;07&ndash;31, at 7:09 AM, David Krauss &lt;<a href=3D"mailto:potswa@gm=
ail.com">potswa@gmail.com</a>&gt; wrote:</div><br class=3D"Apple-interchang=
e-newline"><blockquote type=3D"cite"><meta http-equiv=3D"Content-Type" cont=
ent=3D"text/html charset=3Dwindows-1252"><div style=3D"word-wrap: break-wor=
d; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">static=
 member: <font face=3D"Courier">a @ b =3D&gt; decltype( a )::operator @ ( a=
, b )</font> // no ADL</div></blockquote><div><br></div><div>Hmm, now that =
I write it that way, I see that this precludes conversions of a because it =
must be the right type in the first place.</div></div><br><div>I guess the =
proposal needs a little more work but ADL is all but off-limits. Another so=
lution would be to try looking in the scope of <font face=3D"Courier">declt=
ype(b)</font> as well. Users who really want to to opportunistically conver=
t both operands from <font face=3D"Courier">int</font> can go the non-membe=
r ADL route.</div><div><br></div></body></html>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&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=_BE64A44A-6F6D-402C-8FAD-663AE335CE87--

.


Author: =?UTF-8?Q?David_Rodr=C3=ADguez_Ibeas?= <dibeas@ieee.org>
Date: Thu, 31 Jul 2014 00:01:25 -0400
Raw View
--001a11c1db709d4b3d04ff755317
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

I am not completely sure why you want to avoid ADL altogether, combined
with friend functions defined inside the class definition it provides an
interesting mechanism to provide free functions that don't pollute the
namespace. In an example similar to the one you provided you could have:

// CRTP
template <typename T>
class OpForAddable {
     friend T& operator+=3D(T& lhs, T const & rhs) {
         returh lhs.do_add(rhs);
     }
};

struct MyType : OpForAddable<MyType> {
   MyType& do_add(MyType const & rhs);
};

Note that by using CRTP, the above can have a generic implementation for
multiple types without the actual function being a template. The
implication is that compared with the first template implementation you
allow for *conversions* (which seem to be one goal). If you don't want to
allow for those conversions, you can avoid CRTP and move the template to
the friend function (no conversions allowed, closer to your initial version
of 'operator+=3D'. [*]

One clear advantage (personal opinion) is that the lookup rules already
take care of what you were doing with SFINAE (in the case of the template).
Types opt into inheriting from the base, different versions of it could be
present even in the same namespace (for example, I have used this to
provide 'operator>' in terms of 'operator<' in one base, or in terms of a
'compare' function for other types; each type decides how it wants to
define its operators).

Outside of a type hierarchy this can be done in each type to provide a the
operators that pertain to the type. The main pain point here being that the
friend function definition must be inside the class definition (and thus in
the header, against some coding guidelines, implicitly inline=E2=80=A6). Wh=
en using
this approach in the past the friend functions just forwarded to the actual
implementation (similar to the code above, where the operator just calls
'do_add').

   David

[*] The use of templates inside the base (instead of CRTP) is problematic
in other ways, for example, ADL will look inside the associated namespaces
of template arguments, so 'std::vector<MyType>' would find a +=3D that is n=
ot
designed to work with it if the base was:

class OpForAddable {
     template <typename T>
     friend T& operator+=3D(T& lhs, T const & rhs) {
         returh lhs.do_add(rhs);
     }
};



On Wed, Jul 30, 2014 at 7:15 PM, David Krauss <potswa@gmail.com> wrote:

>
> On 2014=E2=80=9307=E2=80=9331, at 7:09 AM, David Krauss <potswa@gmail.com=
> wrote:
>
> static member: a @ b =3D> decltype( a )::operator @ ( a, b ) // no ADL
>
>
> Hmm, now that I write it that way, I see that this precludes conversions
> of a because it must be the right type in the first place.
>
> I guess the proposal needs a little more work but ADL is all but
> off-limits. Another solution would be to try looking in the scope of
> decltype(b) as well. Users who really want to to opportunistically
> convert both operands from int can go the non-member ADL route.
>
>  --
>
> ---
> 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/.
>

--=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/.

--001a11c1db709d4b3d04ff755317
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I am not completely sure why you want to avoid ADL altoget=
her, combined with friend functions defined inside the class definition it =
provides an interesting mechanism to provide free functions that don&#39;t =
pollute the namespace. In an example similar to the one you provided you co=
uld have:<div>
<br></div><div>// CRTP</div><div>template &lt;typename T&gt;</div><div>clas=
s OpForAddable {</div><div>=C2=A0 =C2=A0 =C2=A0friend T&amp; operator+=3D(T=
&amp; lhs, T const &amp; rhs) {<br></div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0returh lhs.do_add(rhs);</div><div>
=C2=A0 =C2=A0 =C2=A0}</div><div>};</div><div><br></div><div>struct MyType :=
 OpForAddable&lt;MyType&gt; {<br></div><div>=C2=A0 =C2=A0MyType&amp; do_add=
(MyType const &amp; rhs);</div><div>};</div><div><br></div><div>Note that b=
y using CRTP, the above can have a generic implementation for multiple type=
s without the actual function being a template. The implication is that com=
pared with the first template implementation you allow for *conversions* (w=
hich seem to be one goal). If you don&#39;t want to allow for those convers=
ions, you can avoid CRTP and move the template to the friend function (no c=
onversions allowed, closer to your initial version of &#39;operator+=3D&#39=
;. [*]</div>
<div><br></div><div>One clear advantage (personal opinion) is that the look=
up rules already take care of what you were doing with SFINAE (in the case =
of the template). Types opt into inheriting from the base, different versio=
ns of it could be present even in the same namespace (for example, I have u=
sed this to provide &#39;operator&gt;&#39; in terms of &#39;operator&lt;&#3=
9; in one base, or in terms of a &#39;compare&#39; function for other types=
; each type decides how it wants to define its operators).</div>
<div><br></div><div>Outside of a type hierarchy this can be done in each ty=
pe to provide a the operators that pertain to the type. The main pain point=
 here being that the friend function definition must be inside the class de=
finition (and thus in the header, against some coding guidelines, implicitl=
y inline=E2=80=A6). When using this approach in the past the friend functio=
ns just forwarded to the actual implementation (similar to the code above, =
where the operator just calls &#39;do_add&#39;).</div>
<div><br></div><div>=C2=A0 =C2=A0David</div><div><br></div><div>[*] The use=
 of templates inside the base (instead of CRTP) is problematic in other way=
s, for example, ADL will look inside the associated namespaces of template =
arguments, so &#39;std::vector&lt;MyType&gt;&#39; would find a +=3D that is=
 not designed to work with it if the base was:</div>
<div><br></div><div><div>class OpForAddable {<br></div><div>=C2=A0 =C2=A0 =
=C2=A0template &lt;typename T&gt;</div><div>=C2=A0 =C2=A0 =C2=A0friend T&am=
p; operator+=3D(T&amp; lhs, T const &amp; rhs) {<br></div><div>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0returh lhs.do_add(rhs);</div><div>
=C2=A0 =C2=A0 =C2=A0}</div><div>};</div></div><div><br></div></div><div cla=
ss=3D"gmail_extra"><br><br><div class=3D"gmail_quote">On Wed, Jul 30, 2014 =
at 7:15 PM, David Krauss <span dir=3D"ltr">&lt;<a href=3D"mailto:potswa@gma=
il.com" target=3D"_blank">potswa@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"><div style=3D"word-wrap:break-word"><br><div=
><div class=3D""><div>On 2014=E2=80=9307=E2=80=9331, at 7:09 AM, David Krau=
ss &lt;<a href=3D"mailto:potswa@gmail.com" target=3D"_blank">potswa@gmail.c=
om</a>&gt; wrote:</div>
<br><blockquote type=3D"cite"><div style=3D"word-wrap:break-word">static me=
mber: <font face=3D"Courier">a @ b =3D&gt; decltype( a )::operator @ ( a, b=
 )</font> // no ADL</div></blockquote><div><br></div></div><div>Hmm, now th=
at I write it that way, I see that this precludes conversions of a because =
it must be the right type in the first place.</div>
</div><br><div>I guess the proposal needs a little more work but ADL is all=
 but off-limits. Another solution would be to try looking in the scope of <=
font face=3D"Courier">decltype(b)</font> as well. Users who really want to =
to opportunistically convert both operands from <font face=3D"Courier">int<=
/font> can go the non-member ADL route.</div>
<div><br></div></div><div class=3D"HOEnZb"><div class=3D"h5">

<p></p>

-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&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" target=3D"_=
blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&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 />

--001a11c1db709d4b3d04ff755317--

.


Author: David Krauss <potswa@gmail.com>
Date: Thu, 31 Jul 2014 15:53:26 +0800
Raw View
--Apple-Mail=_555B46E5-C6E3-4850-9BBD-1A4B2924411C
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1


On 2014-07-31, at 12:01 PM, David Rodr=EDguez Ibeas <dibeas@ieee.org> wrote=
:

> I am not completely sure why you want to avoid ADL altogether, combined w=
ith friend functions defined inside the class definition it provides an int=
eresting mechanism to provide free functions that don't pollute the namespa=
ce.

As members, they do pollute the namespace. They are not found in the namesp=
ace only as long as the enclosing class is not associated with either opera=
nd. All base classes of an associated class are also associated, so the der=
ived class cannot provide its own operator +=3D . The base implementation i=
s final.

> Note that by using CRTP, the above can have a generic implementation for =
multiple types without the actual function being a template.

Hmm, I hadn't considered that. It's certainly a good way to define operator=
 +. It's nice, though, to have only one base class, and not derive classes =
from a stateful "implementation" base plus a CRTP "interface" base, if the =
CRTP part is specific to the other part.

> The implication is that compared with the first template implementation y=
ou allow for *conversions* (which seem to be one goal). If you don't want t=
o allow for those conversions, you can avoid CRTP and move the template to =
the friend function (no conversions allowed, closer to your initial version=
 of 'operator+=3D'. [*]

Well, LHS conversions aren't an issue for operator +=3D. That goal should b=
e dropped, along with the issue I raised in my previous (self-reply) messag=
e.

> One clear advantage (personal opinion) is that the lookup rules already t=
ake care of what you were doing with SFINAE (in the case of the template).

ADL name hiding does not work as reliably as member lookup, though, because=
 it's a "top-down" adjustment of the set of visible namespace members, rath=
er than a "bottom-up" search process starting from the most-derived class.

Careful SFINAE, with an enable/disable trait for each base friend, can repl=
icate the same safety but the language might as well remove the brain surge=
ry factor.

> Types opt into inheriting from the base, different versions of it could b=
e present even in the same namespace (for example, I have used this to prov=
ide 'operator>' in terms of 'operator<' in one base, or in terms of a 'comp=
are' function for other types; each type decides how it wants to define its=
 operators).
>=20
> Outside of a type hierarchy this can be done in each type to provide a th=
e operators that pertain to the type. The main pain point here being that t=
he friend function definition must be inside the class definition (and thus=
 in the header, against some coding guidelines, implicitly inline...). When=
 using this approach in the past the friend functions just forwarded to the=
 actual implementation (similar to the code above, where the operator just =
calls 'do_add').

The pattern of a master free function template dispatching to a derived (pe=
rhaps static) member function does work, but it's a workaround and it requi=
res that only one such dispatcher is found by association with the derived =
class. If the derived class is a template specialization, and one template =
argument comes from another library using the same workaround, then everyth=
ing breaks.

Yep, I've written such code too, and it does work, give or take a compiler =
bug in name lookup. It's far from easy, though, and the safest (scalable) s=
olution is seldom the first choice. I think that static operator overload t=
emplates would let one size fit all, which is a good thing for scalability.

--=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=_555B46E5-C6E3-4850-9BBD-1A4B2924411C
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dwindows-1252"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-=
mode: space; -webkit-line-break: after-white-space;"><br><div><div>On 2014&=
ndash;07&ndash;31, at 12:01 PM, David Rodr=EDguez Ibeas &lt;<a href=3D"mail=
to:dibeas@ieee.org">dibeas@ieee.org</a>&gt; wrote:</div><br class=3D"Apple-=
interchange-newline"><blockquote type=3D"cite"><div dir=3D"ltr">I am not co=
mpletely sure why you want to avoid ADL altogether, combined with friend fu=
nctions defined inside the class definition it provides an interesting mech=
anism to provide free functions that don't pollute the namespace. </div></b=
lockquote><div><br></div><div>As members, they do pollute the namespace. Th=
ey are not found in the namespace only as long as the enclosing class is no=
t associated with either operand. All base classes of an associated class a=
re also associated, so the derived class cannot provide its own <font face=
=3D"Courier">operator +=3D</font> . The base implementation is final.</div>=
<br><blockquote type=3D"cite"><div dir=3D"ltr"><div>Note that by using CRTP=
, the above can have a generic implementation for multiple types without th=
e actual function being a template. </div></div></blockquote><div><br></div=
><div>Hmm, I hadn&rsquo;t considered that. It&rsquo;s certainly a good way =
to define <font face=3D"Courier">operator +</font>. It&rsquo;s nice, though=
, to have only one base class, and not derive classes from a stateful &ldqu=
o;implementation&rdquo; base plus a CRTP &ldquo;interface&rdquo; base, if t=
he CRTP part is specific to the other part.</div><div><br></div><blockquote=
 type=3D"cite"><div dir=3D"ltr"><div>The implication is that compared with =
the first template implementation you allow for *conversions* (which seem t=
o be one goal). If you don't want to allow for those conversions, you can a=
void CRTP and move the template to the friend function (no conversions allo=
wed, closer to your initial version of 'operator+=3D'. [*]</div></div></blo=
ckquote><div><br></div><div>Well, LHS conversions aren&rsquo;t an issue for=
 <font face=3D"Courier">operator +=3D</font>. That goal should be dropped, =
along with the issue I raised in my previous (self-reply) message.</div><br=
><blockquote type=3D"cite"><div dir=3D"ltr">
<div>One clear advantage (personal opinion) is that the lookup rules alread=
y take care of what you were doing with SFINAE (in the case of the template=
). </div></div></blockquote><div><br></div><div>ADL name hiding does not wo=
rk as reliably as member lookup, though, because it&rsquo;s a &ldquo;top-do=
wn&rdquo; adjustment of the set of visible namespace members, rather than a=
 &ldquo;bottom-up&rdquo; search process starting from the most-derived clas=
s.</div><div><br></div><div>Careful SFINAE, with an enable/disable trait fo=
r each base <font face=3D"Courier">friend</font>, can replicate the same sa=
fety but the language might as well remove the brain surgery factor.</div><=
/div><br><div><blockquote type=3D"cite"><div>Types opt into inheriting from=
 the base, different versions of it could be present even in the same names=
pace (for example, I have used this to provide 'operator&gt;' in terms of '=
operator&lt;' in one base, or in terms of a 'compare' function for other ty=
pes; each type decides how it wants to define its operators).</div><div><br=
></div><div>Outside of a type hierarchy this can be done in each type to pr=
ovide a the operators that pertain to the type. The main pain point here be=
ing that the friend function definition must be inside the class definition=
 (and thus in the header, against some coding guidelines, implicitly inline=
&hellip;). When using this approach in the past the friend functions just f=
orwarded to the actual implementation (similar to the code above, where the=
 operator just calls 'do_add&rsquo;).</div></blockquote><br></div><div>The =
pattern of a master free function template dispatching to a derived (perhap=
s static) member function does work, but it&rsquo;s a workaround and it req=
uires that only one such dispatcher is found by association with the derive=
d class. If the derived class is a template specialization, and one templat=
e argument comes from another library using the same workaround, then every=
thing breaks.</div><div><br></div><div>Yep, I&rsquo;ve written such code to=
o, and it does work, give or take a compiler bug in name lookup. It&rsquo;s=
 far from easy, though, and the safest (scalable) solution is seldom the fi=
rst choice. I think that static operator overload templates would let one s=
ize fit all, which is a good thing for scalability.</div><div><br></div></b=
ody></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=_555B46E5-C6E3-4850-9BBD-1A4B2924411C--

.