次のプログラムを検討してください。
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;
このような場合、あいまいさなしに実行できる場合、コンパイラは、実際のパラメーターが call に含まれる範囲が最も小さい型のパラメーターを持つルーチンを呼び出します。
しかし、それはここに当てはまるようです。サンプル コード内のプロシージャ コールはどれも、呼び出し内の実パラメータに対応する型を受け入れません。
コンパイラが従う規則について説明しているドキュメントが見つかりません。誰かが私にそのようなドキュメントを教えてもらえますか?
この質問は、次の記事によって促されました。
アップデート
Ken White のコメントに促されて、私は別のプログラムを作成して、さらに奇妙なことを説明しました。
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
UInt64
Delphi 6 では、出力が Delphi 6 に存在しないため、オーバーロードを削除する必要があります。
Unsigned variables passed as parameters:
Byte
Word
Cardinal
Signed variables passed as parameters:
Byte
Byte
Byte
この場合も、どちらの動作も次のステートメントと一致していないように見えます。
このような場合、あいまいさなしに実行できる場合、コンパイラは、実際のパラメーターが call に含まれる範囲が最も小さい型のパラメーターを持つルーチンを呼び出します。