33
44.. include :: ../../../global.txt
55
6- Unconstrained Arrays
7- --------------------
6+
7+ .. _Adv_Ada_Array_Constraints :
8+
9+ Array constraints
10+ -----------------
11+
12+ Array constraints are important in the declaration of an array because they
13+ define the total size of the array. In fact, arrays must always be constrained.
14+ In this section, we start our discussion with unconstrained array types, and
15+ then continue with constrained arrays and arrays types. Finally, we discuss
16+ the differences between unconstrained arrays and vectors.
17+
18+ .. admonition :: In the Ada Reference Manual
19+
20+ - :arm22: `3.6 Array Types <3-6> `
21+
22+
23+ Unconstrained array types
24+ ~~~~~~~~~~~~~~~~~~~~~~~~~
825
926In the
1027:ref: `Introduction to Ada course <Intro_Ada_Unconstrained_Array_Types >`,
1128we've seen that we can declare array types whose bounds are not fixed: in that
1229case, the bounds are provided when creating objects of those types. For
1330example:
1431
15- .. code :: ada run_button project=Courses.Advanced_Ada.Data_Types.Arrays.Unconstrained_Arrays.Unconstrained_Array_Example
32+ .. code :: ada run_button project=Courses.Advanced_Ada.Data_Types.Arrays.Array_Constraints.Unconstrained_Array_Type
1633
1734 package Measurement_Defs is
1835
@@ -40,8 +57,12 @@ In this example, the :ada:`Measurements` array type from the
4057:ada: `Show_Measurements ` procedure, we declare a constrained object (:ada: `M `)
4158of this type.
4259
60+
61+ Constrained arrays
62+ ~~~~~~~~~~~~~~~~~~
63+
4364The :ref: `Introduction to Ada course <Intro_Ada_Unconstrained_Array_Type_Instance_Bound >`
44- also highlights the fact that the bounds are fixed once an object is declared:
65+ highlights the fact that the bounds are fixed once an object is declared:
4566
4667 Although different instances of the same unconstrained array type can
4768 have different bounds, a specific instance has the same bounds
@@ -52,21 +73,59 @@ also highlights the fact that the bounds are fixed once an object is declared:
5273In the :ada: `Show_Measurements ` procedure above, once we declare :ada: `M `, its
5374bounds are fixed for the whole lifetime of :ada: `M `. We cannot *add * another
5475component to this array. In other words, :ada: `M ` will have 10 components for
55- its whole lifetime.
76+ its whole lifetime:
5677
57- .. admonition :: In the Ada Reference Manual
78+ .. code-block :: ada
5879
59- - :arm22: `3.6 Array Types <3-6> `
80+ M : Measurements (1 .. 10);
81+ -- ^^^^^^^
82+ -- Bounds cannot be changed!
83+
84+
85+ .. _Adv_Ada_Constrained_Array_Type :
86+
87+ Constrained array types
88+ ~~~~~~~~~~~~~~~~~~~~~~~
89+
90+ Note that we could declare constrained array types. Let's rework the previous
91+ example:
92+
93+ .. code :: ada run_button project=Courses.Advanced_Ada.Data_Types.Arrays.Array_Constraints.Constrained_Array_Type
94+
95+ package Measurement_Defs is
96+
97+ type Measurements is
98+ array (1 .. 10) of Float;
99+ -- ^ Bounds are of known and fixed.
100+
101+ end Measurement_Defs;
102+
103+ with Ada.Text_IO; use Ada.Text_IO;
104+
105+ with Measurement_Defs; use Measurement_Defs;
106+
107+ procedure Show_Measurements is
108+ M : Measurements;
109+ -- ^ We cannot change the
110+ -- bounds here!
111+ begin
112+ Put_Line ("First index: " & M'First'Image);
113+ Put_Line ("Last index: " & M'Last'Image);
114+ end Show_Measurements;
115+
116+ In this case, the bounds of the :ada: `Measurements ` type are fixed. Now, we
117+ cannot specify the bounds (or change them) in the declaration of the :ada: `M `
118+ array, as they have already been defined in the type declaration.
60119
61120
62121Unconstrained Arrays vs. Vectors
63- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
122+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
64123
65124If you need, however, the flexibility of increasing the length of an array, you
66- could use vectors instead. This is how we could rewrite the previous example
67- using vectors:
125+ could use the language-defined :ada: ` Vector ` type instead. This is how we could
126+ rewrite the previous example using vectors:
68127
69- .. code :: ada run_button project=Courses.Advanced_Ada.Data_Types.Arrays.Unconstrained_Arrays.Unconstrained_Array_Example
128+ .. code :: ada run_button project=Courses.Advanced_Ada.Data_Types.Arrays.Array_Constraints.Unconstrained_Array_Type_Vs_Vector
70129
71130 with Ada.Containers; use Ada.Containers;
72131 with Ada.Containers.Vectors;
@@ -327,6 +386,7 @@ to highlight the following aspects:
327386.. admonition :: In the Ada Reference Manual
328387
329388 - :arm22: `3.6 Array Types <3-6> `
389+ - :arm22: `3.6.2 Operations of Array Types <3-6-2> `
330390
331391
332392Unconstrained Multidimensional Arrays
@@ -525,16 +585,182 @@ we'd like to highlight the following aspects:
525585 form: :ada: `(others => (others => 0.0)) `.
526586
527587
528- ..
529- TO BE DONE:
588+ Derived array types and array subtypes
589+ --------------------------------------
530590
531- Array Subtypes
532- --------------
591+ .. _Adv_Ada_Derived_Array_Types :
533592
534- .. admonition :: In the Ada Reference Manual
593+ Derived array types
594+ ~~~~~~~~~~~~~~~~~~~
535595
536- - :arm: `3.7 Discriminants <3-7> `
596+ As expected, we can derive from array types by declaring a new type. Let's see
597+ a couple of examples based on the :ada: `Measurement_Defs ` package from previous
598+ sections:
599+
600+ .. code :: ada compile_button project=Courses.Advanced_Ada.Data_Types.Arrays.Derived_Arrays_And_Subtypes.Derived_Arrays
601+
602+ package Measurement_Defs is
603+
604+ type Measurements is
605+ array (Positive range <>) of Float;
606+
607+ --
608+ -- New array type:
609+ --
610+ type Measurements_Derived is
611+ new Measurements;
612+
613+ --
614+ -- New array type with
615+ -- default component value:
616+ --
617+ type Measurements_Def30 is
618+ new Measurements
619+ with Default_Component_Value => 30.0;
620+
621+ --
622+ -- New array type with constraints:
623+ --
624+ type Measurements_10 is
625+ new Measurements (1 .. 10);
626+
627+ end Measurement_Defs;
628+
629+ In this example, we're deriving :ada: `Measurements_Derived ` from the
630+ :ada: `Measurements ` type. In the case of the :ada: `Measurements_Def30 ` type,
631+ we're not only deriving from the :ada: `Measurements ` type, but also setting
632+ the :ref: `default component value <Adv_Ada_Default_Component_Value >` to 30.0.
633+ Finally, in the case of the :ada: `Measurements_10 `, we're deriving from the
634+ :ada: `Measurements ` type and
635+ :ref: `constraining the array type <Adv_Ada_Constrained_Array_Type >` in the
636+ range from 1 to 10.
637+
638+ Let's use these types in a test application:
639+
640+ .. code :: ada run_button project=Courses.Advanced_Ada.Data_Types.Arrays.Derived_Arrays_And_Subtypes.Derived_Arrays
641+
642+ with Measurement_Defs; use Measurement_Defs;
643+
644+ procedure Show_Measurements is
645+ M1, M2 : Measurements (1 .. 10)
646+ := (others => 0.0);
647+
648+ MD : Measurements_Derived (1 .. 10);
649+ MD2 : Measurements_Derived (1 .. 40);
650+ MD10 : Measurements_10;
651+ begin
652+ M1 := M2;
653+ -- ^^^^^^
654+ -- Assignment of arrays of
655+ -- same type.
656+
657+ MD := Measurements_Derived (M1);
658+ -- ^^^^^^^^^^^^^^^^^^^^^^^^^
659+ -- Conversion to derived type for
660+ -- the assignment.
661+
662+ MD10 := Measurements_10 (M1);
663+ -- ^^^^^^^^^^^^^^^^^^^^
664+ -- Conversion to derived type for
665+ -- the assignment.
666+
667+ MD10 := Measurements_10 (MD);
668+ MD10 := Measurements_10 (MD2 (1 .. 10));
669+ end Show_Measurements;
670+
671+ As illustrated by this example, we can assign objects of different array types,
672+ provided that we perform the appropriate type conversions and make sure that
673+ the bounds match.
674+
675+
676+ .. _Adv_Ada_Array_Subtypes :
677+
678+ Array subtypes
679+ ~~~~~~~~~~~~~~
680+
681+ Naturally, we can also declare subtypes of array types. For example:
682+
683+ .. code :: ada compile_button project=Courses.Advanced_Ada.Data_Types.Arrays.Derived_Arrays_And_Subtypes.Array_Subtypes
684+
685+ package Measurement_Defs is
686+
687+ type Measurements is
688+ array (Positive range <>) of Float;
689+
690+ --
691+ -- Simple subtype declaration:
692+ --
693+ subtype Measurements_Sub is Measurements;
694+
695+ --
696+ -- Subtype with constraints:
697+ --
698+ subtype Measurements_10 is
699+ Measurements (1 .. 10);
700+
701+ --
702+ -- Subtype with dynamic predicate
703+ -- (array can only have 20 components
704+ -- at most):
705+ --
706+ subtype Measurements_Max_20 is Measurements
707+ with Dynamic_Predicate =>
708+ Measurements_Max_20'Length <= 20;
709+
710+ --
711+ -- Subtype with constraints and
712+ -- dynamic predicate (first element
713+ -- must be 2.0).
714+ --
715+ subtype Measurements_First_Two is
716+ Measurements (1 .. 10)
717+ with Dynamic_Predicate =>
718+ Measurements_First_Two (1) = 2.0;
719+
720+ end Measurement_Defs;
721+
722+ Here, we're declaring subtypes of the :ada: `Measurements ` type. For example,
723+ :ada: `Measurements_Sub ` is a *simple * subtype of :ada: `Measurements ` type. In
724+ the case of the :ada: `Measurements_10 ` subtype, we're constraining the type to
725+ a range from 1 to 10.
726+
727+ For the :ada: `Measurements_Max_20 ` subtype, we're specifying |mdash | via a
728+ dynamic predicate |mdash | that arrays of this subtype can only have 20
729+ components at most. Finally, for the :ada: `Measurements_First_Two ` subtype,
730+ we're constraining the type to a range from 1 to 10 and requiring that the
731+ first component must have a value of 2.0.
732+
733+ Note that we cannot set the default component value for array subtypes |mdash |
734+ only type declarations are allowed to use that facility.
735+
736+ Let's use these subtypes in a test application:
737+
738+ .. code :: ada run_button project=Courses.Advanced_Ada.Data_Types.Arrays.Derived_Arrays_And_Subtypes.Array_Subtypes
739+ :class: ada-run-expect-failure
740+
741+ with Measurement_Defs; use Measurement_Defs;
742+
743+ procedure Show_Measurements is
744+ M1, M2 : Measurements (1 .. 10)
745+ := (others => 0.0);
746+ MS : Measurements_Sub (1 .. 10);
747+ MD10 : Measurements_10;
748+ M_Max20 : Measurements_Max_20 (1 .. 40);
749+ M_F2 : Measurements_First_Two;
750+ begin
751+ MS := M1;
752+ MD10 := M1;
753+
754+ M_Max20 := (others => 0.0); -- ERROR!
755+
756+ MD10 (1) := 4.0;
757+ M_F2 := MD10; -- ERROR!
758+ end Show_Measurements;
537759
538- .. todo ::
760+ As expected, assignments to objects with different subtypes |mdash | but with
761+ the same parent type |mdash | work fine without conversion. The assignment to
762+ :ada: `M_Max_20 ` fails because of the predicate failure: the predicate requires
763+ that the length be 20 at most, and it's 40 in this case. Also, the
764+ assignment to :ada: `M_F2 ` fails because the predicate requires that the first
765+ element must be set to :ada: `2.0 `, and :ada: `MD10 (1) ` has the value 4.0.
539766
540- - Complete section!
0 commit comments