I've created a generic package called Generic_Functions which must be instantiated in similar fashion to the standard Ada.Numerics.Generic_Real_Arrays and has next specification:
with Ada.Numerics.Generic_Real_Arrays;
generic
type Real is digits <>;
package Generic_Functions is
package Real_Arrays is new Ada.Numerics.Generic_Real_Arrays (Real);
use Real_Arrays;
function Sphere_Function (X : Real_Vector) return Real;
-- function Ackley_Function (X : Real_Vector) return Real;
-- function Griewank_Function (X : Real_Vector) return Real;
-- function Rastrigin_Function (X : Real_Vector) return Real;
function Rosenbrock_Function (X : Real_Vector) return Real;
end Generic_Functions;
The difference between the packages is that the functions return with type Real instead of Real'Base.
I want to use it in my main procedure which also uses the Ada.Numerics.Generics_Real_Arrays package, so, at first, I instantiated them like this:
type Real is new Long_Float;
package Real_Arrays is new Ada.Numerics.Generic_Real_Arrays (Real);
use Real_Arrays;
package Real_Functions is new Generic_Functions (Real);
use Real_Functions;
After which I tried to rename one of the Real_Functions, because it's convenient and I plan to move the algorithm to a separate function/package: function F (X : Real_Vector) return Real renames Rosenbrock_Function;
But the compiler yielded error no visible subprogram matches the specification for "F".
At first, I didn't understand why it doesn't work, because both packages were instantiated with same type, and the function signature is the same.
I've managed to resolve this conflict by using the Real_Arrays from the Real_Functions like next code and it worked out fine:
type Real is new Long_Float;
package Real_Functions is new Generic_Functions (Real);
use Real_Functions;
use Real_Arrays;
I guessed that this may occur because of conflicting uses, although it would be weird as no such error was produced, or because both instances of Generic_Real_Arrays are treated as different types, even though they're instantiated with the same type. So I've tried next code but it didn't work for the same reason:
type Real is new Long_Float;
package Real_Arrays is new Ada.Numerics.Generic_Real_Arrays (Real);
use Real_Arrays;
package Real_Functions is new Generic_Functions (Real);
function F (X : Real_Vector) return Real renames Real_Functions.Rosenbrock_Function;
This problem already has a solution, but what if there were other such packages? Even a single one?
There are two ways, that I can think of, to avoid this:
Real and Real_Vector from Generic_Real_Arrays instance (although I couldn't use the Real from it when tried);The latter idea came from this answer.
How to deal with such situations? Even though I'm in control here, this may occur with other people's packages, and then I'm screwed.
EDIT
If possible, can you please also explain, why does some of the subprograms in Ada.Numerics.Generic_Real_Arrays return Real'Base instead of just Real? Why doesn't it make them incompatible?
As you've found, the two different declarations of type Real are incompatible. Instead, declare a formal package "to pass packages to a generic unit."
generic
type Real is digits <>;
with package Real_Arrays is new Ada.Numerics.Generic_Real_Arrays (Real);
package Generic_Functions is
…
end Generic_Functions;
Then you can declare type Real and a concrete instance of Generic_Real_Arrays with which to instantiate Real_Functions.
type Real is new Long_Float;
package Real_Arrays is new Ada.Numerics.Generic_Real_Arrays (Real);
package Real_Functions is new Generic_Functions (Real, Real_Arrays);
A short, complete example is shown below, and a related example may be found here.
-- https://stackoverflow.com/q/79774130/230513
with Ada.Numerics.Generic_Real_Arrays;
with Ada.Text_IO;
procedure Generics is
generic
type Real is digits <>;
with package Real_Arrays is new Ada.Numerics.Generic_Real_Arrays (Real);
use Real_Arrays;
package Generic_Functions is
function Sphere_Function (X : Real_Vector) return Real is (abs (X));
end Generic_Functions;
type Real is digits 6;
package Real_Arrays is new Ada.Numerics.Generic_Real_Arrays (Real);
package Real_Functions is new Generic_Functions (Real, Real_Arrays);
begin
Ada.Text_IO.Put_Line (Real_Functions.Sphere_Function ((1.0, 1.0))'Image);
end Generics;