5.5.1 User-Defined Iterator Types
Static Semantics
{
AI05-0139-2}
The following language-defined generic library package exists:
{
AI12-0241-1}
generic
type Cursor;
with function Has_Element (Position : Cursor)
return Boolean;
package Ada.Iterator_Interfaces
is
with Pure, Nonblocking => False is pragma Pure (Iterator_Interfaces);
type Forward_Iterator
is limited interface;
function First (Object : Forward_Iterator)
return Cursor
is abstract;
function Next (Object : Forward_Iterator; Position : Cursor)
return Cursor
is abstract;
type Reversible_Iterator
is limited interface and Forward_Iterator;
function Last (Object : Reversible_Iterator)
return Cursor
is abstract;
function Previous (Object : Reversible_Iterator; Position : Cursor)
return Cursor
is abstract;
{
AI12-0266-1}
type Parallel_Iterator is limited interface and Forward_Iterator;
{
AI12-0266-1}
function Is_Split (Object : Parallel_Iterator)
return Boolean is abstract;
{
AI12-0266-1}
procedure Split_Into_Chunks (Object : in out Parallel_Iterator;
Max_Chunks : in Chunk_Index) is abstract
with Pre'Class => not Object.Is_Split or else raise Program_Error,
Post'Class => Object.Is_Split and then
Object.Chunk_Count <= Max_Chunks;
{
AI12-0266-1}
function Chunk_Count (Object : Parallel_Iterator)
return Chunk_Index is abstract
with Pre'Class => Object.Is_Split or else raise Program_Error;
{
AI12-0266-1}
function First (Object : Parallel_Iterator;
Chunk : Chunk_Index) return Cursor is abstract
with Pre'Class => (Object.Is_Split and then
Chunk <= Object.Chunk_Count)
or else raise Program_Error;
{
AI12-0266-1}
function Next (Object : Parallel_Iterator;
Position : Cursor;
Chunk : Chunk_Index) return Cursor is abstract
with Pre'Class => (Object.Is_Split and then
Chunk <= Object.Chunk_Count)
or else raise Program_Error;
{
AI12-0266-1}
type Parallel_Reversible_Iterator is limited interface
and Parallel_Iterator and Reversible_Iterator;
end Ada.Iterator_Interfaces;
Reason: {
AI12-0241-1}
This package must allow blocking (Nonblocking =>
False) for compatibility. The purpose of this package is to provide a
template for overriding user-defined routines; and such routines can
only allow blocking if the root type does so. Users can still declare
their overridding routines nonblocking if they wish.
{
AI05-0139-2}
{
AI12-0266-1}
An
iterator type is a type descended from the Forward_Iterator
interface from some instance of Ada.Iterator_Interfaces.
A
reversible iterator type is a type descended from the Reversible_Iterator
interface from some instance of Ada.Iterator_Interfaces.
A parallel iterator type
is a type descended from the Parallel_Iterator interface from some instance
of Ada.Iterator_Interfaces. A type descended from the Parallel_Reversible_Iterator
interface from some instance of Ada.Iterator_Interfaces is both a parallel
iterator type and a reversible iterator type. An
iterator object
is an object of an iterator type.
A
reversible
iterator object is an object of a reversible iterator type.
A parallel iterator object is an object
of a parallel iterator type. The formal subtype
Cursor from the associated instance of Ada.Iterator_Interfaces is the
iteration cursor subtype for the iterator type.
{
AI05-0139-2}
{
AI05-0292-1}
The following type-related operational aspects may be specified for an
indexable container type
T (see
4.1.6):
This aspect is specified by a
name
that denotes exactly one function declared immediately within the same
declaration list in which
T, or the declaration
completed by T, is declared, whose first parameter is of
type
T or
T'Class or an access parameter whose designated
type is type
T or
T'Class, whose other parameters, if any,
have default expressions, and whose result type is an iterator type.
This function is the
default iterator function for
T.
Its result subtype is the
default iterator subtype for
T.
The iteration cursor subtype for the default iterator subtype is the
default cursor subtype for
T.
This aspect is inherited by descendants of type T (including T'Class).
Aspect Description for Default_Iterator:
Default iterator to be used in for loops.
This aspect is specified by a
name
that denotes a subtype. This is the
default element subtype for
T.
This aspect is inherited by descendants of type T (including T'Class).
Aspect Description for Iterator_Element:
Element type to be used for user-defined iterators.
This aspect is specified by a name
that denotes a type T2 with the following properties:
T2 is declared
in the same compilation unit as T;
T2 is an
iterable container type;
T2 has a
single discriminant which is an access discriminant designating T;
and
The default iterator
subtypes for T and T2 statically match.
This aspect is never
inherited[, even by T'Class].
Reason: Iterator_View
allows specifying an alternative type to be automatically used by container
element iterators; see 5.5.2. This allows
setting state for an iteration only once rather than for each individual
reference.
Ramification: Since
Iterator_View is not inherited, it does not apply to T'Class.
Otherwise, the type of the iterator object would not be known at compile-time
(since it necessarily has to be different for each descendant).
Aspect Description
for Iterator_View: An
alternative type to used for container element iterators.
This paragraph was
deleted.{
AI12-0111-1}
These aspects are inherited by descendants of type
T (including T'Class).
{
AI05-0139-2}
{
AI05-0292-1}
{
AI12-0266-1}
An
iterable container type is an indexable container type with
specified Default_Iterator and Iterator_Element aspects.
A
reversible iterable container type is an iterable container
type with the default iterator type being a reversible iterator type.
A parallel iterable container type is an
iterable container type with the default iterator type being a parallel
iterator type. An
iterable container object
is an object of an iterable container type.
A
reversible
iterable container object is an object of a reversible iterable container
type.
A parallel iterable
container object is an object of a parallel iterable container type.
Term entry: iterable
container type — type that has user-defined behavior for iteration,
via the Default_Iterator and Iterator_Element aspects
{
AI12-0138-1}
The Default_Iterator and Iterator_Element aspects
are nonoverridable (see 13.1.1).
Reason: This ensures
that all descendants of an iterable container type have aspects with
the same properties. This prevents generic contract problems with formal
derived types.
Legality Rules
{
AI05-0139-2}
{
AI05-0292-1}
The Constant_Indexing aspect (if any) of an iterable container type
T
shall denote exactly one function with the following properties:
the result type of the function is covered by the
default element type of
T or is a reference type (see
4.1.5)
with an access discriminant designating a type covered by the default
element type of
T;
the type of the second parameter of the function
covers the default cursor type for T;
if there are more than two parameters, the additional
parameters all have default expressions.
This function (if any) is the
default constant
indexing function for
T.
Ramification: This does not mean that
Constant_Indexing has to designate only one subprogram, only that there
is only one routine that meets all of these properties. There can be
other routines designated by Constant_Indexing, but they cannot have
the profile described above. For instance, map containers have a version
of Constant_Indexing that takes a key instead of a cursor; this is allowed.
{
AI05-0139-2}
{
AI05-0292-1}
The Variable_Indexing aspect (if any) of an iterable container type
T
shall denote exactly one function with the following properties:
the result type of the function is a reference
type (see
4.1.5) with an access discriminant
designating a type covered by the default element type of
T;
the type of the second parameter of the function
covers the default cursor type for T;
if there are more than two parameters, the additional
parameters all have default expressions.
This function (if any) is the
default variable
indexing function for
T.
Erroneous Execution
{
AI12-0354-1}
A call on the First or Next operation on a given
Parallel_Iterator object with a given Chunk value, which does not propagate
an exception, should return a Cursor value that either yields False when
passed to Has_Element, or that identifies an element distinct from any
Cursor value returned by a call on a First or Next operation on the same
Parallel_Iterator object with a different Chunk value. If the First or
Next operations with a Chunk parameter behave in any other manner, execution
is erroneous.
Reason: This describes
the expectations from a user-written parallel iterator. If the expectations
are not met, execution is erroneous so that implementations do not need
to go to heroic efforts to avoid problems caused by bad iterators. This
is similar to the handling of storage pools, see 13.11.
Extensions to Ada 2005
{
AI05-0139-2}
User-defined iterator types are new in Ada 2012.
Incompatibilities With Ada 2012
{
AI12-0138-1}
Corrigendum: Defined
Default_Iterator and Iterator_Element to be nonoveridable, which makes
redefinitions and hiding of these aspects illegal. It's possible that
some program could violate one of these new restrictions, but in most
cases this can easily be worked around by using overriding rather than
redefinition.
{
AI12-0266-1}
Various new types and subprograms are newly added
to Ada.Iterator_Interfaces. Therefore, a use clause conflict is possible;
see the introduction of Annex A for more on this
topic.
Extensions to Ada 2012
{
AI12-0111-1}
Aspect Iterator_View is new;
it allows container element iterators to set the tampering state once
rather than for each use of the element.
{
AI12-0266-1}
{
AI12-0354-1}
Parallel iterator interfaces are new; they allow
user-defined parallel loops to be defined.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe