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

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:
Если целевой тип является типом доступа к переменной, то тип операнда должен быть типом доступа к переменной;
Если целевой тип назначения является помеченным, то тип назначения операнда должен быть преобразуем в целевой тип назначения;
Если целевой тип назначения не помечен, то типы назначения должны быть одинаковыми, и либо:
подтипы назначения должны статически совпадать; или
тип назначения должен быть дискриминированным в полном представлении и не ограниченным в любом частичном представлении, и один из подтипов назначения должен быть неограниченным;
Уровень доступности типа операнда не должен статически превышать уровень доступности целевого типа, за исключением случаев, когда целевой тип является анонимным типом доступа к автономному объекту. Если целевой тип является типом такого автономного объекта, уровень доступности типа операнда не должен статически превышать уровень доступности объявления автономного объекта.
  • Если целевой тип является типом доступа к объекту, специфичному для пула, то тип операнда должен быть universal_access.
  • Если целевой тип является типом доступа к подпрограмме, то тип операнда должен быть universal_access или типом доступа к подпрограмме. Далее, если тип операнда не universal_access:
Определяемые профили должны соответствовать подтипу.
Уровень доступности типа операнда не должен статически превышать уровень доступности целевого типа. Если тип операнда объявлен в теле обобщенного блока, то целевой тип должен быть объявлен в этом обобщенном теле.
Если целевой тип имеет аспект Global, отличный от in out all или Unspecified, то каждый режим аспекта Global типа операнда должен определять подмножество переменных, определенных соответствующим режимом аспекта Global целевого типа или режимом in out аспекта Global целевого типа.
Если целевой тип неблокирующий, тип операнда также должен быть неблокирующим.
В дополнение к местам, где обычно применяются Правила легальности (см. 12.3), эти правила применяются также в частях объявления экземпляра обобщенного блока.

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

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

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

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