Анимация
JavaScript
|
Главная Библионтека ровать неограниченно большими наборами типов, генерировать структуры данных и код на основе этих коллекций и т.д. На этапе компиляции к спискам типов можно применять большинство элементарных функций, предусмотренных для обычных списков: добавлять, удалять и заменять элементы, удалять дубликаты, обращаться к элементам, осуществлять их поиск и даже выполнять их частичное упорядочение. Код, реализующий манипуляции со списками типов, ограничен чисто функциональным стилем, поскольку на этапе компиляции не сушествует изменяемых величин - типы и статические константы, будучи однажды определенными, уже никогда не изменяются. По этой причине большинство операций над списками типов основано на рекурсивных шаблонах и сопоставлении образцов с помощью частичной шаблонной специализации. Списки типов полезны, когда приходится писать один и тот же код - декларативный или императивный - для каждого отдельного типа. Они позволяют абстрагировать и обобщать сущности, которые невозможно абстрагировать и обобщать с помощью других приемов программирования. По этой причине списки типов представляют собой средство для создания совершенно новых идиом и реализаций библиотек, как мы увидим в главах 9 и 10. Библиотека Loki содержит два мощных примитива для автоматической генерации иерархий классов: шаблонные классы GenScatterHierarchy и GenLinearHierarchy. Они генерируют две основные структуры классов: распределенную (см. рис. 3.2) и линейную (см. рис. 3.6). Линейная иерархия классов наиболее эффективна с точки зрения размера. Распределенная иерархия классов обладает полезным свойством: все конкретизации шаблона, определенного пользователем (передаваемого в качестве аргумента классу GenScatterHierarchy), представляют собой корни финального класса, как показано на рис. 3.2. 3.15. Краткое описание класса Typelist • Заголовочный файл: туре! ist. h. • Все сущности класса находятся в пространстве имен Loki: :TL. • Определен шаблонный класс Type!ist<Head, Tai!>. • Создание списка типов: определены макросы от typelist 1 до typelist 50. Количество принимаемых ими параметров указано в их имени. • Пользователь может повысить верхний предел макросов (50). #define typelist 51(t1, повторять вплоть до т51) \ TYPELiST(Tl, typelist(t2, повторять вплоть до j51)> • По соглашению первым элементом списков типов всегда является простой тип (не список типов), а хвост может быть либо списком типов, либо классом Nu!!Type. • В заголовочном файле определен набор примитивов, оперирующих со списками типов. По соглашению все эти примитивы возвращают результат в виде определения вложенного (внутреннего) открытого типа под названием Resu!t. Если результатом работы примитива является значение, оно имеет имя va!ue. • Примитивы описаны в табл. 3.1. • Краткое описание шаблонного класса GenScatterHierarchy: template <c1ass TList, template <c1ass> class unit> class GenScatterHierarchy; Шаблонный класс GenScatterHierarchy порождает иерархию, конкретизирующую класс unit для каждого типа, указанного в списке типов TList. Конкретизация класса GenScatterHierarchy прямо или косвенно наследует свойства класса unit<T> для каждого типа т из списка типов TList. Структура иерархии, порожденной классом GenScatterHierarchy, изображена на рис. 3.2. Краткое описание шаблонного класса GenLinearHierarchy: template <class TList, template <class, class> class unit> class GenLinearHierarchy; Шаблонный класс GenLinearHierarchy порождает линейную иерархию, изображенную на рис. 3.6. Шаблонный класс GenLinearHierarchy конкретизирует класс unit, передавая каждый тип из списка типов TList в качестве первого шаблонного параметра этого класса. Обратите внимание: класс unit должен создаваться на основе второго шаблонного параметра с помошью открытого наследования. Перегруженные функции Field обеспечивают доступ к узлам иерархии по типу и по индексу. Функция Field<Type>(obj) возвращает ссылку на конкретизацию класса unit, соответствующую указанному типу туре. Функция Field<index>(obj) возвращает ссылку на конкретизацию класса unit, соответствующую типу, позиция которого в списке типов задается целочисленной константой i ndex. Таблица 3.1. Статические алгоритмы работы со списками типов Имя примитива Описание примитива Length<TList> TypeAt<TLiSt, idx> TypeAtNonstrict<TList, idx> lndexOf<TList, т> Append<TList, T> Erase<TList, т> EraseAll<TList, т> Вычисляет длину списка типов т1 i st Возвращает тип, занимающий заданную позицию в списке типов TList (считая от нуля). Если индекс больше длины списка или равен ей, возникает ошибка компиляции Возврашает тип, занимающий заданную позицию в списке типов TList (считая от нуля). Если индекс больше длины списка или равен ей, возвращается тп NullType Возврашает индекс первого вхождения типа т в список TList. Если тип не найден, возвращает число -1 Добавляет в список TList новый тип или список типов Удаляет первое вхождение в список TList типа т (если оно есть) Удаляет все вхождения в список TList типа т (если они есть) Окончание табл. 3.1 Имя примитива Описание примитива NoDuplicates<TList, т> Replace<TList, т> ReplaceAn<TList, т> MostDerived<TList, т> DerivedToFront<TList, т> Удаляет из списка тТ i st все дубликаты Заменяет первое вхождение в список TList типа Т (если оно есть) типом U Заменяет все вхождения в список TList типа Т (если они есть) типом U Определяет наиболее глубоко вложенный тип, производный от типа Т. Если такого типа нет, возвращается тип Т Передвигает наиболее глубоко вложенные производные типы в голову списка типов Tlist 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 [ 27 ] 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |