Reputation: 2942
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
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
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
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
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