Spec-Zone.ru › Ada 95
Справочник по Ada 95

4.6 Преобразования типов

Явные преобразования типов, как преобразования значений, так и преобразования представлений, разрешены между тесно связанными типами, как определено ниже. Этот пункт также определяет правила для преобразований значений и представлений к конкретному подтипу типа, как явные, так и неявные в других конструкциях.

Синтаксис

type_conversion ::=
subtype_mark(expression)
| subtype_mark(name)
Целевой подтип преобразования типа type_conversion — это подтип, обозначенный subtype_mark. Операнд преобразования типа type_conversion — это expression или name в скобках; его тип — тип операнда.
Один тип преобразуем к другому типу, если преобразование типа type_conversion с первым типом как типом операнда и вторым типом как целевым типом является допустимым в соответствии с правилами этого раздела. Два типа преобразуемы, если каждый из них преобразуем к другому.
Преобразование типа type_conversion, операндом которого является name объекта, называется преобразованием представления, если оба его целевой тип и тип операнда являются помеченными, или если оно появляется в качестве фактического параметра с режимом out или in out; другие преобразования типа type_conversion называются преобразованиями значения.

Правила разрешения имен

Ожидается, что операнд преобразования типа type_conversion будет иметь любой тип.
Операнд преобразования представления интерпретируется только как name; операнд преобразования значения интерпретируется как expression.

Правила допустимости

Если целевой тип — числовой тип, то тип операнда должен быть числовым типом.
Если целевой тип — тип массива, то тип операнда должен быть типом массива. Кроме того:
  • Типы должны иметь одинаковую размерность;
  • Соответствующие типы индексов должны быть преобразуемы;
  • Подтипы компонентов должны статически соответствовать; и
  • При преобразовании представления целевой тип и тип операнда должны оба или ни один из них иметь ссылочные компоненты.
Если целевой тип — тип общего доступа, то тип операнда должен быть типом доступа к объекту. Кроме того:
  • Если целевой тип — тип доступа к переменной, то тип операнда должен быть типом доступа к переменной;
  • Если целевой обозначенный тип помечен, то обозначенный тип операнда должен быть преобразуем в целевой обозначенный тип;
  • Если целевой обозначенный тип не помечен, то обозначенные типы должны быть одинаковыми, и либо обозначенные подтипы должны статически соответствовать, либо целевой обозначенный подтип должен быть дискриминированным и не ограниченным; и
  • Уровень доступности типа операнда не должен быть статически глубже, чем уровень доступности целевого типа. Помимо мест, где обычно применяются правила допустимости (см. 12.3), это правило применяется также в частях с закрытым доступом экземпляра генерируемого блока.
Если целевой тип — тип доступа к подпрограмме, то тип операнда должен быть типом доступа к подпрограмме. Кроме того:
  • Определяющие профили должны быть подтиповыми.
  • Уровень доступности типа операнда не должен быть статически глубже, чем уровень доступности целевого типа. Помимо мест, где обычно применяются правила допустимости (см. 12.3), это правило применяется также в частях с закрытым доступом экземпляра генерируемого блока. Если тип операнда объявлен внутри тела генерируемого блока, целевой тип должен быть объявлен внутри тела генерируемого блока.
Если целевой тип не входит ни в одну из вышеперечисленных четырёх категорий, должен существовать тип, являющийся предком как целевого типа, так и типа операнда. Кроме того, если целевой тип помечен, то либо:
  • Тип операнда должен быть покрыт или происходить от целевого типа; или
  • Тип операнда должен быть универсальным типом, который охватывает целевой тип.
При преобразовании представления для непомеченного типа целевой тип должен быть преобразуем (обратно) к типу операнда.

Статическая семантика

Преобразование типа type_conversion, являющееся преобразованием значения, обозначает значение, являющееся результатом преобразования значения операнда в целевой подтип.
Преобразование типа type_conversion, являющееся преобразованием представления, обозначает представление объекта, обозначаемого операндом. Это представление — переменная целевого типа, если операнд обозначает переменную; в противном случае это константа целевого типа.
Номинальный подтип преобразования типа type_conversion — его целевой подтип.

Динамическая семантика

Для вычисления преобразования типа type_conversion, являющегося преобразованием значения, операнд вычисляется, а затем значение операнда преобразуется в соответствующее значение целевого типа, если таковое имеется. Если нет значения целевого типа, соответствующего значению операнда, возникает Constraint_Error; это может произойти только при преобразовании в модулярный тип и только тогда, когда значение операнда находится вне базового диапазона модулярного типа. Следуют дополнительные правила:
  • Преобразование числового типа
  • Если целевой и тип операнда — оба целочисленные типы, то результат — значение целевого типа, соответствующее тому же математическому целому числу, что и операнд.
  • Если целевой тип — десятичный тип с плавающей точкой, то результат усекается (к 0) если значение операнда не является кратным small целевого типа.
  • Если целевой тип — какой-либо другой вещественный тип, то результат находится в пределах точности целевого типа (см. G.2, «Требования к производительности чисел'', для реализаций, поддерживающих Приложение по числу).
  • Если целевой тип — целочисленный тип, а тип операнда — вещественный, результат округляется до ближайшего целого (в сторону от нуля, если ровно посередине между двумя целыми).
  • Преобразование типа перечисления
  • Результат — значение целевого типа с тем же порядковым номером, что и значение операнда.
  • Преобразование типа массива
  • Если целевой подтип — ограниченный подтип массива, то проверяется, что длина каждого измерения значения операнда равна длине соответствующего измерения целевого подтипа. Границы результата — те же, что у целевого подтипа.
  • Если целевой подтип — неограниченный подтип массива, то границы результата получаются путём преобразования каждой границы значения операнда в соответствующий тип индекса целевого типа. Для каждого ненулевого диапазона индексов проверяется, что границы диапазона принадлежат соответствующему подтипу индексов.
  • В любом случае с массивом, значение каждого компонента результата — это значение соответствующего компонента значения операнда (см. 4.5.2).
  • Преобразование составного (не массива) типа
  • Значение каждого компонента результата, не являющегося дискриминатором, — это значение соответствующего компонента значения операнда.
  • Тег результата — это тег операнда. Если тип операнда — универсальный тип, проверяется, что тег операнда определяет (конкретный) тип, который покрыт или происходит от целевого типа.
  • Для каждого дискриминатора целевого типа, соответствующего дискриминатору типа операнда, его значение — это значение соответствующего дискриминатора значения операнда; если он соответствует более чем одному дискриминатору типа операнда, проверяется, что все эти дискриминаторы равны в значении операнда.
  • Для каждого дискриминатора целевого типа, соответствующего дискриминатору, заданному в derived_type_definition для какого-либо предка типа операнда (или, если универсальный, какого-либо предка конкретного типа, идентифицируемого тегом операнда), его значение в результате определяется derived_type_definition.
  • Для каждого дискриминатора типа операнда, соответствующего дискриминатору, заданному в derived_type_definition для какого-либо предка целевого типа, проверяется, что в значении операнда он равен указанному для него значению.
  • Для каждого дискриминатора результата проверяется, что его значение принадлежит его подтипу.
  • Преобразование типа доступа
  • Для типа доступа к объекту проверяется, что уровень доступности типа операнда не глубже, чем уровень доступности целевого типа.
  • Если целевой тип является анонимным типом доступа, выполняется проверка, что значение операнда не равно null; если целевой тип не является анонимным типом доступа, то результат равен null, если значение операнда равно null.
  • Если значение операнда не равно null, то результат обозначает тот же объект (или подпрограмму), что и значение операнда, но рассматривается как имеющий целевой обозначенный подтип (или профиль); выполняются любые проверки, связанные с оценкой преобразования в целевой обозначенный подтип.
После преобразования значения в целевой тип, если целевой подтип ограничен, выполняется проверка, удовлетворяет ли значение этому ограничению.
Для оценки преобразования представления операнд имя оценивается, и создается новое представление объекта, обозначаемого операндом, тип которого является целевым типом; если целевой тип составной, выполняются проверки, как описано выше, для преобразования значения.
Свойства этого нового представления следующие:
  • Если целевой тип составной, границы или дискриминанты (если таковые имеются) представления определяются, как описано выше для преобразования значения; каждый компонент представления, не являющийся дискриминантом, обозначает соответствующий компонент объекта операнда; подтип представления ограничен, если либо целевой подтип, либо объект операнда ограничен, или если целевой подтип неопределен, или если тип операнда является потомком целевого типа и имеет дискриминанты, которые не были унаследованы от целевого типа;
  • Если целевой тип помечен, то присваивание представлению присваивает соответствующую часть объекта, обозначаемого операндом; в противном случае присваивание представлению присваивает объекту, после преобразования присвоенного значения в подтип объекта (что может вызвать Constraint_Error);
  • Чтение значения представления дает результат преобразования значения объекта операнда в целевой подтип (что может вызвать Constraint_Error), за исключением случая, когда объект является типом доступа и преобразование представления передается в качестве параметра out; в последнем случае значение объекта операнда используется для инициализации формального параметра без проверки на соответствие какому-либо ограничению целевого подтипа (см. 6.4.1).
Если проверка доступа Accessibility_Check завершается неудачно, возбуждается Program_Error. Любая другая проверка, связанная с преобразованием, возбуждает Constraint_Error в случае неудачи.
Преобразование в тип эквивалентно преобразованию в неограниченный подтип типа.
ПРИМЕЧАНИЯ
20 Помимо явных преобразований type_conversion, преобразования типов выполняются неявно в ситуациях, когда ожидаемый тип и фактический тип конструкта различаются, как это разрешено правилами разрешения типов (см. 8.6). Например, целочисленная литерал имеет тип universal_integer и неявно преобразуется при присваивании целевому типу конкретного целочисленного типа. Аналогично, фактический параметр конкретного помеченного типа неявно преобразуется, когда соответствующий формальный параметр является типом класса.
21 Даже когда ожидаемые и фактические типы совпадают, неявные преобразования подтипов выполняются для корректировки границ массива (если таковые имеются) операнда для соответствия желаемому целевому подтипу или для возбуждения Constraint_Error, если (возможно, скорректированное) значение не удовлетворяет ограничениям целевого подтипа.
Следствием правил разрешения перегрузки является то, что операнд явного type_conversion не может быть литералом null, аллокатором, агрегатом, строковой_литералью, символьной_литералью или ссылкой attribute_reference на атрибут доступа или Unchecked_Access. Аналогично, такая выражение, заключенная в скобки, не допускается. qualified_expression (см. 4.7) может использоваться вместо такого type_conversion.
22 Ограничение целевого подтипа не оказывает влияния на type_conversion элементарного типа, переданного в качестве параметра out. Поэтому рекомендуется, чтобы первый подтип был указан как целевой, чтобы свести к минимуму путаницу (аналогичное рекомендация относится к переименованию и формальным in out объектам обобщений).

Примеры

Примеры преобразования числовых типов:
Real(2*J) -- значение преобразуется в число с плавающей точкой
Integer(1.6) -- значение равно 2
Integer(-0.4) -- значение равно 0
Пример преобразования между производными типами:
type A_Form is new B_Form;
X : A_Form;
Y : B_Form;
X := A_Form(Y);
Y := B_Form(X); -- обратное преобразование
Примеры преобразований между массивами:
type Sequence is array (Integer range <>) of Integer;
subtype Dozen is Sequence(1 .. 12);
Ledger : array(1 .. 100) of Integer;
Sequence(Ledger) -- границы совпадают с границами Ledger
Sequence(Ledger(31 .. 42)) -- границы равны 31 и 42
Dozen(Ledger(31 .. 42)) -- границы совпадают с границами Dozen


Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API