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

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

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

Синтаксис

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

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

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

Правила законности

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

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

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

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

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