Relational Operators and Membership Tests
Author: JTC1/SC22/WG9/ARG, by Randall Brukardt, ARG Editor

Ada Reference Manual — Legal Information

# 4.5.2 Relational Operators and Membership Tests

1
The equality operators = (equals) and /= (not equals) are predefined for nonlimited types. The other relational_operators are the ordering operators < (less than), <= (less than or equal), > (greater than), and >= (greater than or equal). 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.
2/3
A membership test, using in or not in, determines whether or not a value belongs to any given subtype or range, is equal to any given value, has a tag that identifies a type that is covered by a given type, or is convertible to and has an accessibility level appropriate for a given access type. Membership tests are allowed for all types.

#### Name Resolution Rules

3/3
The tested type of a membership test is determined by the membership_choices of the membership_choice_list. Either all membership_choices of the membership_choice_list shall resolve to the same type, which is the tested type; or each membership_choice shall be of an elementary type, and the tested type shall be covered by each of these elementary types.
3.1/3
If the tested type is tagged, then the simple_expression shall resolve to be of a type that is convertible (see 4.6) to the tested type; if untagged, the expected type for the simple_expression is the tested type. The expected type of a choice_expression in a membership_choice, and of a simple_expression of a range in a membership_choice, is the tested type of the membership operation.

#### 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.1/3
If a membership test includes one or more choice_expressions and the tested type of the membership test is limited, then the tested type of the membership test shall have a visible primitive equality operator.

#### 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
7.1/2
The following additional equality operators for the universal_access type are declared in package Standard for use with anonymous access types:
7.2/2
function "=" (Left, Right : universal_access) return Boolean
function "/="(Left, Right : universal_access) 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

#### Name Resolution Rules

9.1/2
At least one of the operands of an equality operator for universal_access shall be of a specific anonymous access type. Unless the predefined equality operator is identified using an expanded name with prefix denoting the package Standard, neither operand shall be of an access-to-object type whose designated type is D or D'Class, where D has a user-defined primitive equality operator such that:
9.2/2
its result type is Boolean;
9.3/3
it is declared immediately within the same declaration list as D or any partial or incomplete view of D; and
9.4/2
at least one of its operands is an access parameter with designated type D.

#### Legality Rules

9.5/2
At least one of the operands of the equality operators for universal_access shall be of type universal_access, or both shall be of access-to-object types, or both shall be of access-to-subprogram types. Further:
9.6/2
When both are of access-to-object types, the designated types shall be the same or one shall cover the other, and if the designated types are elementary or array types, then the designated subtypes shall statically match;
9.7/2
When both are of access-to-subprogram types, the designated profiles shall be subtype conformant.
9.8/3
If the profile of an explicitly declared primitive equality operator of an untagged record type is type conformant with that of the corresponding predefined equality operator, the declaration shall occur before the type is frozen. In addition, if the untagged record type has a nonlimited partial view, then the declaration shall occur in the visible part of the enclosing package. 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.

#### 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.
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. 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.
14/3
For a type extension, predefined equality is defined in terms of the primitive (possibly user-defined) equals operator for the parent type and for any components that have a record type in the extension part, and predefined equality for any other components not inherited from the parent type.
14.1/3
For a derived type whose parent is an untagged record type, predefined equality is defined in terms of the primitive (possibly user-defined) equals operator of the parent type.
15/3
For a private type, if its full type is a record type, predefined equality is defined in terms of the primitive equals operator of the full type; otherwise, predefined equality for the private type is that of its full type.
16
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.
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/3
Otherwise, the result is defined in terms of the primitive equals operator for any matching components that are records, and the predefined equals for any other matching components.
24.1/3
If the primitive equals operator for an untagged record type is abstract, then Program_Error is raised at the point of any (implicit) call to that abstract subprogram.
24.2/1
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.
25
The predefined "/=" operator gives the complementary result to the predefined "=" operator.
26/3
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).
26.1/3
An individual membership test is the membership test of a single membership_choice.
27/3
For the evaluation of a membership test using in whose membership_choice_list has a single membership_choice, the simple_expression and the membership_choice are evaluated in an arbitrary order; the result is the result of the individual membership test for the membership_choice.
27.1/3
For the evaluation of a membership test using in whose membership_choice_list has more than one membership_choice, the simple_expression of the membership test is evaluated first and the result of the operation is equivalent to that of a sequence consisting of an individual membership test on each membership_choice combined with the short-circuit control form or else.
28/3
An individual membership test yields the result True if:
28.1/3
The membership_choice is a choice_expression, and the simple_expression is equal to the value of the membership_choice. If the tested type is a record type or a limited type, the test uses the primitive equality for the type; otherwise, the test uses predefined equality.
28.2/3
The membership_choice is a range and the value of the simple_expression belongs to the given range.
29/3
The membership_choice is a subtype_mark, the tested type is scalar, the value of the simple_expression belongs to the range of the named subtype, and the predicate of the named subtype evaluates to True.
30/3
The membership_choice is a subtype_mark, the tested type is not scalar, the value of the simple_expression satisfies any constraints of the named subtype, the predicate of the named subtype evaluates to True, and:
30.1/2
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.2/3
if the tested type is an access type and the named subtype excludes null, the value of the simple_expression is not null;
30.3/3
if the tested type is a general access-to-object type, the type of the simple_expression is convertible to the tested type and its accessibility level is no deeper than that of the tested type; further, if the designated type of the tested type is tagged and the simple_expression is nonnull, the tag of the object designated by the value of the simple_expression is covered by the designated type of the tested type.
31/3
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
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.
NOTES
33/2
This paragraph was deleted.
34
13 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/3
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/3
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)
Card in Clubs | Spades -- list 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)

Ada 2005 and 2012 Editions sponsored in part by Ada-Europe