Библиотека диапазонов (C++20)
Библиотека диапазонов является расширением и обобщением библиотек алгоритмов и итераторов, что делает их более мощными, составными и менее подверженным ошибкам.
Библиотека создаёт и управляет представлениями диапазонов, облегчёнными объектами, которые косвенно представляют итерируемые последовательности (диапазонов). Диапазоны это абстракция над
- пары итераторов [начало, конец), например диапазоны, созданные неявным преобразованием из контейнеров. Все алгоритмы, использующие пары итераторов, теперь имеют перегрузки, которые принимают диапазоны (например, ranges::sort)
- подсчитанные последовательности [начало, размер), т.е. диапазон, возвращённый views::counted
- условно-завершённые последовательности [начало, предикат), например диапазон, возвращаемый views::take_while
- неограниченные последовательности [начало..), например диапазон, возвращённый views::iota
Библиотека диапазонов включает алгоритмы диапазонов, которые применяются к диапазонам активно, и адаптеры диапазонов, которые применяются к представлениям лениво. Адаптеры могут быть объединены в конвейеры, чтобы их действия происходили по мере повторения представления.
| Определено в заголовочном файле <ranges>
|
||
| namespace std { namespace views = ranges::views; |
(начиная с C++20) | |
Псевдоним пространства имён std::views предоставляется как сокращение для std::ranges::views.
| Определены в пространстве имён
std::ranges | ||
Доступ к диапазонам | ||
| Определены в заголовочном файле
<ranges> | ||
| Определены в заголовочном файле
<iterator> | ||
| (C++20) |
возвращает итератор на начало диапазона (объект точки настройки) | |
| (C++20) |
возвращает ограничитель, указывающий на конец диапазона (объект точки настройки) | |
| (C++20) |
возвращает итератор на начало диапазона только для чтения (объект точки настройки) | |
| (C++20) |
возвращает ограничитель, указывающий на конец диапазона, доступного только для чтения (объект точки настройки) | |
| (C++20) |
возвращает обратный итератор на диапазон (объект точки настройки) | |
| (C++20) |
возвращает обратный конечный итератор диапазона (объект точки настройки) | |
| (C++20) |
возвращает обратный итератор на диапазон только для чтения (объект точки настройки) | |
| (C++20) |
возвращает обратный конечный итератор на диапазон только для чтения (объект точки настройки) | |
| (C++20) |
возвращает целое число, равное размеру диапазона (объект точки настройки) | |
| (C++20) |
возвращает целое число со знаком, равное размеру диапазона (объект точки настройки) | |
| (C++20) |
проверяет, пуст ли диапазон (объект точки настройки) | |
| (C++20) |
получает указатель на начало непрерывного диапазона (объект точки настройки) | |
| (C++20) |
получает указатель на начало непрерывного диапазона, доступного только для чтения (объект точки настройки) | |
Примитивы диапазонов | ||
| Определены в заголовочном файле
<ranges> | ||
| получает связанные типы диапазона (псевдоним шаблона) | ||
Обработка висячих итераторов | ||
| Определены в заголовочном файле
<ranges> | ||
| (C++20) |
тип заполнителя, указывающий, что итератор или поддиапазон не должны быть возвращены, так как они будут висячими (класс) | |
получает тип итератора или тип поддиапазона из borrowed_range (псевдоним шаблона) | ||
Концепты диапазонов | ||
| Определены в заголовочном файле
<ranges> | ||
| (C++20) |
указывает, что тип является диапазоном, то есть предоставляет итератор begin и ограничитель end (концепт) | |
| (C++20) |
указывает, что тип является range, и итераторы, полученные из его выражения, могут быть безопасно возвращены без опасности зависания (концепт) | |
| (C++20) |
указывает, что диапазон узнаёт свой размер за константное время (концепт) | |
| (C++20) |
указывает, что диапазон является представлением, то есть имеет постоянное время копирования/перемещения/присваивания (концепт) | |
| (C++20) |
указывает диапазон, тип итератора которого соответствует input_iterator (концепт) | |
| (C++20) |
указывает диапазон, тип итератора которого соответствует output_iterator (концепт) | |
| (C++20) |
указывает диапазон, тип итератора которого соответствует forward_iterator (концепт) | |
| (C++20) |
указывает диапазон, тип итератора которого соответствует bidirectional_iterator (концепт) | |
| (C++20) |
указывает диапазон, тип итератора которого соответствует random_access_iterator (концепт) | |
| (C++20) |
указывает диапазон, тип итератора которого соответствует contiguous_iterator (концепт) | |
| (C++20) |
указывает, что диапазон имеет идентичные типы итератора и ограничителя (концепт) | |
| (C++20) |
определяет требования к range для безопасного преобразования в view (концепт) | |
Представления | ||
| Определены в заголовочном файле
<ranges> | ||
| (C++20) |
шаблон вспомогательного класса для определения view, используя любопытно повторяющийся образец шаблон (шаблон класса) | |
| (C++20) |
объединяет пару итератор-ограничитель в view (шаблон класса) | |
[править] Фабрики диапазонов
| Определены в заголовочном файле
<ranges> | |
| Определены в пространстве имён
std::ranges | |
| пустой view без элементов (шаблон класса) (шаблонная переменная) | |
| view, который содержит единственный элемент указанного значения (шаблон класса) (объект точки настройки) | |
| (C++20) |
view, состоящий из последовательности, сгенерированной путём многократного увеличения начального значения (шаблон класса) (объект точки настройки) |
| view, состоящий из элементов, полученных последовательным применением operator>> к соответствующему входному потоку (шаблон класса) (объект точки настройки) | |
[править] Адаптеры диапазонов
| Определены в заголовочном файле
<ranges> | |
| Определены в пространстве имён
std::ranges | |
| (C++20) |
view, который включает все элементы range (псевдоним шаблона) (объект адаптера диапазона) |
| (C++20) |
view из элементов некоторого другого range (шаблон класса) |
| (C++20) |
view с уникальным владельцем некоторого range (шаблон класса) |
| view, который состоит из элементов range, который соответствует предикату (шаблон класса) (объект адаптера диапазона) | |
| view последовательности, которая применяет функцию преобразования к каждому элементу (шаблон класса) (объект адаптера диапазона) | |
| (C++20) |
view, состоящий из первых N элементов другого view (шаблон класса) (объект адаптера диапазона) |
| view, состоящий из начальных элементов другого view, до первого элемента, для которого предикат не вернёт false (шаблон класса) (объект адаптера диапазона) | |
| (C++20) |
view, состоящий из элементов другого view, пропуская первые N элементов (шаблон класса) (объект адаптера диапазона) |
| view, состоящий из элементов другого view, пропуская начальную подпоследовательность элементов до первого элемента, для которого предикат вернет false (шаблон класса) (объект адаптера диапазона) | |
| (C++20) |
view, состоящий из последовательности, полученной уплотнением view, состоящего из range (шаблон класса) (объект адаптера диапазона) |
| view по поддиапазонам, полученным в результате разделения другого view с использованием разделителя (шаблон класса) (объект адаптера диапазона) | |
| view по поддиапазонам, полученным в результате разделения другого view с использованием разделителя (шаблон класса) (объект адаптера диапазона) | |
| (C++20) |
создаёт поддиапазон из итератора и счётчика (объект точки настройки) |
| преобразует view в common_range (шаблон класса) (объект адаптера диапазона) | |
| view, который перебирает элементы другого двунаправленного представления в обратном порядке (шаблон класса) (объект адаптера диапазона) | |
| принимает view, состоящий из значений, подобных кортежу, и числа N, и создаёт view из N-го элемента каждого кортежа (шаблон класса) (объект адаптера диапазона) | |
| (C++20) |
принимает view, состоящий из парных значений, и создаёт view первых элементов каждой пары (шаблон класса) (объект адаптера диапазона) |
| принимает view, состоящий из парных значений, и создаёт view из вторых элементов каждой пары (шаблон класса) (объект адаптера диапазона) | |
| (C++23) |
view, состоящий из кортежей ссылок на соответствующие элементы адаптированных представлений (шаблон класса) (объект точки настройки) |
| view, состоящий из кортежей результатов применения функции преобразования к соответствующим элементам адаптированных представлений (шаблон класса) (объект точки настройки) | |
| view, состоящий из кортежей ссылок на соседние элементы адаптированного представления (шаблон класса) (объект адаптера диапазона) | |
| view, состоящий из кортежей результатов применения функции преобразования к смежным элементам адаптированного представления (шаблон класса) (объект адаптера диапазона) | |
Некоторые адаптеры диапазонов заключают свои элементы или объекты функции в способную к копированию оболочку.
[править] Объекты адаптеров диапазонов
Объекты адаптеров диапазонов это объекты точки настройки, которые принимают viewable_range в качестве своих первых аргументов и возвращают view. Некоторые объекты адаптеров диапазонов являются унарными, т.е. они принимают один viewable_range в качестве единственного аргумента. Другие объекты адаптеров диапазонов принимают viewable_range и другие завершающие аргументы.
Если объект адаптера диапазона принимает более одного аргумента, он также поддерживает частичное применение:
- пусть
aбудет таким объектом адаптера диапазона, и - args... будет аргументами (обычно подходит для завершающих аргументов),
выражение a(args...) имеет следующие свойства:
- оно действительно тогда и только тогда, когда для каждого аргумента e в args... такого что
Eравно decltype((e)), std::is_constructible_v<std::decay_t<E>, E> равно true, - когда вызов действителен, его объект результата сохраняет подобъект типа std::decay_t<E> инициализированный напрямую без списка с помощью std::forward<E>(e), для каждого аргумента e в args... (другими словами, объекты адаптеров диапазонов связывают аргументы по значению), и
- объект результата это объект замыкания адаптера диапазона (смотрите ниже).
Как и другие объекты точки настройки, пусть
-
aбудет объектом cv-неквалифицированной версии типа любых объектов адаптеров диапазонов, - args... будет любой группой аргументов, соответствующих ограничениям operator() типа
a,
вызовы
- a(args...),
- std::as_const(a)(args...),
- std::move(a)(args...), and
- std::move(std::as_const(a))(args...)
эквивалентны.
Объектом результата каждого из этих выражений является либо объект view, либо объект замыкания адаптера диапазона.
Примечания: operator() не поддерживается для версий типов объектов адаптеров диапазонов, квалифицированных как volatile или const volatile. При связывании массивы и функции преобразуются в указатели.
[править] Объекты замыкания адаптеров диапазонов
Объекты замыкания адаптеров диапазонов это объекты, тип которых совпадает с типом одного из следующих объектов (без учёта cv-квалификации):
- унарные объекты адаптеров диапазонов,
- результаты привязки конечных аргументов объектами адаптеров диапазонов, и
- результаты объединения двух объектов замыкания адаптеров диапазонов с помощью operator|.
Объекты замыкания адаптеров диапазонов принимают один viewable_range в качестве единственного аргумента и возвращают view. Их можно вызвать с помощью оператора конвейера: если C объект замыкания адаптера диапазона, а R это viewable_range, эти два выражения эквивалентны:
C(R) R | C
Этот вызов перенаправляет связанные аргументы (если есть) в связанный объект адаптера диапазона. В этом вызове связанные аргументы в C (если есть) идентично обрабатываются как левостороннее или правостороннее значение и cv-квалифицированы как C.
Два объекта замыкания адаптеров диапазонов могут быть связаны с помощью operator| для создания другого объекта замыкания адаптеров диапазонов: если C и D являются объектами замыкания адаптеров диапазонов, то C | D также является объектом замыкания адаптеров диапазонов, если это допустимо.
Связанные аргументы C | D определяются следующим образом:
- в объекте результата есть субъект того же типа (cv-квалификация отброшена) для каждого подобъекта в обоих операндах, который является связанным аргументом,
- такой связанный аргумент инициализируется напрямую, без списка инициализации, с исходным подобъектом в содержащем его операнде, где источник идентично обрабатывается как левостороннее или правостороннее значение и cv-квалифицируется как операнд,
- результат действителен тогда и только тогда, когда правильна инициализация всех связанных аргументов.
Эффект и валидность результата operator() определяется следующим образом: при viewable_range R эти два выражения эквивалентны (оба правильно или неправильно сформированы):
R | C | D // (R | C) | D R | (C | D)
Примечание: operator() не поддерживается для версий типов замыкания объектов адаптеров диапазонов с квалификацией volatile или const volatile.
[править] Вспомогательные концепты
Следующие концепты только для описания и используются для нескольких типов, но они не являются частями интерфейса стандартной библиотеки.
| template<class R> concept __SimpleView = // только разъяснение |
||
[править] Примечание
Макрос тестирования функциональности: __cpp_lib_ranges
[править] Пример
#include <ranges> #include <iostream> int main() { auto const ints = {0,1,2,3,4,5}; auto even = [](int i) { return 0 == i % 2; }; auto square = [](int i) { return i * i; }; // "конвейерный" синтаксис для создания представлений: for (int i : ints | std::views::filter(even) | std::views::transform(square)) { std::cout << i << ' '; } std::cout << '\n'; // традиционный "функциональный" синтаксис составления: for (int i : std::views::transform(std::views::filter(ints, even), square)) { std::cout << i << ' '; } }
Вывод:
0 4 16 0 4 16
[править] Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
| Номер | Применён | Поведение в стандарте | Корректное поведение |
|---|---|---|---|
| LWG 3509 | C++20 | было неясно, как объекты адаптеров диапазонов связывают конечные аргументы | они связаны по значению |

