Thread overview
How to const-overload opEquals(R)(R rhs)?
Aug 07, 2012
Tobias Pankrath
Aug 07, 2012
David
Aug 07, 2012
Ali Çehreli
Aug 07, 2012
Tobias Pankrath
Aug 07, 2012
Jonathan M Davis
August 07, 2012
Hey,

let's say I have a simple struct and I want to give it an opEquals like this.

struct Point
{
    int x, y;
    bool opEquals(R)(R rhs) { return x == rhs.x && y == rhs.y; }
}


With this I can't call opEquals on const instances of Point, because dmd says

> bug.d(13): Error: function bug.Point.opEquals!(Point).opEquals (Point rhs) is not callable using argument types (Point) const

So I overoad is with a const version of oqEquals:

struct Point
{
    int x, y;
    bool opEquals(R)(R rhs) { return x == rhs.x && y == rhs.y; }
    bool opEquals(R)(R rhs) const { return x == rhs.x && y == rhs.y; }
}

But the error stays the same. So why is the const version not taken into consideration?

Thanks for your answers.
August 07, 2012
Really? It compiles: http://dpaste.dzfl.pl/e0470f9a
August 07, 2012
On 08/07/2012 06:40 AM, Tobias Pankrath wrote:

> bool opEquals(R)(R rhs) { return x == rhs.x && y == rhs.y; }
> bool opEquals(R)(R rhs) const { return x == rhs.x && y == rhs.y; }

I strongly recommend that only the const version should be defined. That would work on both mutable and immutable objects.

Besides, opEquals should not modify the object anyway; that would be surprising.

Ali

August 07, 2012
On Tuesday, 7 August 2012 at 16:46:04 UTC, Ali Çehreli wrote:
> On 08/07/2012 06:40 AM, Tobias Pankrath wrote:
>
> > bool opEquals(R)(R rhs) { return x == rhs.x && y == rhs.y; }
> > bool opEquals(R)(R rhs) const { return x == rhs.x && y ==
> rhs.y; }
>
> I strongly recommend that only the const version should be defined. That would work on both mutable and immutable objects.
>
> Besides, opEquals should not modify the object anyway; that would be surprising.
>
> Ali

Design & Style aside. Shouldn't this be possible?

I do have std.Tuple in mind, which can have members of any type. If one of these does not have a const opEquals, comparison is unnecessary restricted to mutable instances.
August 07, 2012
On Tuesday, August 07, 2012 15:40:18 Tobias Pankrath wrote:
> Hey,
> 
> let's say I have a simple struct and I want to give it an opEquals like this.
> 
> struct Point
> {
> int x, y;
> bool opEquals(R)(R rhs) { return x == rhs.x && y == rhs.y; }
> }
> 
> 
> With this I can't call opEquals on const instances of Point, because dmd says
> 
> > bug.d(13): Error: function bug.Point.opEquals!(Point).opEquals
> > (Point rhs) is not callable using argument types (Point) const
> 
> So I overoad is with a const version of oqEquals:
> 
> struct Point
> {
> int x, y;
> bool opEquals(R)(R rhs) { return x == rhs.x && y == rhs.y; }
> bool opEquals(R)(R rhs) const { return x == rhs.x && y ==
> rhs.y; }
> }
> 
> But the error stays the same. So why is the const version not taken into consideration?
> 
> Thanks for your answers.

The standard way to define opEquals at this point would be to have

bool opEquals(const Point rhs) {return this == rhs;}
bool opEquals(const ref Point rhs) {...}

I don't know if templatizing it causes problems or not. And if you can't have it work with const for some reason, then remove the const modifiers on both.

But assuming that templatizing it works, since it's a template, you could probably just do one definition with auto ref:

bool opEquals(R)(auto const ref rhs) const {...}

There have been some discussions on adjusting how const ref and/or auto ref works which would make it so that only one signature was required even without templates, but that hasn't been sorted out yet.

- Jonathan M Davis