Thread overview
How do you overload opEquals?
Nov 19, 2013
Dale Matthews
Nov 19, 2013
Adam D. Ruppe
Nov 19, 2013
Adam D. Ruppe
Nov 19, 2013
Dale Matthews
Nov 19, 2013
Dale Matthews
Nov 19, 2013
Adam D. Ruppe
Nov 19, 2013
Andrea Fontana
Nov 20, 2013
Adam D. Ruppe
Nov 20, 2013
Mike Parker
November 19, 2013
I'm brand new to D and I'm taking on a project. In the midst, I've overloaded a whole load of operators for my Vec3 class. Most seem to be working (I haven't tested them all yet) but opEquals is refusing to be called. I've followed the guidelines here: http://dlang.org/operatoroverloading.html#equals

class Vec3
{
public:
	float x, y, z;
	this(float xVal, float yVal, float zVal) { x = xVal, y = yVal, z = zVal; }
	bool opEquals()(auto ref const Vec3 v) const
	{
		debug writeln("bool opEquals(Vec3) called");
		return x == v.x && y == v.y && z == v.z;
	}
};
unittest
{
	Vec3 v = new Vec3(5, 10, 15);
	Vec3 v2 = new Vec3(5, 10, 15);
	//if(v.opEquals(v2))                      //this works great!
	if(v == v2)                                   //idk where this goes off to but it returns false
		writeln("FINALLY");
	else
		writeln("try again?");
}

I've tried many variations of auto ref and const (although I'm not sure how the function is different for each variation), and it still doesn't get called. I feel like I'm missing something simple.
November 19, 2013
On Tuesday, 19 November 2013 at 20:59:31 UTC, Dale Matthews wrote:
> I feel like I'm missing something simple.

opEquals doesn't work on classes with class references. It doesn't call a method with obj = other_obj, it just rebinds the reference. If you want full control over opEquals, it'll have to be a struct instead of class.

November 19, 2013
On Tuesday, 19 November 2013 at 20:59:31 UTC, Dale Matthews wrote:
> I'm brand new to D and I'm taking on a project. In the midst, I've overloaded a whole load of operators for my Vec3 class. Most seem to be working (I haven't tested them all yet) but opEquals is refusing to be called. I've followed the guidelines here: http://dlang.org/operatoroverloading.html#equals
>
> class Vec3
> {
> public:
> 	float x, y, z;
> 	this(float xVal, float yVal, float zVal) { x = xVal, y = yVal, z = zVal; }
> 	bool opEquals()(auto ref const Vec3 v) const
> 	{
> 		debug writeln("bool opEquals(Vec3) called");
> 		return x == v.x && y == v.y && z == v.z;
> 	}
> };
> unittest
> {
> 	Vec3 v = new Vec3(5, 10, 15);
> 	Vec3 v2 = new Vec3(5, 10, 15);
> 	//if(v.opEquals(v2))                      //this works great!
> 	if(v == v2)                                   //idk where this goes off to but it returns false
> 		writeln("FINALLY");
> 	else
> 		writeln("try again?");
> }
>
> I've tried many variations of auto ref and const (although I'm not sure how the function is different for each variation), and it still doesn't get called. I feel like I'm missing something simple.


    override bool opEquals (Object o) const {
        if ( auto v = cast( typeof( this ) ) o )
            return x == v.x && y == v.y && z == v.z;
        return false;
    }


You need:
1) 'override' in order to override the base class implementation.
2) 'Object' typed parameter, then cast.
November 19, 2013
On Tuesday, 19 November 2013 at 21:05:23 UTC, Adam D. Ruppe wrote:
> opEquals doesn't work on classes with class references.

IGNORE ME, I am wrong here. I mixed up opEquals and opAssign in my head.

Sorry!
November 19, 2013
On Tuesday, 19 November 2013 at 21:10:57 UTC, Chris Nicholson-Sauls wrote:
>     override bool opEquals (Object o) const {
>         if ( auto v = cast( typeof( this ) ) o )
>             return x == v.x && y == v.y && z == v.z;
>         return false;
>     }
>
>
> You need:
> 1) 'override' in order to override the base class implementation.
> 2) 'Object' typed parameter, then cast.

Very cool, it works great! Thanks for the help, Chris.

Adam, do you recommend using a struct instead of a class? I'm from C++ where structs are mainly used for PODs. It sounds handy in instances like this though: http://dlang.org/cpptod.html#structcmp
November 19, 2013
On Tuesday, 19 November 2013 at 21:22:27 UTC, Adam D. Ruppe wrote:

> IGNORE ME, I am wrong here. I mixed up opEquals and opAssign in my head.
>
> Sorry!

Will do :]
November 19, 2013
On Tuesday, 19 November 2013 at 21:25:47 UTC, Dale Matthews wrote:
> Adam, do you recommend using a struct instead of a class?

Yes, I would use a struct instead of a class here. The key question to ask in D is: do you need inheritance? If yes, use a class, if no, struct is usually better, since it is lighter weight and generally more flexible.
November 19, 2013
On Tuesday, 19 November 2013 at 21:33:31 UTC, Adam D. Ruppe wrote:
> On Tuesday, 19 November 2013 at 21:25:47 UTC, Dale Matthews wrote:
>> Adam, do you recommend using a struct instead of a class?
>
> Yes, I would use a struct instead of a class here. The key question to ask in D is: do you need inheritance? If yes, use a class, if no, struct is usually better, since it is lighter weight and generally more flexible.

And, of course, struct are value type, class are reference type.
So, for example:

int i = 0;
while(++i < 10000000)
{
  S a; // if S is a class S a = new S;
  a.i = 10;
}

it's really faster if S is a struct
November 20, 2013
On Tuesday, 19 November 2013 at 23:58:20 UTC, Andrea Fontana wrote:
> And, of course, struct are value type, class are reference type.

Yeah, true in general, though it is possible to have a struct be very similar to a reference type. Consider:

struct WrappedClass {
   Object obj;
   /* and whatever other methods, but no more data */
}

It's still a value type, but the only member is a reference, so you can use it the same way as any other reference type; it works the same way as Object itself.

So struct is flexible in the value vs reference type regard too.
November 20, 2013
On 11/20/2013 5:59 AM, Dale Matthews wrote:

>
> class Vec3
> {
>
>      bool opEquals()(auto ref const Vec3 v) const


You don't need to use 'ref' on parameters that are classes. Unlike C++, D classes are already reference types, not value types. More like Java. Structs, OTOH, are value types. With those, a const ref parameter makes sense, but not with classes.