Some problems with operator overloading

bearophile bearophileHUGS at lycos.com
Sun Mar 14 07:55:41 PDT 2010


In the following little programs can you help me tell apart my errors from bugs in dmd?

(This post shows only part of the problems I have found with operator overloading).

-------------------------------

1) Error in the documentation in this page:
http://www.digitalmars.com/d/2.0/operatoroverloading.html

This:

struct S {
    int opEquals(ref const S s) { ... }
}

Probably has to become like:

struct S {
    const bool opEquals(ref const(S) s) { ... }
}

-------------------------------

2) This code runs:


import std.c.stdio: printf;
struct Foo {
    int data;
    int opEquals(T:Foo)(T other) {
        printf("A");
        return this.data == other.data;
    }
}
void main() {
    int r = Foo(5) == Foo(5);
}


But I think dmd has to raise a c error, and require something like:
const bool opEquals(T:Foo)(ref const(Foo) other) {
Or:
const bool opEquals(T:Foo)(const(Foo) other) {
etc.

-------------------------------

3) This code runs:


struct Foo {
    int data;
    bool opBinary(string Op:"==")(ref const Foo other) { // wrong: opEquals
        return this.data == other.data;
    }
    bool opBinary(string Op)(ref const Foo other) if (Op == "0") { // wrong
        return this.data == other.data;
    }
}
void main() {}


But that can cause bugs: it's easy for programmers to forget to use opEquals instead of opBinary("==").

And generally I'd like dmd to raise an error when silly ops are defined, like that "0". It's important to avoid many bugs in the operator overloading usage.

-------------------------------

4) This program doesn't compile:


struct Foo {
    int x;
    Foo opUnary(string op:"++")() {
        this.x++;
        return this;
    }
}
void main() {
    Foo f = Foo(5);
    f++; // line 10
}


Prints:
temp.d(10): Error: var has no effect in expression (__tmp1)

-------------------------------

5) Here an implicit cast to uint or int can be handy, to avoid the cast (to be able to create a generic "fake int" struct), is this possible?


struct Foo {
    int x;
    int opCast(T:int)() {
        return this.x;
    }
}
void main() {
    Foo f = Foo(5);
    auto a1 = new int[cast(int)f]; // OK
    auto a2 = new int[f];          // ERR
}


Philippe Sigaud in the digitalmars.D.learn newsgroup suggests an opImplicitCast. It can be useful in other situations (but I don't know its possible bad side effects):


struct Foo {
    int x;
    int opCast(T:int)() {
        return this.x;
    }
}
void bar(int i) {}
void main() {
    Foo f = Foo(5);
    bar(f); // Error
}

-------------------------------

Bye,
bearophile



More information about the Digitalmars-d mailing list