opEquals(const ref yadaYada)

Steven Schveighoffer schveiguy at yahoo.com
Tue Dec 15 07:43:45 PST 2009


On Mon, 14 Dec 2009 11:44:18 -0500, lws <invalid at email.com> wrote:

> On 2009-12-14 07:01:47 -0800, dsimcha <dsimcha at yahoo.com> said:
>
>> == Quote from lws (invalid at email.com)'s article
>>> I don't know if I believe this is necesarrily bad.  It's revealing some
>>> bad coding on your part.
>>> You shouldn't be doing opEquals with an rvalue of a class.   Make
>>> getFoo return a reference.
>>> ref Foo getFoo() {} fixes the problem and avoids value-copying for no
>>> reason to an rvalue that's going to get garbage collected.
>>  1.  This was in DFL's code, not stuff I wrote.
>> 2.  It was a small struct that was cheap to copy, not a class.
>> 3.  At any rate, the inconsistency with builtins is inexcusable.
>
> 1.  Well, stuff like this is good warning to whomever about the code.    
> Since D is a imperative language, it should at least give you a warning  
> when you're doing something really inefficient that has a boilerplate  
> way of accomplishing it that is much faster.

It's not faster, it's slower.  Passing a reference to an integer or  
smaller value type is not as efficient passing the value type itself.

> 2.  That's odd.  structs DO have stack scope in D.  Right?   It  
> shouldn't even warn in that case.  IMHO.

The issue is that the compiler is incorrectly assuming that it *must* use  
a const ref form of opEquals for a member when composing an opEquals  
function for a struct that doesn't provide one.  To this end, it always  
ensures any overload set of opEquals has a const ref form.  The premise  
that const ref is always required is false in some cases, and this is the  
bug.

> 3.  For classes, it is consistent with the whole point of the new const  
> stuff and the GC, and the fact that they are heap objects by  
> definition.   Classes have always been treated "differently."   And I  
> think it's good.    Walter has enabled a lot of expressiveness with the  
> syntax in D when compared to C++, and it allows nice warnings when  
> you're doing things you probably shouldn't.

Classes should be allowed to be passed as const only, no ref.  Passing a  
reference to a class makes no sense since they are references already  
(Even scoped class variables are references).

In fact, const ref makes absolutely no sense for a class, ever.

> Unfortunately, this isn't an error....   Maybe for some reason you  
> REALLY want to be copying around structs and classes.

It is an error, not a warning.

The following opEquals functions should always compile:

struct S1
{
    int x;
    bool opEquals(S1 s) const { return true; }
}

struct S2
{
    int *x;
    bool opEquals(const S2 s) const { return true; }
}

The following should not necessarily compile:

struct Sbad
{
    int *x;
    bool opEquals(Sbad s) const { return true; }
}

-Steve



More information about the Digitalmars-d mailing list