Hello,
I would like to define a subprogram which has the same name but different type signatures.
In this case, I have the “Generic_Operation” subprogram, which has a “Input : U8_Array” parameter version and a “Input : String” parameter version.
The desired code form is presented here:
with Ada.Text_IO; use Ada.Text_IO;
procedure Desired_Form is
type U8 is mod 2**8;
type U8_Array is array (Natural range <>) of U8;
Operation_A : constant U8 := 1;
Operation_B : constant U8 := 2;
Operation_C : constant U8 := 3;
function Generic_Operation
(Operation : U8;
Input : U8_Array)
return U8_Array
is
begin
return ( 16#FF#, Operation ) & Input;
end Generic_Operation;
function Generic_Operation
(Operation : U8;
Input : String)
return U8_Array
is
begin
return ( 16#01#, Operation );
end Generic_Operation;
begin
declare
Binary_Blob : U8_Array :=
Generic_Operation (Operation_A, (16#00#, 16#C0#)) &
Generic_Operation (Operation_B, "Test");
begin
null;
end;
end Desired_Form;
On compilation, I get the following errors:
desired_form.adb:35:07: ambiguous expression (cannot resolve “Generic_Operation”)
desired_form.adb:35:07: possible interpretation at line 22
desired_form.adb:35:07: possible interpretation at line 13
This implies that the line:
Generic_Operation (Operation_A, (16#00#, 16#C0#)) &
could be used as an input to the U8_Array or the String version of “Generic_Operation”.
With this consideration, I comment out the U8_Array version and recompile this code:
with Ada.Text_IO; use Ada.Text_IO;
procedure String_Form_Only is
type U8 is mod 2**8;
type U8_Array is array (Natural range <>) of U8;
Operation_A : constant U8 := 1;
Operation_B : constant U8 := 2;
Operation_C : constant U8 := 3;
-- function Generic_Operation
-- (Operation : U8;
-- Input : U8_Array)
-- return U8_Array
-- is
-- begin
-- return ( 16#FF#, Operation ) & Input;
-- end Generic_Operation;
function Generic_Operation
(Operation : U8;
Input : String)
return U8_Array
is
begin
return ( 16#01#, Operation );
end Generic_Operation;
begin
declare
Binary_Blob : U8_Array :=
Generic_Operation (Operation_A, (16#00#, 16#C0#)) &
Generic_Operation (Operation_B, "Test");
begin
null;
end;
end String_Form_Only;
Since either interpretation (line 22, or line 13) is possible (at least according to the errors), just having the one interpretation on line 22 should be satisfactory, but on compilation I get the errors:
desired_formtype_test.adb:35:40: expected type "Standard.Character"
string_form_only.adb:35:40: found type universal integer
string_form_only.adb:35:48: expected type "Standard.Character"
string_form_only.adb:35:48: found type universal integer
What I find interesting and somewhat surprising is that the compiler considers the types U8_Array and String different enough to not allow implicit conversion (in the string_form_only.adb example), but not different enough (in the desired.adb example) to match the invocation with the correct subprogram signature.
I can get the compiler to compile the code with no errors if I explicitly identify the array as a U8_Array, as in:
Generic_Operation (Operation_A, U8_Array'(16#00#, 16#C0#) &
I don’t understand why this is necessary in order for the compiler to match the correct subprogram signature for the Desired_Form program code.
I am using gnatmake which is calling gcc version:
x86_64-linux-gnu-gcc-10 (Ubuntu 10.5.0-1ubuntu1~22.04) 10.5.0
Could somebody help explain the nature of these observations?
Thanks,
N