www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - opEquals does not work?

reply "Namespace" <rswhite4 googlemail.com> writes:
Did I miss something?

I expected this output
----
opEquals: 23 == 23
Equal 1
opEquals: 23 == 23
Equal 2
----
by the following code, but I only get this:
----
opEquals: 23 == 23
Equal 2
----

Code:
[code]
import std.stdio;

class A {
public:
	int id;

	this(int id) {
		this.id = id;
	}

	bool opEquals(const A a) const {
		writefln("opEquals: %d == %d", this.id, a.id);
		return a.id == this.id;
	}
}

void main() {
	A a1 = new A(23);
	A a2 = new A(23);

	if (a1 == a2) {
		writeln("Equal 1");
	}

	if (a1.opEquals(a2)) {
		writeln("Equal 2");
	}
}
[/code]
Jun 07 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
I got it. I must use Object instead of A... How ridiculous. I 
thought this was already fixed...
Jun 07 2013
next sibling parent reply "w0rp" <devw0rp gmail.com> writes:
On Friday, 7 June 2013 at 20:51:13 UTC, Namespace wrote:
 I got it. I must use Object instead of A... How ridiculous. I 
 thought this was already fixed...
The class opEquals is quite like .equals in Java. You need to match the signature of Object, which is implicitly the base class of all classes. I think I recommend something like this. override bool opEquals(Object o) const { auto other = cast(A) o; // It's probably easy to miss out !is null here, which matters. return other !is null && this.id == other.id; }
Jun 07 2013
parent reply "Namespace" <rswhite4 googlemail.com> writes:
On Friday, 7 June 2013 at 20:58:40 UTC, w0rp wrote:
 On Friday, 7 June 2013 at 20:51:13 UTC, Namespace wrote:
 I got it. I must use Object instead of A... How ridiculous. I 
 thought this was already fixed...
The class opEquals is quite like .equals in Java. You need to match the signature of Object, which is implicitly the base class of all classes. I think I recommend something like this. override bool opEquals(Object o) const { auto other = cast(A) o; // It's probably easy to miss out !is null here, which matters. return other !is null && this.id == other.id; }
Yes, I remember. As I heard it the first time I thought it's because of the limited compiler and that it will fixed some day.
Jun 07 2013
parent "w0rp" <devw0rp gmail.com> writes:
On Friday, 7 June 2013 at 21:02:15 UTC, Namespace wrote:
 Yes, I remember. As I heard it the first time I thought it's 
 because of the limited compiler and that it will fixed some day.
opEquals for classes is interesting because you actually do need to write 'Object' there because of type polymorphism.
Jun 07 2013
prev sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, June 07, 2013 22:51:12 Namespace wrote:
 I got it. I must use Object instead of A... How ridiculous. I
 thought this was already fixed...
I have an open pull request as part of the move to getting rid of opEquals, opCmp, toHash, and toString from Object, and it would make it so that you could use something other than Object: https://github.com/D-Programming-Language/druntime/pull/459 However, due to D's overload rules, you will _always_ be forced to have an opEquals which takes the most base class that you can compare. But you should be able to do something like overload it with the derived class type and then alias the base classes' opEquals into the scope of the derived class. - Jonathan M Davis
Jun 07 2013
next sibling parent "w0rp" <devw0rp gmail.com> writes:
On Friday, 7 June 2013 at 21:18:12 UTC, Jonathan M Davis wrote:
 I have an open pull request as part of the move to getting rid 
 of opEquals,
 opCmp, toHash, and toString from Object, and it would make it 
 so that you
 could use something other than Object
Oh, that's cool. I didn't know about that.
Jun 07 2013
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 However, due to D's overload rules, you will _always_ be forced 
 to have an
 opEquals which takes the most base class that you can compare.
http://d.puremagic.com/issues/show_bug.cgi?id=10292 Bye, bearophile
Jun 07 2013
parent "Namespace" <rswhite4 googlemail.com> writes:
On Friday, 7 June 2013 at 21:42:36 UTC, bearophile wrote:
 Jonathan M Davis:

 However, due to D's overload rules, you will _always_ be 
 forced to have an
 opEquals which takes the most base class that you can compare.
http://d.puremagic.com/issues/show_bug.cgi?id=10292 Bye, bearophile
Thank you.
Jun 07 2013
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 06/07/2013 02:18 PM, Jonathan M Davis wrote:

 I have an open pull request as part of the move to getting rid of 
opEquals,
 opCmp, toHash, and toString from Object, and it would make it so that you
 could use something other than Object:
I hope it supports delegate-taking toString overload for classes.[1] Ali [1] As a reminder to others who don't know or keep forgetting like me, :) toString has a more efficient toString overload. Unfortunately, it works only with structs at this point. I am way off-topic now but here is an example: import std.stdio; import std.format; struct Point { int x; int y; void toString(void delegate(const(char)[]) sink) const { formattedWrite(sink, "(%s,%s)", x, y); } } struct Color { ubyte r; ubyte g; ubyte b; void toString(void delegate(const(char)[]) sink) const { formattedWrite(sink, "RGB:%s,%s,%s", r, g, b); } } struct ColoredPoint { Color color; Point point; void toString(void delegate(const(char)[]) sink) const { formattedWrite(sink, "{%s;%s}", color, point); } } struct Poligon { ColoredPoint[] points; this(ColoredPoint[] points) { this.points = points; } void toString(void delegate(const(char)[]) sink) const { formattedWrite(sink, "%s", points); } } void main() { auto poligon = Poligon( [ ColoredPoint(Color(10, 10, 10), Point(1, 1)), ColoredPoint(Color(20, 20, 20), Point(2, 2)), ColoredPoint(Color(30, 30, 30), Point(3, 3)) ]); writeln(poligon); } The advantage of this method over the more-common toString() overload (the one that returns string) is that although there are still a total of 10 calls made to various toString() functions, those calls collectively produce a single string, not 10. Ali
Jun 07 2013
parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, June 07, 2013 14:53:44 Ali Çehreli wrote:
 On 06/07/2013 02:18 PM, Jonathan M Davis wrote:
 I have an open pull request as part of the move to getting rid of
opEquals,
 opCmp, toHash, and toString from Object, and it would make it so that you
 could use something other than Object:
I hope it supports delegate-taking toString overload for classes.[1]
It should be perfectly possible to declare such an overload now. It just won't work when used through Object. If it doesn't work, then I expect that that's a bug in formattedWrite and friends. As far as overriding goes though, that'll depend on what the base classes of a class have declared. If they all declare toString without a delegate, then that's what you'd have to override to use toString using references of their type, whereas if they use the toString which takes a delegate, then that's what you'd have to override. But I don't see any reason that you can't have both just so long as the type of the reference that you're using has it. Howver, I supposed that a potential problem with formattedWrite and friends is that if you have two toString methods, it has to pick which one to use, and right now, it probably just picks the one from Object. Better behavior would be to us the delegate one if it's there and fall back to the non-delegate version if it's not. Long term though, formattedWrite et al will probably have the potential of not working at all with a class if we fully remove it from Object ike we intend to, since then there's no guarantee that a class or any of its base classes have even declared any toString. In any case, if toString with a delegate doesn't work with formattedWrite et al, then we need an enhancement request for that to be fixed. - Jonathan M Davis
Jun 07 2013