Анимация
JavaScript
|
Главная Библионтека объявлен производным только от тега итераторов ввода, а пе от тега итераторов вывода. Соответственно произвольный прямой итератор пе является разновидностью итератора вывода. Для прямых итераторов определены особые требования, которые отличают их от итераторов вывода. За подробностями обращайтесь на с. 260. При написании универсального кода важна не только категория итераторов. Например, вам может потребоваться тип элементов, на которые ссылается итератор. По этой причине в стандартной библиотеке С++ имеется специальный шаблон структуры, позволяющий определить варианты трактовки итераторов (iterator traits). Эта структура содержит наиболее существенную информацию об итераторе и предоставляет общий интерфейс ко всем определениям типов, ассоциированным с итератором (категория, тип элементов и т. д.): namespace std { template <class Т> struct 1terator trait5 { typedef typename T typedef typename T typedef typename T typedef typename T typedef typename T value type value type; di fference type di fference type; iterator category iterator category; pointer pointer; reference reference; В этом шаблоне Т представляет тип итератора. Это означает, что в программе для произвольного итератора можно получить доступ к его категории, типу элементов и т. д. Например, следующее выражение определяет тип значений, перебираемых итератором типа Т: typename std::iterator traits<T>::value type У такой структуры есть два важных достоинства: О она гарантирует, что итератор предоставляет все необходимые определения типов; О она может (в определенной степени) настраиваться для специальных итераторов. Например, специализация применяется для обычных указателей, которые тоже могут использоваться в качестве итераторов: namespace std { template <class Т> struct Tterator traits<T*> { typedef T value type: typedef ptrdiff t difference type: typedef random access iterator tag iterator category; typedef T* pointer; typedef T& reference: Любой тип «указателя на Т» определяется как относящийся к категории итераторов произвольного доступа. Соответствующая частичная специализация существует и для константных указателей (const Т*). Написание унифицированных функций для итераторов Благодаря механизму трактовки итераторов появляется возможность писать унифицированные функции, которые в зависимости от категории итератора используют производные определения типов или выбирают код реализации. Использование типов итераторов простым примером использования механизма трактовки итераторов является алгоритм, которому необходима временная переменная для хранения элементов. Временная перемегпгая просто объявляется в следующем виде; typename std::iterator traits<T>;:value type tmp; Здесь Т - тип итератора. Другой пример - алгоритм циклического сдвига элементов; template <class ForwardIterator> void shiftjeft (Forwardlterator beg. Forwardlterator end) Временная переменная для первого элемента typedef typename std:;1terator tra1t5<ForwardIterator>::value type value type; If (beg != end) { Сохранить значение первого элемента value type tmp(*beg); Сдвиг следующих значений Выбор категории итерэтора Выбор реализации в зависимости от категории итератора вьшолняется в два этапа. 1. При вызове другой функции ваша шаблонная функция передает ей категорию итератора в качестве дополнительного аргумента. Пример: template <class Iterator> Inline void foo (Iterator beg. Iterator end) foo (beg. end. std::iterator traits<Iterator>;;iterator category()); 2. Другая функция реализуется для всех категорий итераторов, имеющих специальную реализацию, не унаследованную от одной из категорий итераторов. Пример: fooO для двунаправленных итераторов template <class BlIterator> void foo (BiIterator beg. BiIterator end. std::bidirectional iterator tag) Версия для итераторов произвольного доступа могла бы, например, использовать возможности, не поддерживаемые двунаправленными итераторами. Благодаря иерархической структуре тегов итераторов (см. с. 287) можно предоставить одну реализацию для нескольких категорий итераторов. Выбор реализации для функции distance в следующем примере демонстрируется онисагпгая методика выбора реализации в зависимости от типа итератора. Мы рассмотрим реализацию вспомогательной функции distanceO, возвращающей расстояние между двумя позициями итераторов и их элементов (см. с. 267). Реализация для итераторов произвольного доступа сводится к простому использованию оператора -. Для остальных категорий итераторов возвращается количество операций + + , необходимых для достижения конца интервала. Унифицированная реализация функции distanceO template <class Iterator> typename std::iterator traits<Iterator>:;difference type distance (Iterator posl. Iterator pos2) return distance (posl, pos2. std::iterator traits<Iterator> ::iterator category()): Реализация функции distanceO для итераторов произвольного доступа template <class RaIterator> typename std;:iterator traits<RaIterator>::difference type distance (Ralterator posl, Ralterator pos2. std::random access iterator tag) return pos2 - posl: Реализация функции distanceO для итераторов ввода. прямых и двунаправленных итераторов template <class InIterator> 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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |