hse-oimp.github.io

Лекция 12. Алгоритмы стандартной библиотеки

using с шаблонами

В отличии от typedef, using можно использовать с template. Однако при создании нужно явно указывать типы.

template <typename T>
using IntPair = std::pair<int, T>;

void f() {
    IntPair<std::string> pair(10, "abracadabra");
}

Функции стандартной библиотеки

В стандартной библиотеке есть обширный набор функций для упрощения кода. Все последующие функции принимают первым аргументом итератор на начало части коллекции, по которой они работают, и вторым аргументом итератор на элемент после последнего элемента этой части.

std::vector<int> v {1, 2, 3, 4, 5};
std::all_of(v.begin(), v.end(), [](auto i) { return i > 0; }); // Возвращает true если все элементы v удовлетворяют условию
std::for_each(v.begin(), v.end(), [](auto& i) { std::cout << i << std::endl; }); // Запускает функцию от каждого из элементов v

Здесь для задания условия используется lambda-функция от одного параметра, возвращающая true или false. Эта функция передается третьим параметром и называется предикатом.

Следующие функции возвращают итераторы. Каждая из них возвращает итератор v.end(), если подходящих элементов в коллекции не было найдено

auto it = std::find_if(v.begin(), v.end(), [](auto x) { return x > 2; }); // Ищем первый элемент, удовлетворяющий предикату
auto it = std::search(v.begin(), v.end(), v2.begin(), v2.end()); // Обобщенный аналог поиска подстроки в строке
auto it = std::find_end(v.begin(), v.end(), v2.begin(), v2.end()); // Как и search, но ищем последнее вхождение

Эти функции копируют выбранные элементы одной коллекции в другую.

std::copy(v.begin(), v.end(), std::back_inserter(v2)); // Скопирует все элементы в конец v2
std::copy_if(v.begin(), v.end(), std::back_inserter(v2), [](auto i) { return i % 2 == 0; }); // Скопируем только четные элементы
std::move(v.begin(), v.end(), std::back_inserter(v2)); // Вместо копирования вызывает move для каждого элемента

Здесь std::back_inserter( collection ) является конструкцией, при работе с которой элемент будет добавляться в конец указанной коллекции.

Функция std::transform берет элементы первой коллекции, выполняет над ними указанную функцию, а затем добавляет в другую коллекцию.

std::transform(v.begin(), v.end(), std::back_inserter(v2), [](auto& x) { return x * 2; }) // v2 - все элементы v, умноженные на 2

Другие полезные функции.

std::remove(v.begin(), v.end(), 3); // Удаляет указанный элемент, возвращает новый конец коллекции
std::reverse(v.begin(), v.end()); // Разворачивает коллекцию