Some problems with operator overloading

Steven Schveighoffer schveiguy at yahoo.com
Mon Mar 15 08:12:42 PDT 2010


On Mon, 15 Mar 2010 10:46:01 -0400, bearophile <bearophileHUGS at lycos.com>  
wrote:

> Steven Schveighoffer:
>
>> I think there is no restriction on what opEquals in structs.<
>
> I think this is a hole in the specification that needs to be filled,  
> because I think you must be sure opEquals returns a bool.

Oh, I thought you meant that the const decorations need to be in there.  I  
still think normal compilation should take care of this.

>
>
>> These kinds of errors are appropriate for a lint tool.<
>
> Have you seen any good lint tool for D?
>
> Generally any compiler error can be moved to a lint tool, so it's a  
> matter of balance. In my opinion generally if some sanity test on the  
> code is computationally heavy or the errors it spots are uncommon, or if  
> it's not certain they are really errors, or if it's very uncommon, then  
> it's possible or better to move it to a lint. If the test is not  
> hard/heavy to do and it can catch a common sure mistake then it's better  
> to put it into the compiler. D compiler already performs several tests  
> that were work for C lint tools.
>
> So I think the compiler can be allowed to catch some potentially common  
> operator overloading bugs like opBinary("==").

It is a good point.  It's one of the drawbacks of a "lowering" technique  
-- getting one little bit wrong is not flagged as an error.  However, we  
haven't used the system very much yet, let's wait and see how pervasive  
such errors are.  I can see one potential reason to use opBinary("==") and  
that is to collect binary operator code in one place.  The opEquals()  
method could forward to the opBinary("==") function.

One thing that can help is to create in phobos such template constraints  
such as isBinaryOperator(string op) to safeguard against such problems.   
It would be better if the compiler did this, but I'm not sure how it's  
going to play out.  This may become the evil descendant of if(...); but it  
also could turn out to be nothing.  Maybe some really creative programmer  
will come up with a good reason to have it.

>
>
>> Note that opBinary can be directly called via:  
>> myfoo.opBinary!("0")(other);<
>
> And that's insane code, right. Today programmers want a nanny compiler  
> that helps. The age of strong silent C compilers is dead or it's  
> acceptable for kernel devs only.

This is not likely to be a common problem.  I don't think this is a good  
reason to put in a compiler error.

>> Something like this should work:
>> struct Foo {
>>    int x;
>>    int opCast(T:int)() { return this.x; };
>>    alias opCast this;
>> }
>
> This little program:
>
> struct Foo {
>    int x;
>    uint opCast(T:uint)() { return this.x; }
>    int opCast(T:int)() { return this.x; }
>    alias opCast this;
> }
> void main() {
>     Foo f = Foo(5);
>     int[] a = new int[f]; // line 9
> }
>
>
> Gives the following errors:
> test.d(9): Error: cannot implicitly convert expression (f) of type Foo  
> to uint
> test.d(9): Error: cannot cast f.opCast(T : int)

Yeah, I tried to get it to work too, but it doesn't.  Even something like  
this doesn't work:

struct Foo {
    uint x;
    uint castToUint() { return x; }
    alias castToUint this;
}

This should work.  The template code you wrote above might not work,  
because you can't overload functions on no arguments.  I'm unsure how this  
should work, but at least something like this should:

alias opCast!uint this;

A bug filing is in order I think.

-Steve



More information about the Digitalmars-d mailing list