[Issue 9999] Integer literal 0 and 1 should prefer integer type in overload resolution

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Sun Feb 1 14:43:05 PST 2015


https://issues.dlang.org/show_bug.cgi?id=9999

--- Comment #14 from Jonathan M Davis <issues.dlang at jmdavisProg.com> ---
(In reply to Denis Shelomovskij from comment #12)
> Also this issue has to terrible consequences:
> 1. `f(bool)` is preferred over `f(T)(T)`
> 2. expressions like `4 - 3` triggers the issue too
> 
> 
> This code should run fine:
> ---
> int f1(bool) { return 1; }
> int f1(T)(T) { return 2; }
> 
> void f2()(bool) { static assert(0); }
> void f2(T)(T) { }
> 
> void main()
> {
>     assert(f1(    0) == 2);  // fails
>     assert(f1(    1) == 2);  // fails
>     assert(f1(   1U) == 2);  // fails
>     assert(f1(4 - 3) == 2);  // fails
> 
>     f2(    0);  // triggers `static assert(0)`
>     f2(    1);  // ditto
>     f2(   1U);  // ditto
>     f2(4 - 3);  // ditto
> }
> ---

That seems pretty bad. It's things like that which make it so that I think that
it's usually a bad idea to overload templated and non-templated functions. It's
_far_ too easy to have the non-templated one called when you wanted the
templated one to be called.

> A workaround is to use `f(T : bool)(T)` specialization instead of `f(bool)`.

That's also probematic in general, because then stuff like user-defined types
which implicitly convert to bool could qualify, and frequently such functions
do not take that into account. It can certainly be made to work, and I think
that it's great that we can do it, but in general, I think that using implicit
conversions in template constraints and specializations is a mistake. If you
really want it to take bool though, you can just make the type exact with a
template constraint. e.g.

void f1(T)(T t)
    if(is(T == bool))
{}

It's ugly that you would have to do that, but it should make it so that the
function will only work if it's actually give a bool, which is what you're
looking for.

Regardless, I think that it's a mistake for VRP to apply to bool. As far as I
can tell, it's never of any use, and it's error-prone. IMHO, the fact that
foo(1) would call a boolean overload instead of a long overload (which pretty
much no one expects) shows that the current behavior is a mistake. And your
example is far worse. I suspect that most of us would have run into exactly the
same problem and be very surprised by the current behavior.

--


More information about the Digitalmars-d-bugs mailing list