www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Static operator overloads (again)

reply Giles Bathgate <gilesbathgate gmail.com> writes:
I am trying to translate the following C# code into D

     public class Test
        {
            public string Name;

            public static Test operator +(Test lvalue, Test rvalue)
            {
                if (lvalue == null) { lvalue = new Test(); lvalue.Name = "foo";
}
                if (rvalue == null) { rvalue = new Test(); rvalue.Name = "bar";
}

                Console.Write(lvalue.Name);
                Console.Write(rvalue.Name);

                return rvalue;
            }

        }

void main()
{
    Test T = null;
    Test B = null;
    T += B;
}

Whilst leaving the syntax of main() untouched.
Sep 01 2008
next sibling parent reply "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

On Mon, Sep 1, 2008 at 9:11 AM, Giles Bathgate <gilesbathgate gmail.com>wrote:

 I am trying to translate the following C# code into D

     public class Test
        {
            public string Name;

            public static Test operator +(Test lvalue, Test rvalue)
            {
                if (lvalue == null) { lvalue = new Test(); lvalue.Name =
 "foo"; }
                if (rvalue == null) { rvalue = new Test(); rvalue.Name =
 "bar"; }

                Console.Write(lvalue.Name);
                Console.Write(rvalue.Name);

                return rvalue;
            }

        }

 void main()
 {
    Test T = null;
    Test B = null;
    T += B;
 }

 Whilst leaving the syntax of main() untouched.

can only be performed as nonstatic methods of user-defined types. Since a virtual method call requires that the object you're calling it on be non-null (so that you can get the vtable), you can't use overloaded operators on null references.
Sep 01 2008
parent reply Giles Bathgate <gilesbathgate gmail.com> writes:
Jarrett Billingsley Wrote:

 Long story short: I really don't think you can.  Operator overloading in D
 can only be performed as nonstatic methods of user-defined types.  Since > a
virtual method call requires that the object you're calling it on be
 non-null (so that you can get the vtable), you can't use overloaded
 operators on null references.

But static operator overloads are possible in D.
Sep 02 2008
parent reply Giles Bathgate <gilesbathgate gmail.com> writes:
Giles Bathgate Wrote:

 But static operator overloads are possible in D.

Example: public class Test { public char[] Name; public static Test opAddAssign(Test value) { writefln(value.Name); //TODO... } } int Main() { Test t; Test b = new Test(); b.Name = "foo" t += b; // Translates to: Test.opAddAssign(b); } The problem with this though is that there is no access to the lvalue t this is because t+=b; translates to Text.opAddAssign(b); I would like to propose a feature that given the operator overload: public static Test opAddAssign(Test lvalue, Test rvalue) { } then t += b; would translate to: Test.opAddAssign(t,b); I really think this would benefit the language, without breaking anything since the compiler can distinguish between single and double parameter static operator overloads.
Sep 02 2008
parent reply Christopher Wright <dhasenan gmail.com> writes:
Giles Bathgate wrote:
 Giles Bathgate Wrote:
 
 But static operator overloads are possible in D.

Example: public class Test { public char[] Name; public static Test opAddAssign(Test value) { writefln(value.Name); //TODO... } } int Main() { Test t; Test b = new Test(); b.Name = "foo" t += b; // Translates to: Test.opAddAssign(b); } The problem with this though is that there is no access to the lvalue t this is because t+=b; translates to Text.opAddAssign(b); I would like to propose a feature that given the operator overload: public static Test opAddAssign(Test lvalue, Test rvalue) { } then t += b; would translate to: Test.opAddAssign(t,b); I really think this would benefit the language, without breaking anything since the compiler can distinguish between single and double parameter static operator overloads.

I don't particularly think that it would benefit the language. There's no difference between a method call and using an operator overload. If you find yourself doing a lot of null checks, you might want to check out the Null Object pattern. I don't think that having operator overloads be static is such a bad thing, though it prevents you from overloading operators with types. (downs has some interesting examples to this effect...)
Sep 02 2008
parent reply Giles Bathgate <gilesbathgate gmail.com> writes:
Christopher Wright Wrote:

 I don't particularly think that it would benefit the language. There's 
 no difference between a method call and using an operator overload. If 
 you find yourself doing a lot of null checks, you might want to check 
 out the Null Object pattern.

The point is when I write t += b; I don't expect a null reference exception. With operator overloads the only way (that made sense to me) to achieve this was to make the opCatAssign method static, but then my dilemma is that I no longer have an access to the value of t within the opCatAssign method call.
Sep 03 2008
parent reply Christopher Wright <dhasenan gmail.com> writes:
Giles Bathgate wrote:
 Christopher Wright Wrote:
 
 I don't particularly think that it would benefit the language. There's 
 no difference between a method call and using an operator overload. If 
 you find yourself doing a lot of null checks, you might want to check 
 out the Null Object pattern.

The point is when I write t += b; I don't expect a null reference exception. With operator overloads the only way (that made sense to me) to achieve this was to make the opCatAssign method static, but then my dilemma is that I no longer have an access to the value of t within the opCatAssign method call.

On the other hand, what about subclasses? They can't override the behavior of an operator overload, if operator overloading uses static methods. You're reduced to writing your overloads as: class Foo { static Foo opAddAssign (Foo left, Foo right) { return left.addAssign(right); } } So your proposal eliminates two valid use cases and breaks existing syntax and expectations. The only benefit you get is being able to use null in an operator overload, which is also an unexpected change from the existing system. Just use the Null Object pattern. It's intended to solve exactly the sort of problem you have, and it works with methods as well.
Sep 03 2008
parent reply Giles Bathgate <gilesbathgate gmail.com> writes:
Christopher Wright Wrote:

 On the other hand, what about subclasses? They can't override the 
 behavior of an operator overload, if operator overloading uses static 
 methods. You're reduced to writing your overloads as:
 
 class Foo
 {
 	static Foo opAddAssign (Foo left, Foo right)
 	{
 		return left.addAssign(right);
 	}
 }
 

I don't understand your example. It was my understanding that static methods cannot be overridden. (there is no vtable entry for a static method) Maybe you thought that I an requesting for D's implementation of operator overloads to ONLY use static methods?
Sep 04 2008
parent Christopher Wright <dhasenan gmail.com> writes:
Giles Bathgate wrote:
 Christopher Wright Wrote:
 
 On the other hand, what about subclasses? They can't override the 
 behavior of an operator overload, if operator overloading uses static 
 methods. You're reduced to writing your overloads as:

 class Foo
 {
 	static Foo opAddAssign (Foo left, Foo right)
 	{
 		return left.addAssign(right);
 	}
 }

I don't understand your example. It was my understanding that static methods cannot be overridden. (there is no vtable entry for a static method)

That is my point. Static methods cannot be overridden. I want virtual operator overloads.
 Maybe you thought that I an requesting for D's implementation of operator
overloads to ONLY use static methods?

So your suggestion is to convert: {{{ MyClass instance1, instance2; auto instance3 = instance1 + instance2; }}} to: {{{ MyClass instance1, instance2; MyClass instance3; static if (isStaticMethod!(MyClass.opAdd)) instance3 = MyClass.opAdd(instance1, instance2); else instance3 = instance1.opAdd(instance2); }}} I don't see anything wrong with this suggestion. But I just don't see any compelling reason for it. I'm not getting off my chair to patch dmd to support this.
Sep 04 2008
prev sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Thu, 04 Sep 2008 13:47:20 +0400, Giles Bathgate  
<gilesbathgate gmail.com> wrote:

 Christopher Wright Wrote:

 On the other hand, what about subclasses? They can't override the
 behavior of an operator overload, if operator overloading uses static
 methods. You're reduced to writing your overloads as:

 class Foo
 {
 	static Foo opAddAssign (Foo left, Foo right)
 	{
 		return left.addAssign(right);
 	}
 }

I don't understand your example. It was my understanding that static methods cannot be overridden. (there is no vtable entry for a static method)

Indeed, static methods can't be overriden. That's why you end up writing something like this to get polymorphism in C#.
 Maybe you thought that I an requesting for D's implementation of  
 operator overloads to ONLY use static methods?

No, but what is the real difference between two, apart from ability to pass null pointers which is a bad design anyway? It is redundant. I think it should be removed from language at all.
Sep 04 2008