Ali Çehreli:

The type of literal 1 is int, not long. So, both functions are matched with implicit conversions. According to "Function Overloading" here:

  http://dlang.org/function.html

The match is later resolved by "If two or more functions have the same match level, then partial ordering is used to try to find the best match. Partial ordering finds the most specialized function."

If bool is considered to be more specialized than long, then the compiler is behaving according to spec. It is very confusing indeed. Especially, considering that an int *variable* would be matched to long:

    auto i = 1;
    foo(i);

Now the long overload gets called!

This is the code of the OP improved a little:


import std.stdio;

struct Value {
    public enum Type { bool_, long_ }

    private long longVal;
    private bool boolVal;
    private Type type;

    Value opAssign(in long val) pure nothrow {
        longVal = val;
        boolVal = val != 0;

        type = Type.long_;
        return this;
    }

    Value opAssign(in bool val) pure nothrow {
        longVal = val;
        boolVal = val;

        type = Type.bool_;
        return this;
    }

    Type getType() {
        return type;
    }

}

void main() {
    Value data;

    data = 1;
    data.writeln;
    data.getType.writeln;
    assert(data.getType == Value.Type.bool_);

    writeln;

    data = 10;
    data.writeln;
    data.getType.writeln;
    assert(data.getType == Value.Type.long_);
}


Indeed, such implicit casting rules and overload rules are quite arbitrary, and they cause confusion. Functional languages try hard to not have them.

Bye,
bearophile

Reply via email to