www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Will uniform function call syntax apply to operator overloads?

reply Peter Alexander <peter.alexander.au gmail.com> writes:
In short, when UFC is working on all types, will this be possible:

Foo opBinary(string op)(Foo a, Foo b)
{
     return ...;
}

Foo x, y;
Foo z = x + y;

My reasoning here is that x + y is supposedly sugar for 
x.opBinary!("+")(y), so the free opBinary defined above could be chosen 
as a pseudo member of Foo.

Will this be possible?
Oct 12 2010
next sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Peter Alexander <peter.alexander.au gmail.com> wrote:

 In short, when UFC is working on all types, will this be possible:

 Foo opBinary(string op)(Foo a, Foo b)
 {
      return ...;
 }

 Foo x, y;
 Foo z = x + y;

 My reasoning here is that x + y is supposedly sugar for  
 x.opBinary!("+")(y), so the free opBinary defined above could be chosen  
 as a pseudo member of Foo.

 Will this be possible?
As long as operator overloading is defined the way it is, it should work like that, yes. -- Simen
Oct 12 2010
parent reply Tomek =?UTF-8?B?U293acWEc2tp?= <just ask.me> writes:
Simen kjaeraas napisaƂ:

 Peter Alexander <peter.alexander.au gmail.com> wrote:
 
 In short, when UFC is working on all types, will this be possible:

 Foo opBinary(string op)(Foo a, Foo b)
 {
      return ...;
 }

 Foo x, y;
 Foo z = x + y;

 My reasoning here is that x + y is supposedly sugar for
 x.opBinary!("+")(y), so the free opBinary defined above could be chosen
 as a pseudo member of Foo.

 Will this be possible?
As long as operator overloading is defined the way it is, it should work like that, yes.
Funny. I remember asking this not too long ago and got no as an answer. :) Could someone from the D team take a stance on this? -- Tomek
Oct 12 2010
parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Tomek Sowi=C5=84ski <just ask.me> wrote:


 As long as operator overloading is defined the way it is, it should w=
ork
 like that, yes.
Funny. I remember asking this not too long ago and got no as an answer=
. =
 :)
I'm not saying it will. But as long as operator overloading is defined a= s a rewrite of e.g. a + b =3D> a.opBinary!"+"( b ), and uniform function c= all syntax is defined as a rewrite of a.opBinary!"+"( b ) =3D> opBinary!"+"( a, b ), and there are no extra, special rules in play, I would be surprised if it does not work. By this I mean, it would be anti-feature if it did not work, as the compiler would have to be more complex to not support it than to support= it. -- = Simen
Oct 12 2010
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, October 12, 2010 15:53:38 Simen kjaeraas wrote:
 Tomek Sowi=C5=84ski <just ask.me> wrote:
 As long as operator overloading is defined the way it is, it should wo=
rk
 like that, yes.
=20 Funny. I remember asking this not too long ago and got no as an answer. =20 :)
=20 I'm not saying it will. But as long as operator overloading is defined as a rewrite of e.g. a + b =3D> a.opBinary!"+"( b ), and uniform function ca=
ll
 syntax is defined as a rewrite of a.opBinary!"+"( b ) =3D>
 opBinary!"+"( a, b ), and there are no extra, special rules in play, I
 would be surprised if it does not work.
=20
 By this I mean, it would be anti-feature if it did not work, as the
 compiler would have to be more complex to not support it than to support
 it.
That would depend on what order it did things. If it replaced a.func() with= =20 func(a) before it replaced a + b with a.opBinary!"+"(b), then it wouldn't b= e=20 more work at all. It would just naturally not work. If, on the other hand, = the=20 overloaded operators were replaced first, then it could turn a.opBinary!"+"= (b)=20 into opBinary!"+"(a, b). However, I don't think that you can create freestanding operator overloads.= As I=20 understand it, they have to be part of a type (though I could be wrong).=20 Assuming that that were the case, the uniform function syntax would be=20 irrelevant because you couldn't legally declare an overloaded operator func= tion=20 which would work with it. Personally, I do _not_ think that overloaded operators should work with uni= form=20 function syntax, if for no other reason than because it doesn't actually lo= ok=20 like the uniform function syntax does. There is no . operator directly invo= lved.=20 And I don't see any real value in overloaded operators which aren't part of= the=20 type. Unlike C++, I don't think that we have any operators where having an= =20 overloaded operator function be a member function is a problem (the classic= =20 operators with that problem being >> and <<). =2D Jonathan M Davis
Oct 12 2010
next sibling parent Peter Alexander <peter.alexander.au gmail.com> writes:
On 13/10/10 12:15 AM, Jonathan M Davis wrote:
 Personally, I do _not_ think that overloaded operators should work with uniform
 function syntax, if for no other reason than because it doesn't actually look
 like the uniform function syntax does. There is no . operator directly
involved.
 And I don't see any real value in overloaded operators which aren't part of the
 type. Unlike C++, I don't think that we have any operators where having an
 overloaded operator function be a member function is a problem (the classic
 operators with that problem being>>  and<<).

 - Jonathan M Davis
The way I see things, one of the main purposes of uniform function call is so that you can extend structs/classes from 3rd party libraries (i.e. someone else has defined a class, and you want to add an operator without modifying the source file). If I can add any other member function using UFC, I don't see why I shouldn't be able to add operator overloads. It's just an unnecessary inconsistency not to allow them.
Oct 12 2010
prev sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Jonathan M Davis <jmdavisProg gmx.com> wrote:

 That would depend on what order it did things. If it replaced a.func()  
 with
 func(a) before it replaced a + b with a.opBinary!"+"(b), then it  
 wouldn't be
 more work at all. It would just naturally not work. If, on the other  
 hand, the
 overloaded operators were replaced first, then it could turn  
 a.opBinary!"+"(b)
 into opBinary!"+"(a, b).
True. I thought of it as a single step that does both, and repeatedly if necessary.
 Personally, I do _not_ think that overloaded operators should work with  
 uniform
 function syntax, if for no other reason than because it doesn't actually  
 look
 like the uniform function syntax does. There is no . operator directly  
 involved.
 And I don't see any real value in overloaded operators which aren't part  
 of the
 type. Unlike C++, I don't think that we have any operators where having  
 an
 overloaded operator function be a member function is a problem (the  
 classic
 operators with that problem being >> and <<).
Yeah, I also think it should at least be discouraged. I cannot see any situations wherein allowing it would bring significant enough advantages to warrant its use. That said, I am willing to accept there may be such situations, and perhaps even that they should be allowed. -- Simen
Oct 12 2010
parent reply Peter Alexander <peter.alexander.au gmail.com> writes:
On 13/10/10 1:32 AM, Simen kjaeraas wrote:
 Jonathan M Davis <jmdavisProg gmx.com> wrote:
 Personally, I do _not_ think that overloaded operators should work
 with uniform
 function syntax, if for no other reason than because it doesn't
 actually look
 like the uniform function syntax does. There is no . operator directly
 involved.
 And I don't see any real value in overloaded operators which aren't
 part of the
 type. Unlike C++, I don't think that we have any operators where
 having an
 overloaded operator function be a member function is a problem (the
 classic
 operators with that problem being >> and <<).
Yeah, I also think it should at least be discouraged. I cannot see any situations wherein allowing it would bring significant enough advantages to warrant its use. That said, I am willing to accept there may be such situations, and perhaps even that they should be allowed.
Is that how you feel about UFC in general? I can't see how operator overloads should receive discriminatory treatment with respect to their UFC-ability.
Oct 12 2010
parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Peter Alexander <peter.alexander.au gmail.com> wrote:

 Yeah, I also think it should at least be discouraged. I cannot see any
 situations wherein allowing it would bring significant enough advantages
 to warrant its use. That said, I am willing to accept there may be such
 situations, and perhaps even that they should be allowed.
Is that how you feel about UFC in general?
No.
 I can't see how operator overloads should receive discriminatory  
 treatment with respect to their UFC-ability.
Nor do I, when thinking rationally. :p But over the years I've been presented with so much FUD over operator overloading, I don't feel entirely at ease with the possibility of adding operators to third-party data structures. I guess I should keep to my usual thoughts on this, though: stupid people will write stupid code, no matter the tools given, so if someone abuses operator overloading, just stay clear of their code. (and complain loudly if you can't) -- Simen
Oct 13 2010
prev sibling next sibling parent reply "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 12 Oct 2010 17:08:16 -0400, Peter Alexander  
<peter.alexander.au gmail.com> wrote:

 In short, when UFC is working on all types, will this be possible:

 Foo opBinary(string op)(Foo a, Foo b)
 {
      return ...;
 }

 Foo x, y;
 Foo z = x + y;

 My reasoning here is that x + y is supposedly sugar for  
 x.opBinary!("+")(y), so the free opBinary defined above could be chosen  
 as a pseudo member of Foo.

 Will this be possible?
Unknown, but unlikely given how UFC for arrays work today: neither operator overloads nor templates are supported.
Oct 12 2010
parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Robert Jacques <sandford jhu.edu> wrote:

 Unknown, but unlikely given how UFC for arrays work today: neither  
 operator overloads nor templates are supported.
That is not completely true - the following compiles. Templates with more than one required parameter however, doesn't. void output( T )( T[] value ) { writeln( value ); } void main( ) { auto s = "Hello, world!"; s.output; } As for the fact that operator overloads don't work, I believe that is due to array ops, meaning it is not indicative of behavior of other data types. -- Simen
Oct 13 2010
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 12 Oct 2010 17:08:16 -0400, Peter Alexander  
<peter.alexander.au gmail.com> wrote:

 In short, when UFC is working on all types, will this be possible:

 Foo opBinary(string op)(Foo a, Foo b)
 {
      return ...;
 }

 Foo x, y;
 Foo z = x + y;

 My reasoning here is that x + y is supposedly sugar for  
 x.opBinary!("+")(y), so the free opBinary defined above could be chosen  
 as a pseudo member of Foo.

 Will this be possible?
IMO it has to be. operators use a technique called lowering which modifies the original to be as if you typed in the resulting syntax. opBinary has no special qualities except that it is the target of the lowering, so it should be interpreted like any other template function. To answer others' questions of why you'd want to do something like this, a non-member function has control over the signature of both operands. Without an external function, at least one of the operands must be a valid reference. Note the new implementation of comparing two objects for equality, which calls opEquals(o1, o2) instead of o1.opEquals(o2). This significantly improves robustness of opEquals since comparing a null object to another will not result in a segfault. Despite all this, I feel we may want to reinvestigate how to prevent operators from being hijacked. An operator is usually implemented with intimate knowledge of the two types. This usually means being implemented in the same module at least, if not as a member of the class/struct. I wonder if the lowering could be modified to require that. -Steve
Oct 13 2010