Jump to page: 1 2
Thread overview
opEquals does not work?
Jun 07, 2013
Namespace
Jun 07, 2013
Namespace
Jun 07, 2013
w0rp
Jun 07, 2013
Namespace
Jun 07, 2013
w0rp
Jun 07, 2013
Jonathan M Davis
Jun 07, 2013
w0rp
Jun 07, 2013
bearophile
Jun 07, 2013
Namespace
Jun 07, 2013
Ali Çehreli
Jun 08, 2013
Jonathan M Davis
June 07, 2013
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]
June 07, 2013
I got it. I must use Object instead of A... How ridiculous. I thought this was already fixed...
June 07, 2013
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;
}
June 07, 2013
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.
June 07, 2013
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.
June 07, 2013
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
June 07, 2013
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.
June 07, 2013
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
June 07, 2013
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.
June 07, 2013
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

« First   ‹ Prev
1 2