Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Delphi resolve overloaded functions with integral parameters?

Tags:

delphi

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:

  • ReverseBytes()
  • ZeroConf/Bonjour Code that works in Delphi 7 not working in 2009
  • What's in a Word ... ?

Update

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.

like image 380
David Heffernan Avatar asked Sep 21 '12 08:09

David Heffernan


1 Answers

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
like image 76
kludg Avatar answered Oct 17 '22 23:10

kludg