Руководство по Ada (Ada 2022)
4.1.6 Пользовательское индексирование
Статическая семантика
Для помеченного типа T могут быть указаны следующие связанные с типом операционные аспекты:
Constant_Indexing
Этот аспект должен быть указан именем, которое обозначает одну или несколько функций, объявленных непосредственно в том же списке объявлений, в котором объявлен тип T или завершено объявление T. Все такие функции должны иметь как минимум два параметра, первый из которых имеет тип T или T'Class или является параметром доступа к константе с указанным типом T или T'Class.
Variable_Indexing
Этот аспект должен быть указан именем, которое обозначает одну или несколько функций, объявленных непосредственно в том же списке объявлений, в котором объявлен тип T или завершено объявление T. Все такие функции должны иметь как минимум два параметра, первый из которых имеет тип T или T'Class или является параметром доступа с указанным типом T или T'Class. Все такие функции должны иметь тип возвращаемого значения, являющийся типом ссылки (см. 4.1.5), дискриминант ссылки которого имеет тип доступа к переменной.
Эти аспекты наследуются потомками T (включая тип класса T'Class).
Индексируемый контейнерный тип — это (вид) помеченный тип, для которого указан как минимум один из аспектов Constant_Indexing или Variable_Indexing. Индексируемый контейнерный объект — это объект индексируемого контейнерного типа. generalized_indexing — это имя, которое обозначает результат вызова функции, имя которой указано в аспекте Constant_Indexing или Variable_Indexing.
Аспекты Constant_Indexing и Variable_Indexing непереопределяемые (см. 13.1.1).
Правила легальности
Если предком типа T является индексируемый контейнерный тип, то любое явное указание аспектов Constant_Indexing или Variable_Indexing должно быть подтверждающим; то есть, указанное имя должно соответствовать унаследованному аспекту (см. 13.1.1).
Абзацы с 7 по 8 были удалены.
Помимо мест, где обычно применяются правила легальности (см. 12.3), это правило применяется также в приватной части экземпляра обобщенного блока.
generalized_indexing является недопустимым, если эквивалентный префиксный вид (см. ниже) является недопустимым.
Синтаксис
Правила разрешения имен
Ожидаемый тип для indexable_container_object_prefix generalized_indexing — любой индексируемый контейнерный тип.
Если для типа indexable_container_object_prefix generalized_indexing указан аспект Constant_Indexing, то generalized_indexing интерпретируется как постоянное индексирование в следующих случаях:
- когда для типа indexable_container_object_prefix не указан аспект Variable_Indexing;
- когда indexable_container_object_prefix обозначает константу;
- когда generalized_indexing используется в primary, где разрешено имя, обозначающее константу.
В противном случае generalized_indexing интерпретируется как переменное индексирование.
Когда generalized_indexing интерпретируется как постоянное (или переменное) индексирование, это эквивалентно вызову префиксного вида одной из функций, имя которых указано в аспекте Constant_Indexing (или Variable_Indexing) типа indexable_container_object_prefix с заданной actual_parameter_part и с indexable_container_object_prefix как префикса префиксного вида.
ПРИМЕЧАНИЕ. Аспекты Constant_Indexing и Variable_Indexing не могут быть переопределены при наследовании для производного типа, но функции, которые они обозначают, могут быть изменены путём переопределения или перегрузки.
Примеры
Примеры спецификации и использования обобщенного индексирования:
type Indexed_Barrel is tagged ...
with Variable_Indexing => Find;
-- Indexed_Barrel — индексируемый контейнерный тип,
-- Find — операция обобщенного индексирования.
with Variable_Indexing => Find;
-- Indexed_Barrel — индексируемый контейнерный тип,
-- Find — операция обобщенного индексирования.
function Find (B : aliased in out Indexed_Barrel; Key : String)
return Ref_Element;
-- Возвращает ссылку на элемент барабана (см. 4.1.5).
return Ref_Element;
-- Возвращает ссылку на элемент барабана (см. 4.1.5).
IB: aliased Indexed_Barrel;
-- Все последующие вызовы эквивалентны:
Find (IB,"pear").Data.all := Element'(...); -- Традиционный вызов
IB.Find ("pear").Data.all := Element'(...); -- Вызов префиксного вида
IB.Find ("pear") := Element'(...); -- Неявное разыменование (см. 4.1.5)
IB ("pear") := Element'(...); -- Неявное индексирование и разыменование
IB ("pear").Data.all := Element'(...); -- Только неявное индексирование
Find (IB,"pear").Data.all := Element'(...); -- Традиционный вызов
IB.Find ("pear").Data.all := Element'(...); -- Вызов префиксного вида
IB.Find ("pear") := Element'(...); -- Неявное разыменование (см. 4.1.5)
IB ("pear") := Element'(...); -- Неявное индексирование и разыменование
IB ("pear").Data.all := Element'(...); -- Только неявное индексирование