Contents Index Previous Next
4.5.2 Relational Operators and Membership Tests
1
[
{relational operator}
{operator (relational)}
{comparison operator: See relational
operator} {equality operator}
{operator (equality)}
The
equality operators = (equals) and /= (not
equals) are predefined for nonlimited types.
{ordering
operator} {operator (ordering)}
The other
relational_operators
are the
ordering operators < (less than), <= (less than
or equal), > (greater than), and >= (greater than or equal).
{=
operator} {operator (=)}
{equal operator} {operator
(equal)} {/= operator}
{operator (/=)} {not
equal operator} {operator
(not equal)} {< operator}
{operator (<)} {less
than operator} {operator
(less than)} {<= operator}
{operator (<=)} {less
than or equal operator} {operator
(less than or equal)} {>
operator} {operator (>)}
{greater than operator}
{operator (greater than)}
{>= operator} {operator
(>=)} {greater than
or equal operator} {operator
(greater than or equal)} {discrete
array type} The ordering operators are
predefined for scalar types, and for
discrete array types, that
is, one-dimensional array types whose components are of a discrete type.
1.a
Ramification: The equality
operators are not defined for every nonlimited type -- see below
for the exact rule.
2
{membership test}
{in (membership test)}
{not in (membership test)}
A
membership test, using
in or
not
in, determines whether or not a value belongs to a given subtype
or range, or has a tag that identifies a type that is covered by a given
type. Membership tests are allowed for all types.]
Name Resolution Rules
3
{expected type (membership test
simple_expression) [partial]} {tested
type (of a membership test)} The
tested
type of a membership test is the type of the
range
or the type determined by the
subtype_mark.
If the tested type is tagged, then the
simple_expression
shall resolve to be of a type that covers or is covered by the tested
type; if untagged, the expected type for the
simple_expression
is the tested type.
3.a
Reason: The part of the
rule for untagged types is stated in a way that ensures that operands
like null are still legal as operands of a membership test.
3.b
The significance of ``covers or
is covered by'' is that we allow the simple_expression
to be of any class-wide type that covers the tested type, not just the
one rooted at the tested type.
Legality Rules
4
For a membership test, if the simple_expression
is of a tagged class-wide type, then the tested type shall be (visibly)
tagged.
4.a
Ramification: Untagged
types covered by the tagged class-wide type are not permitted. Such types
can exist if they are descendants of a private type whose full type is
tagged. This rule is intended to avoid confusion since such derivatives
don't have their ``own'' tag, and hence are indistinguishable from one
another at run time once converted to a covering class-wide type.
Static Semantics
5
The result type of a membership test is the predefined
type Boolean.
6
The equality operators
are predefined for every specific type T that is not limited,
and not an anonymous access type, with the following specifications:
7
function "=" (Left, Right : T) return Boolean
function "/="(Left, Right : T) return Boolean
8
The ordering operators
are predefined for every specific scalar type T, and for every
discrete array type T, with the following specifications:
9
function "<" (Left, Right : T) return Boolean
function "<="(Left, Right : T) return Boolean
function ">" (Left, Right : T) return Boolean
function ">="(Left, Right : T) return Boolean
Dynamic Semantics
10
For discrete types, the predefined relational
operators are defined in terms of corresponding mathematical operations
on the position numbers of the values of the operands.
11
For real types, the predefined relational operators
are defined in terms of the corresponding mathematical operations on
the values of the operands, subject to the accuracy of the type.
11.a
Ramification: For floating point
types, the results of comparing nearly equal values depends on the accuracy
of the implementation (see G.2.1, ``Model
of Floating Point Arithmetic'' for implementations that support the Numerics
Annex).
11.b
Implementation Note: On
a machine with signed zeros, if the generated code generates both plus
zero and minus zero, plus and minus zero must be equal by the predefined
equality operators.
12
Two access-to-object values are equal if they
designate the same object, or if both are equal to the null value of
the access type.
13
Two access-to-subprogram values are equal if
they are the result of the same evaluation of an Access
attribute_reference,
or if both are equal to the null value of the access type. Two access-to-subprogram
values are unequal if they designate different subprograms.
{unspecified
[partial]} [It is unspecified whether two
access values that designate the same subprogram but are the result of
distinct evaluations of Access
attribute_references
are equal or unequal.]
13.a
Reason: This allows each
Access attribute_reference for a
subprogram to designate a distinct ``wrapper'' subprogram if necessary
to support an indirect call.
14
{equality operator (special
inheritance rule for tagged types)} For
a type extension, predefined equality is defined in terms of the primitive
[(possibly user-defined)] equals operator of the parent type and of any
tagged components of the extension part, and predefined equality for
any other components not inherited from the parent type.
14.a
Ramification: Two values
of a type extension are not equal if there is a variant_part
in the extension part and the two values have different variants
present. This is a ramification of the requirement that a discriminant
governing such a variant_part has
to be a ``new'' discriminant, and so has to be equal in the two values
for the values to be equal. Note that variant_parts
in the parent part need not match if the primitive equals operator for
the parent type considers them equal.
15
For a private type, if its full type is tagged,
predefined equality is defined in terms of the primitive equals operator
of the full type; if the full type is untagged, predefined equality for
the private type is that of its full type.
16
{matching
components} For other composite types, the predefined
equality operators [(and certain other predefined operations on composite types
-- see
4.5.1 and
4.6)]
are defined in terms of the corresponding operation on
matching components,
defined as follows:
17
- For two composite objects or values of the same non-array
type, matching components are those that correspond to the same component_declaration
or discriminant_specification;
18
- For two one-dimensional arrays of the same type, matching
components are those (if any) whose index values match in the following
sense: the lower bounds of the index ranges are defined to match, and
the successors of matching indices are defined to match;
19
- For two multidimensional arrays of the same type, matching
components are those whose index values match in successive index positions.
20
The analogous definitions apply if the types
of the two objects or values are convertible, rather than being the same.
20.a
Discussion: Ada 83 seems to omit
this part of the definition, though it is used in array type conversions. See
4.6.
21
Given the above
definition of matching components, the result of the predefined equals
operator for composite types (other than for those composite types covered
earlier) is defined as follows:
22
- If there are no components, the result is defined to be
True;
23
- If there are unmatched components, the result is defined
to be False;
24
- Otherwise, the result is defined in terms of the primitive
equals operator for any matching tagged components, and the predefined
equals for any matching untagged components.
24.a
Reason: This asymmetry between tagged
and untagged components is necessary to preserve upward compatibility and corresponds
with the corresponding situation with generics, where the predefined operations
``reemerge'' in a generic for untagged types, but do not for tagged types. Also,
only tagged types support user-defined assignment (see 7.6),
so only tagged types can fully handle levels of indirection in the implementation
of the type. For untagged types, one reason for a user-defined equals operator
might be to allow values with different bounds or discriminants to compare equal
in certain cases. When such values are matching components, the bounds or discriminants
will necessarily match anyway if the discriminants of the enclosing values match.
24.b
Ramification: Two null
arrays of the same type are always equal; two null records of the same
type are always equal.
24.c
Note that if a composite object
has a component of a floating point type, and the floating point type
has both a plus and minus zero, which are considered equal by the predefined
equality, then a block compare cannot be used for the predefined composite
equality. Of course, with user-defined equals operators for tagged components,
a block compare breaks down anyway, so this is not the only special case
that requires component-by-component comparisons. On a one's complement
machine, a similar situation might occur for integer types, since one's
complement machines typically have both a plus and minus (integer) zero.
24.1/1
{
8652/0016}
For any composite type, the order in which "=" is called for components
is unspecified. Furthermore, if the result can be determined before calling
"=" on some components, it is unspecified whether "=" is
called on those components.{Unspecified [partial]}
25
The predefined "/=" operator gives
the complementary result to the predefined "=" operator.
25.a
Ramification: Furthermore, if the
user defines an "=" operator that returns Boolean, then a "/="
operator is implicitly declared in terms of the user-defined "=" operator
so as to give the complementary result. See 6.6.
26
{lexicographic order}
For a discrete array type, the predefined ordering
operators correspond to
lexicographic order using the predefined
order relation of the component type: A null array is lexicographically
less than any array having at least one component. In the case of nonnull
arrays, the left operand is lexicographically less than the right operand
if the first component of the left operand is less than that of the right;
otherwise the left operand is lexicographically less than the right operand
only if their first components are equal and the tail of the left operand
is lexicographically less than that of the right (the
tail consists
of the remaining components beyond the first and can be null).
27
{evaluation (membership test)
[partial]} For the evaluation of a membership
test, the
simple_expression and
the
range (if any) are evaluated
in an arbitrary order.
28
A membership test
using in yields the result True if:
29
- The tested type is scalar, and the value of the simple_expression
belongs to the given range, or the
range of the named subtype; or
29.a
Ramification: The scalar
membership test only does a range check. It does not perform any other
check, such as whether a value falls in a ``hole'' of a ``holey'' enumeration
type. The Pos attribute function can be used for that purpose.
29.b
Even though Standard.Float is
an unconstrained subtype, the test ``X in Float'' will still return False
(presuming the evaluation of X does not raise Constraint_Error) when
X is outside Float'Range.
30
- The tested type is not scalar, and the value of the simple_expression
satisfies any constraints of the named subtype, and, if the type of the
simple_expression is class-wide,
the value has a tag that identifies a type covered by the tested type.
30.a
Ramification: Note that
the tag is not checked if the simple_expression
is of a specific type.
31
Otherwise the test yields the result False.
32
A membership test using not in gives the
complementary result to the corresponding membership test using in.
Implementation Requirements
32.1/1
{
8652/0016}
For all nonlimited types declared in language-defined packages, the "="
and "/=" operators of the type shall behave as if they were the predefined
equality operators for the purposes of the equality of composite types and generic
formal types.
32.a.1/1
Ramification: If any
language-defined types are implemented with a user-defined "="
operator, then either the full type must be tagged, or the compiler must
use ``magic'' to implement equality for this type. A normal user-defined
"=" operator for an untagged type does not meet this
requirement.
33
13 No exception is ever raised
by a membership test, by a predefined ordering operator, or by a predefined
equality operator for an elementary type, but an exception can be raised
by the evaluation of the operands. A predefined equality operator for
a composite type can only raise an exception if the type has a tagged
part whose primitive equals operator propagates an exception.
34
14 If a composite type has
components that depend on discriminants, two values of this type have
matching components if and only if their discriminants are equal. Two
nonnull arrays have matching components if and only if the length of
each dimension is the same for both.
Examples
35
Examples of
expressions involving relational operators and membership tests:
36
X /= Y
37
"" < "A" and "A" < "Aa" -- True
"Aa" < "B" and "A" < "A " -- True
38
My_Car = null -- true if My_Car has been set to null (see 3.10.1)
My_Car = Your_Car -- true if we both share the same car
My_Car.all = Your_Car.all -- true if the two cars are identical
39
N not in 1 .. 10 -- range membership test
Today in Mon .. Fri -- range membership test
Today in Weekday -- subtype membership test (see 3.5.1)
Archive in Disk_Unit -- subtype membership test (see 3.8.1)
Tree.all in Addition'Class -- class membership test (see 3.9.1)
Extensions to Ada 83
39.a
{extensions to Ada 83}
Membership tests can be used to test the tag of a
class-wide value.
39.b
Predefined equality for a composite
type is defined in terms of the primitive equals operator for tagged
components or the parent part.
Wording Changes from Ada 83
39.c
The term ``membership test'' refers
to the relation "X in S"
rather to simply the reserved word in or not in.
39.d
We use the term ``equality operator''
to refer to both the = (equals) and /= (not equals) operators. Ada 83
referred to = as the equality operator, and /= as the inequality
operator. The new wording is more consistent with the ISO 10646 name
for "=" (equals sign) and provides a category similar to ``ordering
operator'' to refer to both = and /=.
39.e
We have changed the term ``catenate''
to ``concatenate''.
Contents Index Previous Next Legal