Справочник по Ada 2012
4.5.2 Операторы сравнения и проверки принадлежности
Операторы равенства = (равно) и /= (не равно) определены для типов без ограничения. Другие операторы сравнения relational_operator — это операторы упорядочения < (меньше), <= (меньше или равно), > (больше) и >= (больше или равно). Операторы упорядочения определены для скалярных типов и для дискретных типов массивов, то есть одномерных массивов, компоненты которых имеют дискретный тип.
Проверка принадлежности, используя in или not in, определяет, принадлежит ли значение заданному подтипу или диапазону, равно ли оно заданному значению, имеет ли метку, которая идентифицирует тип, охватываемый заданным типом, или может быть преобразовано в и имеет уровень доступа, подходящий для данного типа доступа. Проверки принадлежности разрешены для всех типов.
Правила разрешения имен
Проверяемый тип проверки принадлежности определяется membership_choice элементами списка membership_choice_list. Все элементы membership_choice списка membership_choice_list должны соответствовать одному и тому же типу, который является проверяемым типом; или каждый элемент membership_choice должен быть элементарного типа, а проверяемый тип должен быть покрыт каждым из этих элементарных типов.
Если проверяемый тип помечен, то tested_simple_expression должен соответствовать типу, который может быть преобразован (см. 4.6) к проверяемому типу; если нет, ожидаемый тип для tested_simple_expression — это проверяемый тип. Ожидаемый тип для choice_simple_expression в элементе membership_choice и для simple_expression диапазона range в элементе membership_choice — это проверяемый тип операции принадлежности.
Правила допустимости
Для проверки принадлежности, если tested_simple_expression имеет тип помеченного класса, тогда проверяемый тип должен быть (видимо) помечен.
Если проверка принадлежности включает один или несколько choice_simple_expression и проверяемый тип проверки принадлежности ограничен, тогда проверяемый тип проверки принадлежности должен иметь видимый примитивный оператор равенства.
Статическая семантика
Тип результата проверки принадлежности — это предопределенный тип Boolean.
Операторы равенства определены для каждого конкретного типа T, который не ограничен и не является анонимным типом доступа, со следующими спецификациями:
function "=" (Left, Right : T) return Boolean
function "/="(Left, Right : T) return Boolean
function "/="(Left, Right : T) return Boolean
Следующие дополнительные операторы равенства для типа universal_access объявлены в пакете Standard для использования с анонимными типами доступа:
function "=" (Left, Right : universal_access) return Boolean
function "/="(Left, Right : universal_access) return Boolean
function "/="(Left, Right : universal_access) return Boolean
Операторы упорядочения определены для каждого конкретного скалярного типа T и для каждого дискретного типа массива T со следующими спецификациями:
function "<" (Left, Right : T) return Boolean
function "<="(Left, Right : T) return Boolean
function ">" (Left, Right : T) return Boolean
function ">="(Left, Right : T) return Boolean
function "<="(Left, Right : T) return Boolean
function ">" (Left, Right : T) return Boolean
function ">="(Left, Right : T) return Boolean
Правила разрешения имен
По крайней мере, один из операндов оператора равенства для universal_access должен быть конкретного анонимного типа доступа. За исключением случаев, когда предопределенный оператор равенства идентифицируется с использованием расширенного имени с prefix, обозначающим пакет Standard, ни один из операндов не должен быть типом доступа к объекту, назначенный тип которого является D или D'Class, где D имеет определённый пользователем примитивный оператор равенства, такой что:
- его тип результата — Boolean;
- он объявлен непосредственно в том же списке объявлений, что и D или любой частичный или неполный вид D; и
- по крайней мере, один из его операндов — это параметр доступа с назначенным типом D.
Правила допустимости
По крайней мере, один из операндов операторов равенства для universal_access должен быть типа universal_access, или оба должны быть типов доступа к объектам, или оба должны быть типов доступа к подпрограммам. Кроме того:
- Когда оба имеют типы доступа к объектам, назначенные типы должны быть одинаковыми или один должен покрывать другой, и если назначенные типы — элементарные или массивы, то назначенные подтипы должны статически совпадать;
- Когда оба имеют типы доступа к подпрограммам, назначенные профили должны соответствовать подтипу.
Если профиль явным образом объявленного примитивного оператора равенства для типа записи без меток соответствует профилю соответствующего предопределенного оператора равенства, объявление должно произойти до того, как тип заморозится. В дополнение к местам, где обычно применяются правила допустимости (см. 12.3), это правило применяется также в частях `private` экземпляра генерического блока.
Динамическая семантика
Для дискретных типов предопределённые операторы сравнения определены с помощью соответствующих математических операций над позиционными номерами значений операндов.
Для вещественных типов предопределённые операторы сравнения определены с помощью соответствующих математических операций над значениями операндов, с учётом точности типа.
Два значения доступа к объектам равны, если они обозначают один и тот же объект, или если оба равны нулевому значению типа доступа.
Два значения доступа к подпрограммам равны, если они являются результатом одного и того же вычисления атрибута доступа attribute_reference, или если оба равны нулевому значению типа доступа. Два значения доступа к подпрограммам не равны, если они обозначают разные подпрограммы. Не определено, равны или нет два значения доступа, обозначающие одну и ту же подпрограмму, но являющиеся результатом различных вычислений атрибута доступа attribute_reference.
Для расширения типа, предопределённое равенство определяется на основе примитивного (возможно, определённого пользователем) оператора равенства для родительского типа и для любых компонентов, которые имеют тип записи в части расширения, а также предопределённое равенство для любых других компонентов, не унаследованных от родительского типа.
Для производного типа, родительским типом которого является тип записи без меток, предопределённое равенство определяется на основе примитивного (возможно, определённого пользователем) оператора равенства родительского типа.
Для частного типа, если его полный тип — тип записи, предопределённое равенство определяется на основе примитивного оператора равенства полного типа; в противном случае, предопределённое равенство для частного типа — это равенство его полного типа.
Для других составных типов, предопределённые операторы равенства (и некоторые другие предопределённые операции над составными типами — см. 4.5.1 и 4.6) определяются на основе соответствующей операции над соответствующими компонентами, определёнными следующим образом:
- Для двух составных объектов или значений одного и того же типа без массива соответствующими компонентами являются те, которые соответствуют одному и тому же объявлению компонента component_declaration или спецификации дискриминанта discriminant_specification;
- Для двух одномерных массивов одного и того же типа соответствующими компонентами являются те (если таковые имеются), значения индексов которых совпадают в следующем смысле: нижние границы диапазонов индексов определяются как совпадающие, и преемники соответствующих индексов определяются как совпадающие;
- Для двух многомерных массивов одного и того же типа соответствующими компонентами являются те, значения индексов которых совпадают в последовательных позициях индекса.
Аналогичные определения применяются, если типы двух объектов или значений могут быть преобразованы, а не идентичны.
С учётом вышеприведённого определения соответствующих компонентов, результат предопределённого оператора равенства для составных типов (кроме тех составных типов, которые были рассмотрены ранее) определяется следующим образом:
- Если нет компонентов, результат определяется как True;
- Если есть несовпадающие компоненты, результат определяется как False;
- В противном случае результат определяется на основе примитивного оператора равенства для любых соответствующих компонентов, которые являются записями, и предопределённого равенства для любых других соответствующих компонентов.
Если примитивный оператор равенства для типа записи без меток абстрактен, то Program_Error возникает в момент любого (явного) вызова этой абстрактной подпрограммы.
Для любого составного типа порядок, в котором вызывается «=» для компонентов, не определён. Кроме того, если результат можно определить до вызова «=» для некоторых компонентов, не определено, будет ли «=» вызван для этих компонентов.
Предопределённый оператор «/» даёт результат, обратный предопределённому оператору «=».
Для дискретного массива порядок предопределённых операторов соответствует лексикографическому порядку, использующему предопределённое отношение порядка типа компонента: массив со значением null лексикографически меньше любого массива, имеющего хотя бы один компонент. В случае непустых массивов левый операнд лексикографически меньше правого, если первый компонент левого операнда меньше, чем правого; в противном случае левый операнд лексикографически меньше правого только в том случае, если их первые компоненты равны, а хвост левого операнда лексикографически меньше хвоста правого (хвост состоит из оставшихся компонентов, кроме первого, и может быть null).
Индивидуальная проверка на членство — это проверка на членство для одного membership_choice.
При оценке проверки на членство с использованием in, у которого membership_choice_list имеет один membership_choice, tested_simple_expression и membership_choice оцениваются в произвольном порядке; результат совпадает с результатом индивидуальной проверки на членство для membership_choice.
При оценке проверки на членство с использованием in, у которого membership_choice_list имеет более одного membership_choice, сначала оценивается tested_simple_expression проверки на членство, а результат операции эквивалентен результату последовательности, состоящей из индивидуальной проверки на членство для каждого membership_choice, объединённых с управляющей формой короткого замыкания or else.
Индивидуальная проверка на членство возвращает результат True, если:
- Значение membership_choice является choice_simple_expression, и tested_simple_expression равно значению membership_choice. Если тип, к которому применяется проверка, является типом записи или ограниченным типом, проверка использует примитивное равенство для этого типа; в противном случае проверка использует предопределённое равенство.
- Значение membership_choice является range, и значение tested_simple_expression принадлежит заданному range.
- Значение membership_choice является subtype_mark, проверяемый тип является скалярным, значение tested_simple_expression принадлежит диапазону именованного подтипа, и значение удовлетворяет предикатам именованного подтипа.
- Значение membership_choice является subtype_mark, проверяемый тип не является скалярным, значение tested_simple_expression удовлетворяет любым ограничениям именованного подтипа, значение удовлетворяет предикатам именованного подтипа, и:
если тип tested_simple_expression является класса, значение имеет метку, которая идентифицирует тип, охватываемый проверяемым типом;
если проверяемый тип является типом доступа и именованный подтип исключает null, значение tested_simple_expression не является null;
если проверяемый тип является общим типом доступа к объекту, тип tested_simple_expression преобразуется в проверяемый тип, а его уровень доступности не глубже, чем уровень проверяемого типа; кроме того, если целевой тип проверяемого типа помечен и tested_simple_expression не является null, метка объекта, на который указывает значение tested_simple_expression, охватывается целевым типом проверяемого типа.
В противном случае проверка возвращает результат False.
Проверка на членство с использованием not in даёт результат, обратный соответствующей проверке на членство с использованием in.
Требования к реализации
Для всех неограниченных типов, объявленных в пакетах, определённых языком, операторы «=» и «/» типа должны вести себя так, как если бы они были предопределёнными операторами равенства для целей равенства составных типов и формальных типов обобщения.
ПРИМЕЧАНИЯ
Этот абзац был удалён.
14 Если составной тип имеет компоненты, зависящие от дискриминантов, два значения этого типа имеют соответствующие компоненты тогда и только тогда, когда их дискриминанты равны. Два непустых массива имеют соответствующие компоненты, если и только если длина каждого измерения одинакова для обоих.
Примеры
Примеры выражений, включающих операторы отношения и проверки на членство:
X /= Y
"" < "A" и "A" < "Aa" -- True
"Aa" < "B" и "A" < "A " -- True
"Aa" < "B" и "A" < "A " -- True
My_Car = null -- True, если My_Car установлено в null (см. 3.10.1)
My_Car = Your_Car -- True, если у нас обеих одна и та же машина
My_Car.all = Your_Car.all -- True, если две машины идентичны
My_Car = Your_Car -- True, если у нас обеих одна и та же машина
My_Car.all = Your_Car.all -- True, если две машины идентичны
N не в 1 .. 10 -- проверка на членство в диапазоне
Today в Mon .. Fri -- проверка на членство в диапазоне
Today в Weekday -- проверка на членство в подтипе (см. 3.5.1)
Card в Clubs | Spades -- проверка на членство в списке (см. 3.5.1)
Archive в Disk_Unit -- проверка на членство в подтипе (см. 3.8.1)
Tree.all в Addition'Class -- проверка на членство в классе (см. 3.9.1)
Today в Mon .. Fri -- проверка на членство в диапазоне
Today в Weekday -- проверка на членство в подтипе (см. 3.5.1)
Card в Clubs | Spades -- проверка на членство в списке (см. 3.5.1)
Archive в Disk_Unit -- проверка на членство в подтипе (см. 3.8.1)
Tree.all в Addition'Class -- проверка на членство в классе (см. 3.9.1)