![]() |
|
Программирование >> Операторы преобразования типа
ляет пропускать лексемы во входном потоке данных. Например, рассмотрим следующие входные данные: No one objects if you are doing a good programming job for someone whom you respect. Для этих данных будет получен такой результат: objects are good for you Прежде чем обращаться к значению *cinPos после вызова advance(), не забудьте убедиться в том, что потоковый итератор вывода остался действительным. Вызов оператора * для итератора конца потока данных приводит к непредсказуемым последствиям. Другие примеры использования потоковых итераторов при чтении из потока данных и записи в поток данных приведены на с. 118, 361 и 378. Грактовка итераторов Итераторы делятся на категории (см. с. 257) в соответствии со своими специфическими возможностями. Иногда бывает удобно и даже необходимо переопределить поведение итератора для других категорий. Такое переопределение выполняется при помощи механизма тегов и трактовок итераторов. Для каждой категории итераторов в стандартной библиотеке С++ определяется тег, предназначенный для ссылок на данную категорию: namespace std { struct outputJterator tag { struct input iterator tag { ): struct forward iterator tag : public input 1terator tag { struct bldirectional iterator tag : public forward iterator tag { struct random access iterator tag : public bidirectionaljterator tag { Обратите внимание иа наследование. Так, из представленной иерархии следует вывод, что любой прямой итератор forwardJterator tag является разновидностью итератора ввода input iterator tag. Но заметьте, что тег прямых итераторов Спасибо Эндрю Кенигу (Andrew Kocnig) за хороший пример. объявлен производным только от тега итераторов ввода, а не от тега итераторов вывода. Соответственно произвольный прямой итератор пе является разновидностью итератора вывода. Для прямых итераторов определены особые требования, которые отличают их от итераторов вывода. За подробностями обращайтесь на с. 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 d1fference type; iterator category iterator category; pointer pointer; reference reference; В этом шаблоне Т представляет тип итератора. Это означает, что в программе для произвольного итератора можно получить доступ к его категории, типу элементов и т. д. Например, следующее выражение определяет тип значений, перебираемых итератором типа Т: typename std::1terator traits<T>::value type У такой структуры есть два важных достоинства: О она гарантирует, что итератор предоставляет все необходимые определения тигюв; О она может (в определенной степени) настраиваться для специальных итераторов. Например, специализация применяется для обычных указателей, которые тоже могут использоваться в качестве итераторов; namespace std { template <class Т> struct Tterator tralts<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 tra1ts<ForwardIterator>::value type value type; 1f (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());
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |