Destructors, const structs, and opEquals

Steven Schveighoffer schveiguy at yahoo.com
Sat Dec 4 20:36:22 PST 2010


On Sat, 04 Dec 2010 11:00:58 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> On 12/4/10 9:23 AM, Don wrote:
>> Andrei Alexandrescu wrote:
>>> On 12/4/10 12:42 AM, Don wrote:
>>>> Officially, opEquals has to have the signature:
>>>>
>>>> struct Foo {
>>>> bool opEquals(const ref Foo x) const {...}
>>>> }
>>>
>>> This is a compiler bug. For structs there should be no official
>>> implementation of opEquals, opCmp etc. All the compiler needs to worry
>>> about is to syntactically translate a == b to a.opEquals(b) and then
>>> let the usual language rules resolve the call.
>>
>> Fine, but try to implement a generic type which supports ==.
>> For example, Tuple in std.typecons.
>> The only reason that many of the Tuple unit tests pass is that opEquals
>> never gets instantiated.
>
> I think it should be as follows:
>
> bool opEquals(auto ref inout Tuple rhs) inout {
>    foreach (i, T; Types) {
>      if (this[i] != rhs[i]) return false;
>    }
>    return true;
> }
>

No no no, inout does not belong here.  Use const.  inout is only used if  
you are returning a portion of the arguments.  That should be a hard rule  
by the compiler (error).

Fixed:

bool opEquals(auto ref const(Tuple) rhs) const

>> How can opEquals be defined in a way that it works for structs with
>> destructors, and also with rvalues?
>
> "auto ref" should be used whenever you want to accept both a value and  
> an rvalue. For structs with destructors see my other post in this thread.
>
> Unfortunately, "auto ref" is currently implemented wrongly due to a  
> misunderstanding between Walter and myself. I meant it as a relaxation  
> of binding rules, i.e. "I'm fine with either an rvalue or an lvalue". He  
> thought it's all about generating two template instantiations. In fact  
> auto ref should work when there's no template in sight.

But it must instantiate two functions, no?  How does one call the same  
function with by ref or by value?  And when inside the function, the code  
generation for a ref storage class is going to be drastically different,  
right?

BTW, I agree with the point, it should not require templates.  But I think  
it does result in two functions.

Actually, thinking about it more, how does this work?

T foo();
T bar();
if(foo() == bar())

both are temporaries, but opEquals passes 'this' by reference.  So there  
we have a case where a reference of a temporary is passed.  Does this make  
sense?

Indeed, I have used this 'trick' to get around the discussed limitations  
while writing dcollections.  Just always compare using 'rvalue == lvalue'.

-Steve


More information about the Digitalmars-d mailing list