Consider the following program:
program IntegerOverloads;
{$APPTYPE CONSOLE}
procedure WordOrCardinal(Value: Word); overload;
begin
Writeln('Word');
end;
procedure WordOrCardinal(Value: Cardinal); overload;
begin
Writeln('Cardinal');
end;
procedure SmallintOrInteger(Value: Smallint); overload;
begin
Writeln('Smallint');
end;
procedure SmallintOrInteger(Value: Integer); overload;
begin
Writeln('Integer');
end;
procedure ShortintOrSmallint(Value: Shortint); overload;
begin
Writeln('Shortint');
end;
procedure ShortintOrSmallint(Value: Smallint); overload;
begin
Writeln('Smallint');
end;
procedure Main;
var
_integer: Integer;
_cardinal: Cardinal;
_word: Word;
begin
WordOrCardinal(_Integer);
SmallintOrInteger(_cardinal);
ShortintOrSmallint(_word);
end;
begin
Main;
Readln;
end.
The output when compiled by XE2 is:
Cardinal
Integer
Smallint
The output when compiled by Delphi 6 is:
Word
Smallint
Shortint
The documentation states (emphasis mine):
You can pass to an overloaded routine parameters that are not identical in type with those in any of the routine's declarations, but that are assignment-compatible with the parameters in more than one declaration. This happens most frequently when a routine is overloaded with different integer types or different real types - for example:
procedure Store(X: Longint); overload; procedure Store(X: Shortint); overload;
In these cases, when it is possible to do so without ambiguity, the compiler invokes the routine whose parameters are of the type with the smallest range that accommodates the actual parameters in the call.
But that does seem to apply here. None of the procedure calls in the example code accept a type that accommodates the actual parameters in the call.
I cannot find any documentation that describes what rule the compiler follows. Can anyone point me to such documentation?
This question was prompted by the following articles:
Prompted by Ken White's comments, I wrote another program to illustrate some more oddities:
program IntegerOverloadsPart2;
{$APPTYPE CONSOLE}
procedure Test(Value: Byte); overload;
begin
Writeln('Byte');
end;
procedure Test(Value: Word); overload;
begin
Writeln('Word');
end;
procedure Test(Value: Cardinal); overload;
begin
Writeln('Cardinal');
end;
procedure Test(Value: Uint64); overload;
begin
Writeln('Uint64');
end;
procedure Main;
var
_byte: Byte;
_shortint: Shortint;
_word: Word;
_smallint: Smallint;
_cardinal: Cardinal;
_integer: Integer;
_uint64: UInt64;
_int64: Int64;
begin
Writeln('Unsigned variables passed as parameters:');
Test(_byte);
Test(_word);
Test(_cardinal);
Test(_uint64);
Writeln;
Writeln('Signed variables passed as parameters:');
Test(_shortint);
Test(_smallint);
Test(_integer);
Test(_int64);
end;
begin
Main;
Readln;
end.
When compiled by XE2 the output is:
Unsigned variables passed as parameters:
Byte
Word
Cardinal
Uint64
Signed variables passed as parameters:
Uint64
Uint64
Uint64
Uint64
On Delphi 6 I have to remove the UInt64
overload since that type does not exist on Delphi 6 the output is:
Unsigned variables passed as parameters:
Byte
Word
Cardinal
Signed variables passed as parameters:
Byte
Byte
Byte
Again neither behaviour looks consistent with the statement that:
In these cases, when it is possible to do so without ambiguity, the compiler invokes the routine whose parameters are of the type with the smallest range that accommodates the actual parameters in the call.
Neither unsigned type can accommodate a signed type; the documentation quoted is consistent with your examples - it just says nothing about how the compiler will treat them. On the other hand a signed type can accommodate an unsigned type (SmallInt accomodates Byte, LongInt accomodates Word, Int64 accomodates Cardinal):
program IntegerOverloadsPart3;
{$APPTYPE CONSOLE}
procedure Test(Value: ShortInt); overload;
begin
Writeln('Short');
end;
procedure Test(Value: SmallInt); overload;
begin
Writeln('Small');
end;
procedure Test(Value: LongInt); overload;
begin
Writeln('Long');
end;
procedure Test(Value: Int64); overload;
begin
Writeln('64');
end;
procedure Main;
var
_byte: Byte;
_word: Word;
_cardinal: Cardinal;
_uint64: UInt64;
begin
Writeln('Unsigned variables passed as parameters:');
Test(_byte);
Test(_word);
Test(_cardinal);
Test(_uint64);
Writeln;
end;
begin
Main;
Readln;
end.
Delphi XE output:
Small
Long
64
64
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With