next C++ |
Ссылки |
Улучшения языка C |
Классы |
Перегрузка функций и операций |
Шаблоны |
Наследование |
Исключительные ситуации |
Лабораторные работы |
Курсовая работа |
Вопросы к экзамену |
В качестве последовательности может быть использован любой контейнерный класс, а в пространстве имен std::views
определены следующие генераторы:
Диапазон | Описание |
---|---|
views::empty() | пустая последовательность |
views::single(x) | одно значение |
views::iota(a) | последовательность [a,+∞) |
views::iota(a,b) | последовательность [a,b) |
views::counted(first,n) | n значений, начиная с first |
Для обработки последовательностей можно использовать специальные варианты алгоритмов, объявленные в пространстве имен std::ranges
.
Их можно применять ко всему содержимому контейнера, не указывая begin и end.
#include <ranges>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
vector<int> v{ 5, 10, 8, 3, 6, 12 };
ranges::sort(v);
for(auto x : views::iota(1,10)) {...}
int a[100];
for(auto x : views::counted(a,10)) {...}
}
С последовательностями можно выполнять следующие операции:
Операция | Описание |
---|---|
views::take(n) | взять первые n значений |
views::take_while(fun) | взять первые значения, удовлетворяющие fun |
views::drop(n) | пропустить первые n значений |
views::drop_while(fun) | пропустить первые значения, удовлетворяющие fun |
Операции применяются в форме последовательность|операция1|операция2|… или операция(последовательность,параметры)
Для преобразования последовательности используются операции
Операция | Описание |
---|---|
views::reverse | в обратном порядке |
views::transform(fun) | выполнить fun над каждым элементом |
views::filter(fun) | оставить в последовательности только значения, удовлетворяющие fun |
views::keys | извлечь первое поле пары |
views::values | извлечь второе поле пары |
views::elements<K> | извлечь K-е поле кортежа |
views::split(v) | разделение на подпоследовательности по v |
views::join | соединение подпоследовательностей в одну |
Для ввода данных можно использовать генератор ranges::istream_view<T>(istream)
#include <iostream>
#include <ranges>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> v;
int n; cin>>n;
ranges::copy(ranges::istream_view<int>(cin)|
views::take(n),
back_inserter(v));
for(auto x:v|views::filter([](int x){ return x%2==0; })|
views::transform([](auto x){return x*x;}))
{ cout<<x<<"\n"; }
}
// вывести квадраты введенных чисел
ranges::copy(ranges::istream_view<int>(cin)|
views::transform([](auto x){return x*x;}),
std::ostream_iterator<int>(cout, "\n"));
Альтернативный подход к обработке последовательностей предложен в библиотеке pipes
std::vector<int> v{ 5, 10, 8, 3, 6, 12 };
std::vector<int> r;
v>>=pipes::filter([](auto x){ return x%2 == 0; })
>>=pipes::transform([](int x){ return x*x; })
>>=pipes::push_back(r);
ranges основаны на "вытягивании", поскольку компоненты запрашивают следующее значение, то есть читают данные в ленивом режиме. pipes основаны на "выталкивании" и предназначены для отправки данных по мере их поступления в конечную точку через конвейер, то есть компоненты ждут следующего значения.
Оба набора классов имеют похожие компоненты, такие как преобразование и фильтр. Но pipes могут смешивать и разделять (fork) последовательности, а ranges могут обрабатывать бесконечные последовательности.