default '==' on structs

Lars T. Kyllingstad public at kyllingen.NOSPAMnet
Thu Feb 3 00:09:57 PST 2011


On Wed, 02 Feb 2011 17:35:50 +0100, spir wrote:

> On 02/02/2011 04:20 PM, Lars T. Kyllingstad wrote:
>> On Wed, 02 Feb 2011 15:55:53 +0100, spir wrote:
>>
>>> Hello,
>>>
>>> What are the default semantics for '==' on structs?
>>>
>>> I ask this because I was forced to write opEquals on a struct to get
>>> expected behaviour. This struct is basically:
>>>
>>> struct Lexeme {
>>>       string tag;
>>>       string slice;
>>>       Ordinal index;
>>> }
>>>
>>> Equal Lexeme's compare unequal using default '=='. When I add:
>>>
>>>       const bool opEquals (ref const(Lexeme) l) {
>>>           return (
>>>                  this.tag   == l.tag
>>>               && this.slice == l.slice
>>>               && this.index == l.index
>>>           );
>>>       }
>>>
>>> then all works fine. What do I miss?
>>
>> I think the compiler does a bitwise comparison in this case, meaning
>> that it compares the arrays' pointers instead of their data.  Related
>> bug report:
>>
>>    http://d.puremagic.com/issues/show_bug.cgi?id=3433
>>
>> -Lars
> 
> Thank you, Lars.
> In fact, I do not really understand what you mean. But it helped me
> think further :-)
> Two points:
> 
> * The issue reported is about '==' on structs not using member opEquals
> when defined, instead performing bitwise comparison. This is not my
> case: Lexeme members are plain strings and an uint. They should just be
> compared as is. Bitwise comparison should just work fine. Also, this
> issue is marked solved for dmd 2.037 (I use 2.051).

Yeah, but I would say it isn't really fixed.  It seems that the final 
decision was that members which define opEquals() are compared using 
opEquals(), while all other members are compared bitwisely.  But built-in 
dynamic arrays can also be compared in two ways, using '==' (equality) or 
'is' (identity, i.e. bitwise equality).  Struct members which are dynamic 
arrays should, IMO, be compared using '==', but apparently they are not.


> * The following works as expected:
> 
> struct Floats {float f1, f2;}
> struct Strings {string s1, s2;}
> struct Lexeme {
>      string tag;
>      string slice;
>      uint index;
> }
> 
> unittest {
>      assert ( Floats(1.1,2.2)  == Floats(1.1,2.2) ); assert (
>      Strings("a","b") == Strings("a","b") ); assert ( Lexeme("a","b",1)
>      == Lexeme("a","b",1) );
> }
> 
> This shows, if I'm right:
> 1. Array (string) members are compared by value, not by ref/pointer. 2.
> Comparing Lexeme's works in this test case.

Nope, it doesn't show that, because you are assigning literals to your 
strings, and DMD is smart enough to detect duplicate literals.

    string s1 = "foo";
    string s2 = "foo";
    assert (s1.ptr == s2.ptr);

That is actually pretty cool, by the way. :)

Here's an example to demonstrate my point:

    import std.stdio;

    struct T { string s; }

    void main(string[] args)
    {
        auto s1 = args[1];
        auto s2 = args[2];
        auto t1 = T(s1);
        auto t2 = T(s2);

        if (s1 == s2) writeln("Arrays are equal");
        else writeln("Arrays are different");

        if (t1 == t2) writeln("Structs are equal");
        else writeln("Structs are different");
    }

If run with the arguments "foo bar" it prints:

    Arrays are different
    Structs are different

If run with the arguments "foo foo" it prints:

    Arrays are equal
    Structs are different

-Lars


More information about the Digitalmars-d-learn mailing list