4.5.2 Relational Operators and Membership Tests
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. 
 
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
Legality Rules
For a membership test, if the 
tested_simple_expression 
is of a tagged class-wide type, then the tested type shall be (visibly) 
tagged. 
 
  If a membership test includes one or more 
choice_simple_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
The result type of a membership test is the predefined 
type Boolean.
The equality operators 
are predefined for every specific type T that is not limited, 
and not an anonymous access type, with the following specifications: 
function "=" (Left, Right : T) return Boolean
function "/="(Left, Right : T) return Boolean
  The following additional 
equality operators for the universal_access type are declared 
in package Standard for use with anonymous access types: 
function "=" (Left, Right : universal_access) return Boolean
function "/="(Left, Right : universal_access) return Boolean
The ordering operators 
are predefined for every specific scalar type T, and for every 
discrete array type T, with the following specifications: 
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
  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: 
 
its result type is Boolean;
it is declared immediately within the same declaration 
list as D or any partial or incomplete view of D; and
at least one of its operands is an access parameter 
with designated type D. 
Legality Rules
  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: 
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;
When both are of access-to-subprogram types, the 
designated profiles shall be subtype conformant. 
  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 
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
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.
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. 
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.
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. 
 
 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. 
 
   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. 
 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.
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: 
 
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;
For two multidimensional arrays of the same type, 
matching components are those whose index values match in successive 
index positions. 
The analogous definitions apply if the types of the 
two objects or values are convertible, rather than being the same. 
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: 
If there are no components, the result is defined 
to be True;
If there are unmatched components, the result is 
defined to be False;
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. 
   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. 
   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.
 
The predefined "/=" operator gives the 
complementary result to the predefined "=" operator. 
 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).
 
   For the evaluation of a membership test using 
in whose 
membership_choice_list 
has more than one 
membership_choice, 
the 
tested_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.
 
 An individual membership 
test yields the result True if: 
if the type of the 
tested_simple_expression 
is class-wide, the value has a tag that identifies a type covered by 
the tested type; 
 
if the tested type is an access 
type and the named subtype excludes null, the value of the 
tested_simple_expression 
is not null;
 
if the tested type is a general 
access-to-object type, the type of the 
tested_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 
tested_simple_expression 
is nonnull, the tag of the object designated by the value of the 
tested_simple_expression 
is covered by the designated type of the tested type. 
 
 Otherwise, the test yields the result False.
A membership test using not in gives the complementary 
result to the corresponding membership test using in.
Implementation Requirements
   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. 
This paragraph was 
deleted.
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
Examples of expressions 
involving relational operators and membership tests: 
X /= Y
"" < "A" and "A" < "Aa"     --  True
"Aa" < "B" and "A" < "A  "  --  True
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 
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