3.7 Discriminants
A
composite type (other than an array or interface type) can have discriminants,
which parameterize the type. A
known_discriminant_part
specifies the discriminants of a composite type. A discriminant of an
object is a component of the object, and is either of a discrete type
or an access type. An
unknown_discriminant_part
in the declaration of a view of a type specifies that the discriminants
of the type are unknown for the given view; all subtypes of such a view
are indefinite subtypes.
Syntax
unknown_discriminant_part ::= (<>)
Name Resolution Rules
Legality Rules
A
discriminant_part
is only permitted in a declaration for a composite type that is not an
array or interface type (this includes generic formal types). A type
declared with a
known_discriminant_part
is called a
discriminated type,
as is a type
that inherits (known) discriminants.
A
discriminant_specification
for an access discriminant may have a
default_expression
only in the declaration for a task or protected type, or for a type that
is a descendant of an explicitly limited record type. 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.
This paragraph was
deleted.
The parent subtype shall be constrained;
If the parent type is not a tagged type, then each
discriminant of the derived type shall be used in the constraint defining
the parent subtype;
If a discriminant is used in the constraint defining
the parent subtype, the subtype of the discriminant shall be statically
compatible (see
4.9.1) with the subtype of
the corresponding parent discriminant.
The type of the
default_expression,
if any, for an access discriminant shall be convertible to the anonymous
access type of the discriminant (see
4.6).
Static Semantics
For a type defined by a
derived_type_definition,
each discriminant of the parent type is either inherited, constrained
to equal some new discriminant of the derived type, or constrained to
the value of an expression.
When inherited or constrained
to equal some new discriminant, the parent discriminant and the discriminant
of the derived type are said to
correspond. Two discriminants
also correspond if there is some common discriminant to which they both
correspond. A discriminant corresponds to itself as well.
If
a discriminant of a parent type is constrained to a specific value by
a
derived_type_definition,
then that discriminant is said to be
specified by that
derived_type_definition.
A
constraint
that appears within the definition of a discriminated type
depends
on a discriminant of the type if it names the discriminant as a bound
or discriminant value. A
component_definition
depends on a discriminant if its
constraint
depends on the discriminant, or on a discriminant that corresponds to
it.
A
component
depends on a discriminant if:
It is declared in a
variant_part
that is governed by the discriminant; or
It is a subcomponent of a component that depends
on the discriminant.
Each value of a discriminated type includes a value
for each component of the type that does not depend on a discriminant;
this includes the discriminants themselves. The values of discriminants
determine which other component values are present in the value of the
discriminated type.
A
type declared with a
known_discriminant_part
is said to have
known discriminants; its first subtype is unconstrained.
A type declared with an
unknown_discriminant_part
is said to have
unknown discriminants. A type declared without
a
discriminant_part
has no discriminants, unless it is a derived type; if derived, such a
type has the same sort of discriminants (known, unknown, or none) as
its parent (or ancestor) type. A tagged class-wide type also has unknown
discriminants.
Any subtype of
a type with unknown discriminants is an unconstrained and indefinite
subtype (see
3.2 and
3.3).
Dynamic Semantics
52 If a discriminated type has
default_expressions
for its discriminants, then unconstrained variables of the type are permitted,
and the values of the discriminants can be changed by an assignment to
such a variable. If defaults are not provided for the discriminants,
then all variables of the type are constrained, either by explicit constraint
or by their initial value; the values of the discriminants of such a
variable cannot be changed after initialization.
53 The
default_expression
for a discriminant of a type is evaluated when an object of an unconstrained
subtype of the type is created.
54 Assignment to a discriminant of an object
(after its initialization) is not allowed, since the name of a discriminant
is a constant; neither
assignment_statements
nor assignments inherent in passing as an
in out or
out
parameter are allowed. Note however that the value of a discriminant
can be changed by assigning to the enclosing object, presuming it is
an unconstrained variable.
55 A discriminant that is of a named access
type is not called an access discriminant; that term is used only for
discriminants defined by an
access_definition.
Examples
Examples of discriminated
types:
type Buffer(Size : Buffer_Size := 100)
is --
see 3.5.4
record
Pos : Buffer_Size := 0;
Value : String(1 .. Size);
end record;
type Matrix_Rec(Rows, Columns : Integer)
is
record
Mat : Matrix(1 .. Rows, 1 .. Columns); --
see 3.6
end record;
type Square(Side : Integer) is new
Matrix_Rec(Rows => Side, Columns => Side);
type Double_Square(Number : Integer) is
record
Left : Square(Number);
Right : Square(Number);
end record;
task type Worker(Prio : System.Priority; Buf :
access Buffer)
is
--
discriminants used to parameterize the task type (see 9.1)
pragma Priority(Prio); --
see D.1
entry Fill;
entry Drain;
end Worker;