1

Given the following array definition:

type A is array (1 .. 10) of INTEGER;

And the following generic:

generic
   type LENGTH_T is range <>;
   type INDEX_T is (<>);
   type ELEMENT_T is limited private;
   type ARRAY_T is array (INDEX_T) of ELEMENT_T;
function LIST_IMAGE
  (LENGTH : in LENGTH_T;
   ITEMS  : in ARRAY_T)
   return STRING;

Is there a way to instantiate LIST_IMAGE for A? What do I need to put for the type of the index?

function ARRAY_IMAGE is new LIST_IMAGE
  (LENGTH_T  => NATURAL,
   INDEX_T   => ???,
   ELEMENT_T => INTEGER,
   ARRAY_T   => A);
Markus
  • 3,155
  • 2
  • 23
  • 33

3 Answers3

7

The solution is that an anonymous integer range always becomes an Integer subtype:

with Ada.Text_IO;

procedure Range_Of_Universal_Integer is

   type A is array (1 .. 10) of Integer;

   generic
      type Length_T is range <>;
      type Index_T is (<>);
      type Element_T is limited private;
      type Array_T is array (Index_T) of Element_T;
   function List_Image (Length : in Length_T;
                        Items  : in Array_T) return String;

   function List_Image (Length : in Length_T;
                        Items  : in Array_T) return String is
      pragma Unreferenced (Length, Items);
   begin
      return "Hello";
   end List_Image;

   subtype A_Lengths is Integer range 0 .. A'Length;
   subtype A_Range   is Integer range A'Range;

   function Image is
     new List_Image (Length_T  => A_Lengths,
                     Index_T   => A_Range,
                     Element_T => Integer,
                     Array_T   => A);

begin
   Ada.Text_IO.Put_Line (Image (Length => 0,
                                Items  => A'(others => 0)));
end Range_Of_Universal_Integer;
Jacob Sparre Andersen
  • 6,733
  • 17
  • 22
  • Thanks. I previously tried `Integer` instead of `A_Range` but I didn't realize that I am simply missing the range constraints. – Markus Aug 01 '18 at 08:27
2

Jacob already gave a full answer, but wanted to add an alternative subtype declaration:

type A is array (1 .. 10) of Integer;

subtype A_Lengths is Integer range 0 .. A'Length;
subtype A_Range   is Integer range A'Range;

function Image is
     new List_Image (Length_T  => A_Lengths,
                     Index_T   => A_Range,
                     Element_T => Integer,
                     Array_T   => A);
Jere
  • 3,124
  • 7
  • 15
  • Unfortunately this one is only correct because `A'Range` happens to start at 1. If you want to derive `A_Lengths` from `A`, you have to do it like this: `subtype A_Lengths is Integer range A'First - 1 .. A'Last;` – Jacob Sparre Andersen Aug 01 '18 at 08:29
  • I like the idea of your subtype definitions for `A_Length` and `A_Range`. – Markus Aug 01 '18 at 08:34
  • @JacobSparreAndersen Why is the subtype definition for `A_Length` not correct? `A_Range` is not related to `A_Length` after all. – Markus Aug 01 '18 at 08:38
  • Sorry. I misread the meaning of the types. @Jere is correct in his formulation. I should correct my example. – Jacob Sparre Andersen Aug 01 '18 at 12:42
0

Simplify your problem by creating a named subtype for your array index.

subtype Index_Type is Integer range 1..10;
type A is array(Index_Type) of Integer;

function Array_Image is new List_Image 
  ( Length_T  => Natural,
    Index_T   => Index_Type,
    Element_T => Integer,
    Array_T   => A);
Jim Rogers
  • 4,822
  • 1
  • 11
  • 24
  • Thanks. Would have done that if I would be able to modify the definition of A, but unfortunately I can't. – Markus Jul 31 '18 at 14:41