std::ranges::range
Материал из cppreference.com
Определено в заголовочном файле <ranges> | ||
template<class T > concept range = requires(T& t){ | ||
Концепт range
определяет требования к типу, который позволяет выполнять итерацию по своим элементам, предоставляя итератор и ограничитель, которые обозначают элементы диапазона.
[править]Требования семантики
Учитывая выражение E такое, что decltype((E)) равно T, T моделирует range, только если
- [ranges::begin(E), ranges::end(E)) обозначают диапазон, и
- оба ranges::begin(E) и ranges::end(E) амортизируются с постоянным временем и не меняют значение E способом, используемым для выражений, сохраняющих равенство, и
- если тип ranges::begin(E) моделирует
forward_iterator
, ranges::begin(E)сохраняет равенство (другими словами, прямые итераторы поддерживают многопроходные алгоритмы)
Примечание. В приведённом выше определении требуемые выражения ranges::begin(t) и ranges::end(t) не требуют неявные варианты выражения.
[править]Примечание
Типичный класс range
должен предоставлять только две функции:
- Функция-элемент
begin()
, тип возвращаемого значения которой моделируетinput_or_output_iterator
. - Функция-элемент
end()
, тип возвращаемого значения которой моделируетsentinel_for
<It>
, гдеIt
это тип возвращаемого значенияbegin()
.
Альтернативно, они могут быть функциями, не являющимися элементами, которые можно найти с помощью поиска, зависящего от аргументов.
[править]Пример
Запустить этот код
#include <iostream>#include <ranges>#include <vector> template<typename T>struct range_t :private T {using T::begin, T::end;/*...*/}; static_assert(std::ranges::range< range_t<std::vector<int>>>); template<typename T>struct scalar_t { T t{};/* нет begin/end */}; static_assert(not std::ranges::range< scalar_t<int>>); int main(){ifconstexpr(range_t<std::vector<int>> r; std::ranges::range<decltype(r)>){std::cout<<"r диапазон\n";} ifconstexpr(scalar_t<int> s; not std::ranges::range<decltype(s)>){std::cout<<"s не диапазон\n";}}
Вывод:
r диапазон s не диапазон