11.13. Реализация итератора с шагом
11.13. Реализация итератора с шагом
Проблема
Имеются смежные числовые ряды и требуется обеспечить доступ к каждому n-му элементу.
Решение
В примере 11.24 представлен заголовочный файл, реализующий класс итератора с шагом.
Пример 11.24. stride_iter.hpp
#ifndef STRIDE_ITER_HPP
#define STRIDE_ITER_HPP
#include <iterator>
#include <cassert>
template<class Iter_T>
class stride_iter {
public:
// открытые имена, вводимые typedef
typedef typename std::iterator_traits<Iter_T>::value_type value_type;
typedef typename std::iterator_traits<Iter_T>::reference reference;
typedef typename std::iterator_traits<Iter_T>::difference_type
difference_type;
typedef typename std::iterator_traits<Iter_T>::pointer pointer;
typedef std::random_access_iterator_tag iterator_category;
typedef stride_iter self;
// конструкторы
stride_iter() : m(NULL), step(0) {};
stride_iter(const self& x) : m(x.m), step(x.step) {}
stride_iter(Iter_T x, difference_type n) : m(x), step(n) {}
// операторы
self& operator++() { m += step; return *this; }
self operator++(int) { self tmp = *this; m += step; return tmp; }
self& operator+=(difference_type x) { m += x * step; return *this; }
self& operator--() { m -= step; return *this; }
self operator--(int) { self tmp = *this; m -= step; return trap; }
self& operator--(difference type x) { m -= x + step; return *this; }
reference operator[](difference_type n) { return m[n * step]; }
reference operator*() { return *m; }
// дружественные операторы
friend bool operator==(const self& x, const self& y) {
assert(x.step == y.step);
return x.m == y.m;
}
friend bool operator!=(const self& x, const self& y) {
assert(x.step == y.step);
return x.m != y.m;
}
friend bool operator<(const self& x, const self& y) {
assert(x.step == y.step);
return x.m < y.m;
}
friend difference type operator-(const self& x, const self& y) {
assert(x.step == y.step);
return (x.m - y.m) / x.step;
}
friend self operator+(const self& x, difference_type y) {
assert(x.step == y.step);
return x += y * x.step;
}
friend self operator+(difference_type x, const self& y) {
assert(x.step == y.step);
return y += x * x.step;
}
private:
Iter_T m;
difference_type step;
};
#endif
Пример 11.25 показывает, как можно использовать итератор stride_iter из примера 11.24 для получения доступа к каждому второму элементу последовательности.
Пример 11.25. Применение итератора stride_iter
#include "stride_iter.hpp"
#include <algorithm>
#include <iterator>
#include <iostream>
using namespace std;
int main() {
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
stride_iter<int*> first(a, 2);
stride_iter<int*> last(a + 8, 2);
copy(first, last, ostream_iterator<int>(cout, " "));
}
Программа примера 11.25 выдает следующий результат.
0
2
4
6
Обсуждение
Итераторы с шагом часто используются при работе с матрицами. Они обеспечивают простой и эффективный способ реализации матриц в виде набора числовых рядов. Представленная в примере 11.24 реализация итератора с шагом выполнена в виде оболочки другого итератора, который передается как параметр шаблона.
Я хотел сделать итератор с шагом совместимым с STL, поэтому пришлось выбрать подходящий тип стандартного итератора и удовлетворить его требования. Представленный в примере 11.24 итератор с шагом сделан по образцу итератора с произвольным доступом.
В примере 11.26 я отдельно привел реализацию итератора с шагом (названную kstride_iter), когда размер шага известен на этапе компиляции. Поскольку размер шага передается как параметр шаблона, компилятор может оптимизировать программный код итератора более эффективно, и размер итератора уменьшается.
Пример 11.26. kstride_iter.hpp
#ifndef KSTRIDE_ITER_HPP
#define KSTRIDE_ITER_HPP
#include <iterator>
template<class Iter_T, int Step_N>
class kstride_iter {
public:
// открытые имена, вводимые typedef
typedef typename std::iterator_traits<Iter_T>::value_type value_type;
typedef typename std::iterator_traits<Iter_T>::reference reference;
typedef typename std::iterator_traits<Iter_T>::difference_type
difference_type;
typedef typename std::iterator_traits<Iter_T>::pointer pointer;
typedef std::random_access_iterator_tag iterator_category;
typedef kstride_iter self;
// конструкторы
kstride_iter() : m(NULL) {} kstride_iter(const self& x) : m(x.m) {}
explicit kstride_iter(Iter_T x) : m(x) {}
// операторы
self& operator++() { m += Step_N; return *this; }
self operator++(int) { self tmp = *this; m += Step_N; return tmp; }
self& operator+=(difference_type x) { m += x * Step_N; return *this; }
self& operator--() { m -= Step_N; return *this; }
self operator--(int) { self tmp = *this; m -= Step_N; return tmp; }
self& operator--(difference_type x) { m -= x * Step_N; return *this; }
reference operator[](difference_type n) { return m[n * Step_N]; }
reference operator*() { return *m; }
// дружественные операторы
friend bool operator==(self x, self y) { return x.m == y.m; }
friend bool operator!=(self x, self y) { return x.m != y.m; }
friend bool operator<(self x, self y) { return x.m < y.m; }
friend difference_type operator-(self x, self y) {
return (x.m - y.m) / Step_N;
}
friend self operator+(self x, difference_type y) { return x += y * Step_N; }
friend self operator+(difference_type x, self y) { return y += x * Step_N; }
private:
Iter_T m;
};
#endif
Пример 11.27 показывает, как можно использовать итератор kstride_iter.
Пример 11.27. Применение итератора kstride_iter
#include "kstride_iter.hpp"
#include <algorithm>
#include <iterator>
#include <iostream>
using namespace std;
int main() {
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
kstride_iter<int*, 2> first(a);
kstride_iter<int*, 2> last(a + 8);
copy(first, last, ostream_iterator<int>(cout, " "));
}
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Шаг за шагом
Шаг за шагом С развитием техник data:URI наиболее логичным выходом из сложившейся ситуации будет следующий характер разработки:Верстальщик создает рабочую версию макета сайта, не прибегая к помощи CSS Sprites (на каждый элемент — одна фоновая картинка).Веб-технолог внедряет
Реализация TCP/IP
Реализация TCP/IP Прежде чем перейти к описанию функционирования модулей протоколов TCP/IP, рассмотрим еще одну структуру данных, называемую управляющим блоком протокола (Protocol Control Block, PCB), который в случае TCP/IP называется Internet PCB, и представлен структурой inpcb, определенной в
Реализация 4.4BSD
Реализация 4.4BSD Если вы никогда ранее не сталкивались с таким типом устройства сервера (несколько процессов, вызывающих функцию accept на одном и том же прослушиваемом сокете), вас, вероятно, удивляет, что это вообще может работать. Пожалуй, здесь уместен краткий экскурс,
12.3.2 Реализация семафоров
12.3.2 Реализация семафоров Дийкстра [Dijkstra 65] показал, что семафоры можно реализовать без использования специальных машинных инструкций. На Рисунке 12.6 представлены реализующие семафоры функции, написанные на языке Си. Функция Pprim блокирует семафор по результатам проверки
Microsoft® Windows® SharePoint® Services 3.0 Шаг за шагом
Microsoft® Windows® SharePoint® Services 3.0 Шаг за шагом Информация для пользователей Windows ХР Рисунки и инструкции, приведенные в этой книге, соответствуют пользовательскому интерфейсу Windows Vista, однако можно использовать и Windows ХР.Большинство отличий при работе в Windows ХР относится к
Реализация gen_mem_fun_t
Реализация gen_mem_fun_t Рассмотрим реализацию mem_fun_t:template<class R, class T> struct mem_fun_t { explicit mem_fun_t(R (T::*pm_)()): pm(pm_) {} R operator()(T *p) const {return ((p->*pm)());} private: R (T::*pm)();}; Все кажется идеальным для работы с указателями, но ведь обобщенный указатель – это не указатель, он не знает, что такое operator->*!
2-й шаг. Реализация проекта
2-й шаг. Реализация проекта Теперь, когда план составлен, вы можете со всей серьезностью приступить к программированию. Возьмите в качестве отправной точки разработку внешнего вида формы, дополните ее небольшим, но тщательно выверенным фрагментом программного кода, и вы
Урок № 84. Реализация НМА
Урок № 84. Реализация НМА Нематериальные активы, как и любые другие активы, могут быть реализованы на сторону. Для отражения в учете операций по реализации нематериальных активов в программе "1С:Бухгалтерия 8" предназначен документ "Передача НМА", с которым мы познакомимся
Реализация интерфейсов в C#
Реализация интерфейсов в C# Чтобы расширить функциональные возможности класса (или структуры) путем поддержки типов интерфейса, нужно просто указать в определении класса (или структуры) список соответствующих типов, разделив их запятыми. Непосредственный базовый класс
11.2. Реализация
11.2. Реализация Во всех более-менее сложных C-программах требуется тщательно продумать организацию, чтобы сохранить модульность и обеспечить удобство сопровождения. Наша демонстрационная программа разделена на четыре главных исходных файла.В каждом исходном файле
7.3.2 Реализация
7.3.2 Реализация Реализующие slist функции в основном просты. Единственая настоящая сложность – что делать в случае ошибки, если, например, пользователь попытается get() что-нибудь из пустого списка. Мы обсудим это в #7.3.4. Здесь приводятся определения членов slist. Обратите
14.5. Реализация
14.5. Реализация Теперь мы приступим к реализации нашей оболочки, следуя тем идеям, которые обсуждались в предыдущем разделе. На рис. 14.9 показаны основные объекты, которыми манипулирует оболочка. Цель — это вопрос, подлежащий рассмотрению; Трасса — это цепочка,
12.10. РЕАЛИЗАЦИЯ
12.10. РЕАЛИЗАЦИЯ Обычно на этапе кодирования всплывают все неприятные проблемы, которые только можно себе представить. Чем больше проект, тем больше проблем. Вот почему первые три шага так важны.Если все из вышеописанных шагов полностью пройдены, то реализация программы