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