Ітератори STL
Концепція ітераторів Концепцію типу ітератора формують три ключові положення: ітератор забезпечує непрямий доступ до елементів послідовності; після інкременту вказує на наступний елемент послідовності; забезпечує перевірку на співпадіння (рівність) з іншим ітератором.
Особливості ітераторів STL Відповідність ітераторного типу концепції контейнера : у векторі – це традиційний вказівник на тип контейнерового елемента, тому операції з ітератором еквівалентні операціям з вказівниками у списку – спеціальний дружній клас, функціональність якого базується на безпосередній роботі з вузлами списку Уніфікованість контейнерних ітераторів з метою застосовності до різнотипових контейнерів загальних алгоритмів наявність бібліотечних ітераторних класів, які разом з допоміжними функціями оголошені в просторі назв std, заголовковий файл надання ітераторам спеціальних властивостей
Категорії ітераторів Ітератор виведення
Теги стандартних ітераторів //xutility internal header struct output_iterator_tag { output_iterator_tag() {;} }; struct input_iterator_tag { input_iterator_tag() {;} }; struct forward_iterator_tag : public input_iterator_tag { forward_iterator_tag() {;} }; struct bidirectional_iterator_tag : public forward_iterator_tag { bidirectional_iterator_tag() {;} }; struct random_access_iterator_tag : public bidirectional_iterator_tag { random_access_iterator_tag() {;} };
Уніфіковані властивості ітераторів template struct iterator// базовий тип для ітераторів { typedef T value_type; typedef Distance difference_type; typedef Pointer pointer;//тип, який повертає operator –>() typedef Reference reference;//тип, який повертає operator *() typedef Category iterator_category; };
Тип характеристик ітераторів template struct iterator_traits { typedef typename Iterator::value_type value_type; typedef typename Iterator::difference_type difference_type; typedef typename Iterator::pointer pointer; typedef typename Iterator::reference reference; typedef typename Iterator::iterator_category iterator_category; };
Використання характеристик template typename iterator_traits::difference_type count(InIter first, InIter last, const T& val){ typename iterator_traits ::difference_type res=0; while (first!=last) if (*first++ ==val) ++res; return res; }
Категорії ітераторів стандартних класів
Генерування ітераторів контейнерами Для роботи з конкретним контейнером генерується в тісному взаємозв’язку з характерними для типу контейнера класами, напр., розподілювача пам’яті, вузла списку і т.п.. Кожен стандартний контейнер автоматично обслуговує функціонування ітераторів. Сукупна система класів, задіяних з цією метою, є достатньо складною, але важливо, що це в основному класи реалізації. Простота оголошення ітератора, достатньо лише вказати стандартну назву ітераторного типу, вбудованого в його шаблон, і далі використовувати притаманні для цього типу методи. Наприклад, два подібні оголошення vector ::iterator iter1; list ::iterator iter2; приводять до утворення ітератора довільного доступу в першому випадку, і двонаправленого в другому.
Ітератори введення, приклад використання Використані операції ітератора введення: !=, *, ++, тому тип ітератора будь-якого контейнера сумісний з типом InputIterator template InputIterator find(InputIterator first, InputIterator last, const T& value) { while (first != last && *first != value) ++first; return first; }
class istream_iterator template , class Distance = ptrdiff_t> class istream_iterator : public iterator { friend bool operator==(const istream_iterator&x, const istream_iterator& y); protected: istream* stream; T value; bool end_marker; void read (); public: typedef T value_type; typedef charT char_type; typedef traits traits_type; typedef istream istream_type; istream_iterator() : stream(&cin), end_marker(false) {} istream_iterator(istream& s) : stream(&s) { read(); } istream_iterator(const istream_iterator& x ) :stream(x.stream) , value(x.value) , end_marker(x.end_marker) { } const T& operator* () const { return value; } istream_iterator& operator++ (); istream_iterator operator++(int); };
без >> istream_iterator is(cin); int i1=*is; ++is; int i2=*is; istream_iterator is(ifs),eostr; remove_copy_if(is,eostr,ins,not1(later_then(y)));
Ітератори виведення, приклад використання template OutputIterator copy(In first, In last, OutputIterator result) { while (first != last) *result++ = *first++; return result; } Використані операції ітератора введення: *, ++, тому тип ітератора будь-якого неконстантного контейнера сумісний з типом OutputIterator ostream_iterator os(ofs); copy(publ.begin(),publ.end(),os);
class ostream_iterator template > class ostream_iterator : public iterator { protected: ostream* stream; const char* str; // delimiter public: typedef T value_type; typedef charT char_type; typedef traits traits_type; typedef ostream istream_type; ostream_iterator(ostream& s) :stream(&s), str(0){} ostream_iterator(ostream& s,const char* c) : stream(&s), str((char *)c){} ostream_iterator( const ostream_iterator& x ) :stream(x.stream) , str(x.str){} ostream_iterator& operator=(const T& value){ *stream << value; if (str) *stream << str; return *this; } ostream_iterator& operator*(){ return *this; } ostream_iterator& operator++(){ return *this; } ostream_iterator& operator++(int){ return *this; } };
Особливості використання ітераторів потоку ostream_iterator та istream_iterator – обгорткові класи, тому необхідний традиційний контроль за станом потоку і позицією в потоці спрощений синтаксис виразів з ostream_iterator ostreambuf_iterator та istreambuf_iterator – ітератори для посимвольної роботи з буфером потоку, замість потоку містять лише private-буфер solution STL_iterators In_Out_stream_iters Stream_iters_1 Stream_iters_2 StreambufIterator
class insert_iterator template class insert_iterator :public iterator { private: typename Container::iterator iter; protected: Container* container; public: typedef Container container_type; typedef typename Container::value_type value_type; insert_iterator(Container& x,typenameContainer::iterator i) : container(&x), iter(i) {} insert_iterator& operator=(const typename Container::value_type& value){ iter=container->insert(iter,value); ++iter; return *this; } insert_iterator& operator*(){ return *this; } insert_iterator& operator++(){ return *this; } insert_iterator& operator++ (int){ return *this; } };
Ітераторна функція inserter() template inline insert_iterator inserter(Container& Cont, Iter Where) { // return insert_iterator return (std::insert_iterator(Cont,Where)); }
Інші ітератори вставки та ітераторні функції template class back_insert_iterator :public iterator{...}; template class front_insert_iterator :public iterator{....}; template inline back_insert_iterator back_inserter(Cont& ); template inline front_insert_iterator front_inserter(Cont& );
Ітератори вставки, приклади використання int arr[4] = {3,4,7,8}; vector v(arr,arr+4); insert_iterator > ins(v, v.begin()+2); ins = 5; ins = 6; solution STL_iterators Insert_iter_list Insert_iter_vector Insert_iter_vector_strings