4.1.6 User-Defined Indexing
Static Semantics
{
AI05-0139-2}
Given a tagged type
T, the following type-related, operational
aspects may be specified:
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.
Aspect Description for Constant_Indexing:
Defines function(s) to implement user-defined
indexed_components.
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.
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.
Aspect Description for Variable_Indexing:
Defines function(s) to implement user-defined
indexed_components.
{
AI12-0104-1}
These aspects are inherited by descendants of
T (including the
class-wide type
T'Class).
[The aspects shall
not be overridden, but the functions they denote may be.]
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.
{
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.]
Term entry: indexable
container type — type that has user-defined behavior for indexing,
via the Constant_Indexing or Variable_Indexing aspects
{
AI12-0138-1}
The Constant_Indexing and Variable_Indexing aspects
are nonoverridable (see 13.1.1).
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.
{
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).
Paragraphs
6 through 9 were deleted.
Legality Rules
{
AI05-0139-2}
{
AI12-0138-1}
{
AI12-0160-1}
The Constant_Indexing or Variable_Indexing aspect
shall not be specified: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).
on a derived type if the
parent type has the corresponding aspect specified or inherited; or
Paragraphs
7 through 8 were deleted.
{
AI12-0160-1}
In addition to the places where
Legality Rules normally apply (see 12.3),
these rules apply also in the private part of an instance of a generic
unit. 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.
Ramification: In
order to enforce these rules without breaking privacy, we cannot allow
a tagged private type to have hidden indexing aspects. There is no problem
if the private type is not tagged (as the indexing aspects cannot be
specified on descendants in that case).
We don't need an assume-the-worst
rule as deriving from formal tagged types is not allowed in generic bodies.
Syntax
Name Resolution Rules
when the Variable_Indexing aspect is not specified
for the type of the
indexable_container_object_prefix;
when the
indexable_container_object_prefix
denotes a constant;
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.
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.
{
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.
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
{
AI12-0429-1}
Examples of the specification and use of generalized
indexing:
{
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.
{
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).
{
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
Incompatibilities With Ada 2012
{
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.
{
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
{
AI12-0104-1}
Corrigendum: Converted confusing and unnecessary
normative wording about "overriding an aspect" into a note.
{
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.
{
AI12-0428-1}
Correction: Allowed the completion of a
private type to use declarations from either the visible part or the
private part.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe