On Monday, 12 November 2018 at 22:07:39 UTC, Walter Bright wrote:
On 11/12/2018 12:34 PM, Neia Neutuladh wrote:
Tell me more about this "consistency".
int f(short s) { return 1; }
int f(int i) { return 2; }
enum : int { a = 0 }
enum A : int { a = 0 }
pragma (msg, f(a)); // calls f(int)
pragma (msg, f(A.a)); // calls f(short)
I.e. it's consistent.
Here's how it works:
f(a): `a` is a manifest constant of type `int`, and `int` is an
exact match for f(int), and f(short) requires an implicit
conversion. The exact match of f(int) is better.
f(A.a): `a` is an enum of type `A`. `A` gets implicitly
converted to `int`. The `int` then gets exact match to f(int),
and an implicit match to f(short). The sequence of conversions
is folded into one according to:
<implicit conversion> <exact> => <implicit
conversion>
<implicit conversion> <implicit conversion> => <implicit
conversion>
Both f(int) and f(short) match, because implicit conversions
rank the same. To disambiguate, f(short) is pitted against
f(int) using partial ordering rules,
which are:
Can a short be used to call f(int)? Yes.
Can an int be used to call f(short)? No.
So f(short) is selected, because the "Most Specialized"
function is selected when there is an ambiguous match.
Note: the "most specialized" partial ordering rules are
independent of the arguments being passed.
---
One could have <implicit conversion><exact> be treated as
"better than" <implicit conversion><implicit conversion>, and
it sounds like a good idea, but even C++, not known for
simplicity, tried that and had to abandon it as nobody could
figure it out once the code examples got beyond trivial
examples.
This just seems like a bug to me. Any sane human being would
expect all these functions to output the same thing. But it
entirely depends on how you use it.
import std.stdio;
void foo(byte v) { writeln("byte ", v); }
void foo(int v) { writeln("int ", v); }
enum : int { a = 127 }
enum A : int { a = 127 }
void main()
{
A v = A.a;
foo(A.a); // byte 127 < These two are probably the best
showcase of what's wrong
foo(v); // int 127 < same values being passed with same
type but different result
foo(a); // int 127
foo(127); // int 127
}
https://run.dlang.io/is/aARCDo