Destructors, const structs, and opEquals

Steven Schveighoffer schveiguy at yahoo.com
Sat Dec 4 22:04:18 PST 2010


On Sun, 05 Dec 2010 00:40:26 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> On 12/4/10 22:36 CST, Steven Schveighoffer wrote:
>> 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
>
> Then you handle the angry crowds for me please.

Huh?  I don't think you understand what I mean.  inout only implicitly  
converts to const.  Example:

struct S
{
   bool opEquals(S rhs){return false;}
}

struct T
{
   S s;
   bool opEquals(auto ref inout T rhs) inout {
      return s == rhs.s; // error, cannot call S.opEquals(S rhs) with  
parameters (inout S) inout
   }
}

You gain nothing from making opEquals of Tuple inout vs. const.

IMO all opEquals should be const functions, and the parameter should be  
const if it is marked as ref, or it contains references.

>
>>>> 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?
>
> No.
>
>> How does one call the same
>> function with by ref or by value?
>
> By always using ref.

I'm totally confused.  I thought the point of auto ref was to pass by  
value if it's an rvalue (since the data is already on the stack).  If this  
is not the case, then why not just make ref work that way?  Why wouldn't I  
mark all my functions as auto ref to avoid being pestered by the compiler?

-Steve


More information about the Digitalmars-d mailing list