# Третий семинар ## Шаблоны ```cpp // template template void swap(T& a, T& b) { T tmp; tmp = a; a = b; b = tmp; } ``` Можно применять и от нескольких неизвестных параметров ```cpp template void transfer(T fromAccount, T toAccount, K code, int sum) { std::cout << "From: " << fromAccount << "\nTo: " << toAccount << "\nSum: " << sum << "\nCode: " << code << std::endl; } ``` Пример кода для абсолютного значения: ```cpp template T abs(const T& x) { // template T abs(T x) { return x >= 0 ? x : -x; } ``` Суммирование элементов массива ```cpp template T sum(T* mas, int N) { T res = 0; for (int i = 0; i < N; ++i) { res += mas[i]; } return res; } int main() { double mas[5] = {...}; std::cout << sum(mas, 5); return 0; } ``` ```cpp template T sum(T* mas, int N) { T res = 0; for (int i = 0; i < N; ++i) { res += mas[i]; } return res; } int main() { double mas[5] = {...}; std::cout << sum(mas); return 0; } ``` ## Что-то про стэк Вторая задача: Суть была реализовывать динамически расширяемый массив ```cpp template class st { T st[SIZE]; int top = 0; public: void push(T a) { if (top == SIZE) { // error } else { st[top++] = a; } } T pop(); } template T st::pop() { return st[--top]; } ``` Если указать стандартное значение для каких-то параметров, вызов обычный ## Библиотеки ### Контейнеры #### Последовательности - list - двунаправленный список - vector - deque - очередь На их основе создаются: - stack - queue #### Ассоциативные массивы - map - отображения - multimap - ключ может несколько раз встречаться - set - уникальные упорядоченные ключи - multiset - совпадающие ключи ### Итераторы `#include ` - подключение библиотеки - value_type - тип значений в контейнере - size_type - аналог size_t - reference/ const reference - ссылки на элемент - pointer/const pointer - указатели Исполняют роль указателей Для каждого контейнера определён: - iterator - идёт от начала - reverse_iterator - идёт с конца - const_iterator - не меняет значений - const_reverse_iterator - не меняет значений, ревёрс ```cpp begin(), end(); rbegin(), rend(); cbegin(), cend(); // для константных ``` Виды итераторов: - input - output - forward - bidirectional - list, map, set - random_access - для vector deque, можно индексировать, += n ```cpp #include int main() { vector v1; // длина 0 vector v2(5); // длина 5, занулены vector v3(10, '*'); int m[] = {1, 2, 3, 4}; vector v4(m, m + 4); // vector v4(m.begin(), m.end()); } ``` ```cpp for (int i = 0; i < v.size(); ++i) cout << v[i] << " "; // только для random_access контейнера v[i] == v.at(i) // выдаёт out_of_range, если нет элемента ``` Печать элементов в прямом и обратном при помощи итераторов ```cpp #include #include // прямой с помощью прямого void f1(std::vector mas) { std::vector::std::iterator iter = mas.begin(); while (iter != mas.end()) { std::cout << *iter << " "; iter++; } } // обратный с помощью реверсивного void f2(std::vector mas) { std::vector::std::reverse_iterator iter = mas.rbegin(); while (iter != mas.rend()) { std::cout << *iter << " "; iter++; } } // обратный с помощью прямого void f3(std::vector mas) { std::vector::std::iterator iter = mas.end(); while (iter != mas.begin()) { --iter; std::cout << *iter << " "; } } ``` Или же код нормального человека: ```cpp for (auto x : v) cout << x << " "; ``` ### Алгоритмы Некоторые методы контейнеров: - `size_type size()` - количество элементов в контейнере - `bool empty()` - пустой ли контейнер - `void clear()` - очищает контейнер - `void push_back()` - добавляет в конец value_type<> - `void pop_back()` - удаляет последний элемент - `reference back()` - возвращает ссылку на последний элемент - `reference front()` - возвращает ссылку на первый элемент - `iterator insert(iterator p, value_type<>)` - вставка перед позицией p, возвращает на новый элемент - `iterator erase(iterator p)` - удаляет, куда указывает, возвращает итератор на некст элемент - `iterator erase(iterator p1, iterator p2)` - c первого до последнего (не включительно) для list, deque - `void push_front(value_type<>)` - `void pop_front(value_type<>)` Для bidirectional итераторов можно использовать - `advance(p1, 3)` для плюса - `n = distance(p1, p2)` для вычитания ```cpp void f(vactor& mas) { auto iter = mas.begin(); while (iter < mas.end()) { ++iter; if (iter != mas.end()) iter = mas.erase(iter); } } ```