www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - struct opCmp?

reply "Nick Sabalausky" <a a.a> writes:
Before I go to post a bug report I want to make sure I'm not missing 
something:

On http://www.digitalmars.com/d/1.0/struct.html it says that structs support 
operator overloading. But I can't seem get opCmp to execute on a struct 
without calling it explicitly:

-------------------------------
import tango.io.Stdout;

struct Foo
{
    int i;
    int opCmp(Foo f)
    {
        Stdout.formatln("In opCmp");
        return i-f.i;
    }
}

Foo getFoo()
{
    return Foo(1);
}

void main()
{
    bool result;
    Stdout.formatln("{}", result);

    result = (Foo(1) == Foo(1));
    Stdout.formatln("{}", result);

    result = (getFoo() == getFoo());
    Stdout.formatln("{}", result);

    Foo f1 = Foo(1);
    Foo f2 = Foo(1);
    result = (f1 == f2);
    Stdout.formatln("{}", result);

    result = (f1.opCmp(f2)) == 0;
    Stdout.formatln("{}", result);
}
-------------------------------

Output:
-------------------------------
false
true
true
true
In opCmp
true
-------------------------------

(FWIW, this is on WinXP 32-bit, DMD 1.043)

Is opCmp completely broken on structs or am I missing something?
May 14 2009
parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Nick Sabalausky wrote:
 Before I go to post a bug report I want to make sure I'm not missing 
 something:
 
 On http://www.digitalmars.com/d/1.0/struct.html it says that structs support 
 operator overloading. But I can't seem get opCmp to execute on a struct 
 without calling it explicitly:
 
 -------------------------------
 import tango.io.Stdout;
 
 struct Foo
 {
     int i;
     int opCmp(Foo f)
     {
         Stdout.formatln("In opCmp");
         return i-f.i;
     }
 }
 
 Foo getFoo()
 {
     return Foo(1);
 }
 
 void main()
 {
     bool result;
     Stdout.formatln("{}", result);
 
     result = (Foo(1) == Foo(1));
     Stdout.formatln("{}", result);
 
     result = (getFoo() == getFoo());
     Stdout.formatln("{}", result);
 
     Foo f1 = Foo(1);
     Foo f2 = Foo(1);
     result = (f1 == f2);
     Stdout.formatln("{}", result);
 
     result = (f1.opCmp(f2)) == 0;
     Stdout.formatln("{}", result);
 }
 -------------------------------
 
 Output:
 -------------------------------
 false
 true
 true
 true
 In opCmp
 true
 -------------------------------
 
 (FWIW, this is on WinXP 32-bit, DMD 1.043)
 
 Is opCmp completely broken on structs or am I missing something?
I think you have to use opEquals to overload ==. opCmp only applies to <, <=, >, and >=. -Lars
May 14 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> wrote in message 
news:gui4ml$2g0n$1 digitalmars.com...
 I think you have to use opEquals to overload ==. opCmp only applies to <, 
 <=, >, and >=.
Oh, I figured either opEquals would be defined in terms of opCmp or an overloaded opCmp would imply a new opEquals defined in terms of it, or something like that.
May 14 2009
next sibling parent Derek Parnell <derek psych.ward> writes:
On Thu, 14 May 2009 18:21:14 -0400, Nick Sabalausky wrote:

 "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> wrote in message 
 news:gui4ml$2g0n$1 digitalmars.com...
 I think you have to use opEquals to overload ==. opCmp only applies to <, 
 <=, >, and >=.
Oh, I figured either opEquals would be defined in terms of opCmp or an overloaded opCmp would imply a new opEquals defined in terms of it, or something like that.
See http://www.digitalmars.com/d/1.0/operatoroverloading.html for actual list. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
May 14 2009
prev sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Nick Sabalausky wrote:
 "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> wrote in message 
 news:gui4ml$2g0n$1 digitalmars.com...
 I think you have to use opEquals to overload ==. opCmp only applies to <, 
 <=, >, and >=.
Oh, I figured either opEquals would be defined in terms of opCmp or an overloaded opCmp would imply a new opEquals defined in terms of it, or something like that.
I think if opCmp is defined and opEquals is not, an opEquals should be implicitly defined in terms of opCmp. I've actually thought about making my own "Object" class... ANyone else have a personalized Object they use?
May 14 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Robert Fraser" <fraserofthenight gmail.com> wrote in message 
news:guihdq$417$3 digitalmars.com...
 Nick Sabalausky wrote:
 "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> wrote in message 
 news:gui4ml$2g0n$1 digitalmars.com...
 I think you have to use opEquals to overload ==. opCmp only applies to 
 <, <=, >, and >=.
Oh, I figured either opEquals would be defined in terms of opCmp or an overloaded opCmp would imply a new opEquals defined in terms of it, or something like that.
I think if opCmp is defined and opEquals is not, an opEquals should be implicitly defined in terms of opCmp.
Yea, I agree. But at the very least, I was thinking that we could use a warning when opCmp is defined and opEquals isn't. Can anyone think of a reasonable case where it would actually make sense to override opCmp, but not opEquals? (that is, without bastardizing them like in a "C++ streams" kind of way)
May 14 2009
next sibling parent reply BCS <none anon.com> writes:
Hello Nick,

 Yea, I agree. But at the very least, I was thinking that we could use
 a warning when opCmp is defined and opEquals isn't. Can anyone think
 of a reasonable case where it would actually make sense to override
 opCmp, but not opEquals? (that is, without bastardizing them like in a
 "C++ streams" kind of way)
 
what about where you want to disallow == like with floating point like cases? I know it doesn't work this way, but if you define opCmp and not opEquals, I wouldn't mind ==/!= being defined to unimplemented.
May 14 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"BCS" <none anon.com> wrote in message 
news:a6268ff5d188cba2e03b08e7a0 news.digitalmars.com...
 Hello Nick,

 Yea, I agree. But at the very least, I was thinking that we could use
 a warning when opCmp is defined and opEquals isn't. Can anyone think
 of a reasonable case where it would actually make sense to override
 opCmp, but not opEquals? (that is, without bastardizing them like in a
 "C++ streams" kind of way)
what about where you want to disallow == like with floating point like cases? I know it doesn't work this way, but if you define opCmp and not opEquals, I wouldn't mind ==/!= being defined to unimplemented.
Interesting idea. Although can't </>/<=/>= also have accuracy problems when the values are close?
May 14 2009
parent BCS <none anon.com> writes:
Hello Nick,

 "BCS" <none anon.com> wrote in message
 news:a6268ff5d188cba2e03b08e7a0 news.digitalmars.com...
 
 Hello Nick,
 
 Yea, I agree. But at the very least, I was thinking that we could
 use a warning when opCmp is defined and opEquals isn't. Can anyone
 think of a reasonable case where it would actually make sense to
 override opCmp, but not opEquals? (that is, without bastardizing
 them like in a "C++ streams" kind of way)
 
what about where you want to disallow == like with floating point like cases? I know it doesn't work this way, but if you define opCmp and not opEquals, I wouldn't mind ==/!= being defined to unimplemented.
Interesting idea. Although can't </>/<=/>= also have accuracy problems when the values are close?
Yes but at least they sometimes work. with == you might as well have the optimizer replace it with false.
May 15 2009
prev sibling parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Nick Sabalausky wrote:
 Can anyone think of a 
 reasonable case where it would actually make sense to override opCmp, but 
 not opEquals? (that is, without bastardizing them like in a "C++ streams" 
 kind of way) 
How about a struct you want to be opCmp()-comparable (which, according to the spec, they aren't by default), but for which equality means bitwise-equality? Similarly, a class that's uniqued (so there are no equal instances that aren't actually the same instance, i.e. comparison means pointer-comparison), yet that has some kind of natural ordering implemented through opCmp().
May 15 2009
parent Christopher Wright <dhasenan gmail.com> writes:
Frits van Bommel wrote:
 Nick Sabalausky wrote:
 Can anyone think of a reasonable case where it would actually make 
 sense to override opCmp, but not opEquals? (that is, without 
 bastardizing them like in a "C++ streams" kind of way) 
How about a struct you want to be opCmp()-comparable (which, according to the spec, they aren't by default), but for which equality means bitwise-equality? Similarly, a class that's uniqued (so there are no equal instances that aren't actually the same instance, i.e. comparison means pointer-comparison), yet that has some kind of natural ordering implemented through opCmp().
In these cases, you can override opEquals to do the bitwise comparisons or pointer comparisons. They're relatively rare, I think. And that natural ordering has to be a total ordering.
May 15 2009