Steztric
Steztric

Reputation: 2942

Copy arrays of same type and size but different index type in Ada

I am learning Ada at the moment and the current lesson is on arrays. Consider the following program;

procedure Main is
   type T_Bool is array (Boolean) of Integer;
   type T_Intg is array (Integer range 1 .. 2) of Integer;
   A1 : T_Bool := (others => 0);
   A2 : T_Intg := (others => 0);
begin
   -- None of these statements work
   A2 := A1;
   A2 (1 .. 2) := A1 (false .. true);
   A2 := A1 (Boolean'First .. Boolean'Last);
end Main;

According to the Adacore university tutor, it is possible to copy values from one array to another as long as the lengths are the same. In the code snippet, why can you not assign arrays with the same size but different indexing methods, despite the fact that the length is the same?

What is the correct way to copy this across? Is it a case of looping through all indexes in the Boolean type range and copying the corresponding array index across or is there another clever way of doing it?

Upvotes: 0

Views: 2043

Answers (4)

Olivier Pirson
Olivier Pirson

Reputation: 802

In this particular case (or when there are only few values for index), it is possible to assign in once with an aggregate.

A2 := (1 => A1 (False),
       2 => A1 (True));

The complete example: https://gcc.godbolt.org/z/josscfPzh

Upvotes: 0

Steztric
Steztric

Reputation: 2942

Thanks for your answers guys, it is definitely useful information. It goes even deeper than I thought. In the quiz part of the tutorial, I learned that even this is an error

procedure Main is
   type T1 is array (Integer range 1 .. 10) of Integer;
   type T2 is array (Integer range 1 .. 10) of Integer;
   A1 : T1;
   A2 : T2;
begin
   A1 := (others => 0);
   -- Cannot do this
   A2 := A1;
end Main;

Types A2 and A1 may well be defined in the same way, but Ada considers them unrelated and therefore incompatible. It would be the equivalent in C++ of doing

typedef int MyType1;
typedef int MyType2;
MyType1 MyVar1;
MyType2 MyVar2;
// Error - Cannot assign differing types,
// despite them being semantically the same
MyVar2 = MyVar1;

Upvotes: 3

Simon Wright
Simon Wright

Reputation: 25491

The tutorial says, on slide 3, that "all arrays are (doubly) typed", which means that - as usual for different types - you can't assign between your two array types; so yes, you need a loop.

There are "clever" ways using, for example, unchecked conversion; but, really, don't go there!

Upvotes: 5

Andreas Bombe
Andreas Bombe

Reputation: 2470

It is possible to copy arrays without any explicit conversion if they are of the same type and length with only the starting index differing:

procedure Test is
    type T is array (Positive range <>) of Integer;    
    A : T(1 .. 10);
    B : T(21 .. 30);
begin
    A := B;
end Test;

Otherwise it is possible to assign arrays of different type with explicit conversion, but apart from having the same dimensionality (and more, see ARM 4.6) the index types also have to be convertible. Boolean is an enumeration type which is not convertible to Integer.

Explicit conversion with convertible index types would look like this:

procedure Main is
   type TMod is mod 10000;
   type T_Mod is array (TMod range 5000 .. 5001) of Integer;
   type T_Intg is array (Integer range 1 .. 2) of Integer;
   A1 : T_Mod := (others => 0);
   A2 : T_Intg := (others => 0);
begin
   A2 := T_Intg(A1);
end Main;

So yes, it would look like you need to copy elements in a loop in your example.

Upvotes: 3

Related Questions