PROPOSAL: Implicit conversions of integer literals to floating point

Don nospam at nospam.com
Wed Dec 29 22:46:19 PST 2010


BACKGROUND:
D currently uses a very simple rule for parameter matching:
* it matches exactly; OR
* it matches using implicit conversions; OR
* it does not match.

There's an important extra feature: polysemous literals (those which can 
be interpreted in multiple ways) have a preferred interpretation.
So 'a' is char (rather than wchar or dchar); 57 is an int (rather than 
short, byte, long, or uint); and 5.0 is a double (rather than float or 
real).
This feature acts as a tie-breaker in the case of ambiguity. Notice that 
the tie-breaking occurs between closely related types.
If you implement overloading on any two of the possibilities, you would 
always overload the preferred type anyway. (eg, it doesn't make sense to 
overload 'short' and 'uint' but not 'int'). So this all works in a 
satisfactory way.

THE PROBLEM:
Unfortunately, the tie-breaking fails for integer literals used as 
floating-point parameters.
Consider:

void foo(double x) {}

void main()
{
    foo(0);
}

This compiles correctly; 0 converts to double using implicit 
conversions. Now add:
void foo(real x) {}
void foo(float x) {}
And now the existing code won't compile, because 0 is ambiguous.
Adding such overloads is a common activity. It is totally unreasonable 
for it to break existing code, since ANY of the overloads would be 
acceptable.

The language doesn't have any reasonable methods for dealing with this. 
The only one that works at all is to add a  foo(int) overload. But it 
scales very poorly -- if you have 4 floating point parameters, you need 
to add 15 overloads, each with a different combination of int 
parameters. And it's wrong -- it forces you to allow int variables
to be accepted by the function (but not uint, short, long !) when all 
you really need is for literals to be supported.

And no, templates are most definitely not a solution, for many reasons 
(they break even more code, they can't be virtual functions, etc)

This problem has already hit Phobos. We inserted a hack so that sqrt(2) 
will work. But exp(1) doesn't work.
Note that the problems really arise because we've inherited C's rather 
cavalier approach to implicit conversion.

PROPOSAL:

I don't think there's any way around it: we need another level of 
implicit conversion, even if only for the special case of integer 
literals->floating point.
 From the compiler implementation point of view, the simplest way to do 
this would be to add a level between "exact" and "implicit". You might 
call it "matches with preferred conversions", or "match with literal 
conversions".

A match which involves ONLY conversions from integer literals to double, 
should be regarded as a better match than any match which includes any 
other kind of implicit conversion.
As usual, if there is more than one "preferred conversion" match, it is 
flagged as ambiguous.

BTW, I do not think this applies to other literals, or other types. It 
only applies to polsemous types, and int literal->floating point is the 
only such case where there's no tie-breaker in the target type.

It's a very special case, but a very common and important one. It 
applies to *any* overloaded floating point function. So I think that a 
special case in the language is justified.


More information about the Digitalmars-d mailing list