Подтвердить что ты не робот

Как Delphi разрешает перегруженные функции с интегральными параметрами?

Рассмотрим следующую программу:

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.

Вывод при компиляции XE2:

Cardinal
Integer
Smallint

Вывод при компиляции Delphi 6:

Word
Smallint
Shortint

документация заявляет (основное внимание):

Вы можете перейти к перегруженным параметрам процедуры, которые не являются идентичны по типу с таковыми в любой из стандартных деклараций, но которые совместимы с параметрами в более чем одном декларация. Это происходит чаще всего, когда процедура перегружена с разными целыми типами или разными реальными типами - например:

procedure Store(X: Longint); overload;
procedure Store(X: Shortint); overload;

В этих случаях, когда это возможно сделать без двусмысленности, компилятор вызывает процедуру, параметры которой имеют тип с наименьший диапазон, который вмещает фактические параметры в вызове.

Но это, похоже, применимо здесь. Ни один из вызовов процедуры в примере кода не принимает тип, который вмещает фактические параметры в вызове.

Я не могу найти какую-либо документацию, описывающую, какое правило следует компилятору. Может ли кто-нибудь указать мне на такую ​​документацию?

Этот вопрос был вызван следующими статьями:


Update

Подсказка от комментариев Кена Уайта, я написал еще одну программу, чтобы проиллюстрировать еще несколько странностей:

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.

При компиляции с помощью XE2 вывод:

Unsigned variables passed as parameters:
Byte
Word
Cardinal
Uint64

Signed variables passed as parameters:
Uint64
Uint64
Uint64
Uint64

В Delphi 6 мне нужно удалить перегрузку UInt64, так как этот тип не существует на Delphi 6, выход:

Unsigned variables passed as parameters:
Byte
Word
Cardinal

Signed variables passed as parameters:
Byte
Byte
Byte

И снова ни одно поведение не согласуется с утверждением, что:

В этих случаях, когда это возможно сделать без двусмысленности, компилятор вызывает процедуру, параметры которой имеют тип с наименьший диапазон, который вмещает фактические параметры в вызове.

4b9b3361

Ответ 1

Ни тип без знака не может содержать подписанный тип; приведенная документация соответствует вашим примерам - она ​​просто не говорит о том, как компилятор будет их обрабатывать. С другой стороны, подписанный тип может содержать неподписанный тип (SmallInt вмещает Byte, LongInt вмещает Word, Int64 вмещает кардинала):

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:

Small
Long
64
64