Annotated Ada Reference Manual (Ada 202y Draft 1)Legal Information
Contents   Index   References   Search   Previous   Next 

4.1.6 User-Defined Indexing

Static Semantics

1/3
{AI05-0139-2} Given a tagged type T, the following type-related, operational aspects may be specified:
2/5
{AI12-0428-1} Constant_Indexing

This aspect shall be specified by a name that denotes one or more functions declared immediately within the same declaration list in which T, or the declaration completed by T, is declared. All such functions shall have at least two parameters, the first of which is of type T or T'Class, or is an access-to-constant parameter with designated type T or T'Class.
2.a/3
Aspect Description for Constant_Indexing: Defines function(s) to implement user-defined indexed_components.
3/5
{AI12-0428-1} Variable_Indexing

This aspect shall be specified by a name that denotes one or more functions declared immediately within the same declaration list in which T, or the declaration completed by T, is declared. All such functions shall have at least two parameters, the first of which is of type T or T'Class, or is an access parameter with designated type T or T'Class. All such functions shall have a return type that is a reference type (see 4.1.5), whose reference discriminant is of an access-to-variable type.
3.a/3
Reason: We require these functions to return a reference type so that the object returned from the function can act like a variable. We need no similar rule for Constant_Indexing, since all functions return constant objects. 
3.b/3
Aspect Description for Variable_Indexing: Defines function(s) to implement user-defined indexed_components.
3.c/6
Reason: {AI22-0002-1} {AI22-0005-1} For a function that has a parameter of T or access T, a blanket rule in 13.1.1 requires the function to be a primitive operation of T, the wording about the same declaration list is redundant in that case. That 13.1.1 rule does not apply to functions that have parameters of T'Class or access T'Class (which is good, as those can never be primitive); the wording about the declaration list is necessary in that case. 
4/4
{AI12-0104-1} These aspects are inherited by descendants of T (including the class-wide type T'Class).
4.a/3
Ramification: Indexing can be provided for multiple index types by overloading routines with different parameter profiles. For instance, the map containers provide indexing on both cursors and keys by providing pairs of overloaded routines to the Constant_Indexing and Variable_Indexing aspects. 
5/3
{AI05-0139-2} {AI05-0292-1} An indexable container type is (a view of) a tagged type with at least one of the aspects Constant_Indexing or Variable_Indexing specified. An indexable container object is an object of an indexable container type. [A generalized_indexing is a name that denotes the result of calling a function named by a Constant_Indexing or Variable_Indexing aspect.]
5.a/5
Term entry: indexable container type — type that has user-defined behavior for indexing, via the Constant_Indexing or Variable_Indexing aspects
5.1/4
 {AI12-0138-1} The Constant_Indexing and Variable_Indexing aspects are nonoverridable (see 13.1.1).
5.b/5
Reason: {AI12-0160-1} This (and the following Legality Rules) ensures that all descendants of an indexable container type have aspects with the same properties. This prevents generic contract problems with formal derived types.
5.c/4
{AI12-0104-1} {AI12-0138-1} A nonoverridable aspect allows the replacement of the implementation of an indexing function and the addition of a new indexing function for a derived type, but not the removal of an indexing function. This is necessary so that indexing can be used on objects of T'Class. So long as the tag of O is that of its nominal subtype, we do not want T'Class(O)(I) to mean something different than O(I). Thus we cannot allow a change in the function identified. As T'Class(O)(I) expands into a dispatching call, we need to ensure that there is a body for each such function -- but it is OK for that body to be changed from the original body (that's just normal dispatching). 

Legality Rules

6/5
{AI12-0160-1} If an ancestor of a type T is an indexable container type, then any explicit specification of the Constant_Indexing or Variable_Indexing aspects shall be confirming; that is, the specified name shall match the inherited aspect (see 13.1.1).
Paragraphs 7 through 8 were deleted. 
9/5
{AI12-0160-1} In addition to the places where Legality Rules normally apply (see 12.3), this rule applies also in the private part of an instance of a generic unit.
9.1/5
 {AI12-0204-1} A generalized_indexing is illegal if the equivalent prefixed view (see below) is illegal. 

Syntax

10/3
{AI05-0139-2} {AI05-0292-1} generalized_indexing ::= indexable_container_object_prefix actual_parameter_part

Name Resolution Rules

11/3
{AI05-0139-2} {AI05-0292-1} The expected type for the indexable_container_object_prefix of a generalized_indexing is any indexable container type.
11.a/5
Ramification: A prefix can be an implicit_dereference (see 4.1), so an access-to-indexable_container_object can be the prefix (English meaning!) of a generalized_indexing.
12/3
{AI05-0139-2} {AI05-0292-1} If the Constant_Indexing aspect is specified for the type of the indexable_container_object_prefix of a generalized_indexing, then the generalized_indexing is interpreted as a constant indexing under the following circumstances:
13/3
when the Variable_Indexing aspect is not specified for the type of the indexable_container_object_prefix;
14/3
when the indexable_container_object_prefix denotes a constant;
15/3
when the generalized_indexing is used within a primary where a name denoting a constant is permitted.
15.a/3
Ramification: This means it is not interpreted as a constant indexing for the variable_name in the LHS of an assignment (not inside a primary), nor for the name used for an out or in out parameter (not allowed to be a constant), nor for the name in an object renaming (not inside a primary), unless there is no Variable_Indexing aspect defined. 
16/3
Otherwise, the generalized_indexing is interpreted as a variable indexing.
17/3
When a generalized_indexing is interpreted as a constant (or variable) indexing, it is equivalent to a call on a prefixed view of one of the functions named by the Constant_Indexing (or Variable_Indexing) aspect of the type of the indexable_container_object_prefix with the given actual_parameter_part, and with the indexable_container_object_prefix as the prefix of the prefixed view.
17.a/3
Ramification: In other words, the generalized_indexing is equivalent to:
17.b/3
indexable_container_object_prefix.Indexing actual_parameter_part
17.c/4
{AI12-0005-1} where Indexing is the name specified for the Constant_Indexing or Variable_Indexing aspect. This equivalence is then resolved in the normal way; the aspect specifies a name, it does not denote declarations. 
18/4
NOTE   {AI12-0104-1} The Constant_Indexing and Variable_Indexing aspects cannot be redefined when inherited for a derived type, but the functions that they denote can be modified by overriding or overloading. 

Examples

19/5
{AI12-0429-1} Examples of the specification and use of generalized indexing:
20/3
{AI05-0268-1} {AI05-0292-1} type Indexed_Barrel is tagged ...
  with Variable_Indexing => Find;
  -- Indexed_Barrel is an indexable container type,
  -- Find is the generalized indexing operation.
21/3
{AI05-0268-1} function Find (B : aliased in out Indexed_Barrel; Key : String)
   return Ref_Element;
   -- Return a reference to an element of a barrel (see 4.1.5).
22/3
{AI05-0268-1} IB: aliased Indexed_Barrel;
23/3
{AI05-0268-1} -- All of the following calls are then equivalent:
Find (IB,"pear").Data.all := Element'(...); -- Traditional call
IB.Find ("pear").Data.all := Element'(...); -- Call of prefixed view
IB.Find ("pear")          := Element'(...); -- Implicit dereference (see 4.1.5)
IB      ("pear")          := Element'(...); -- Implicit indexing and dereference
IB      ("pear").Data.all := Element'(...); -- Implicit indexing only

Extensions to Ada 2005

23.a/3
{AI05-0139-2} Aspects Constant_Indexing and Variable_Indexing, and the generalized_indexing syntax are new. 

Incompatibilities With Ada 2012

23.b/5
{AI12-0160-1} Correction: Prevented a derived type from specifying Constant_Indexing if the ancestor specified Variable_Indexing (and vice versa). This is necessary to preserve the intent that for an object Obj whose tag is that of its nominal subtype, T'Class(Obj)(I) always has the same meaning as Obj(I). Situations like this should be rare in practice; most types will either define both aspects or neither.
23.c/5
{AI12-0204-1} Correction: Added a rule that a generalized indexing is illegal if the equivalent prefixed view would be illegal. If the prefixed view would be illegal for any reason, Ada 2012 would have allowed the generalized indexing while Ada 2022 does not. This violated the principle that a generalized indexing and the equivalent prefixed view have the same semantics; practically, the code may not have worked anyway if a compiler implemented generalized indexing by code expansion into the canonical form. Thus, such code wasn't practically portable.

Wording Changes from Ada 2012

23.d/4
{AI12-0104-1} Corrigendum: Converted confusing and unnecessary normative wording about "overriding an aspect" into a note.
23.e/4
{AI12-0138-1} Corrigendum: Defined Constant_Indexing and Variable_Indexing to be nonoveridable. This is merely a new description for Legality Rules which already applied to these aspects.
23.f/5
{AI12-0428-1} Correction: Allowed the completion of a private type to use declarations from either the visible part or the private part. 

Contents   Index   References   Search   Previous   Next 
Ada-Europe Ada 2005 and 2012 Editions sponsored in part by Ada-Europe