Поделиться через


subrange class (стандартная библиотека C++)

Предоставляет представление части элементов диапазона, определенных начальным итератором и sentinel.

Синтаксис

template<input_or_output_iterator I, sentinel_for<I> S, subrange_kind K>
  requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>)
class subrange : public view_interface<subrange<I, S, K>>

Параметры шаблона

I
Тип итератора начала. Концепция input_or_output_iterator гарантирует, что I это итератор, который может считывать все элементы.

K
Тип подранга: используется subrange_kind::sized для указания подранга размера. Используйте, sized_sentinel_for<S, I> если итератор и sentinel можно вычитать для получения размера. Требование subrange_kind::sized || !sized_sentinel_for<S, I> сохраняет размер локально в объекте subrange и требует создания подранга либо с помощью конструктора, принимающего ( sized_range для которого вы указали subrange_kind::sized здесь), либо через конструктор, iteratorпринимающий объект , sentinelи size (поэтому вы указали sized_sentinel_for<S, I> здесь).

S
Тип итератора конца. Концепция sized_sentinel_for гарантирует, что S можно использовать в качестве sentinel и I что можно вычислить расстояние между sentinel и текущим положением итератора в постоянном I времени.

Просмотр характеристик

Описание следующих записей см. в разделе "Просмотр характеристик класса"

Characteristic Description
Адаптер диапазона views::counted
Базовый диапазон Любой диапазон
Тип элемента iter_reference_t<I>
Просмотр категории итератора То же, что Iи категория s
Размер Если K имеет значение subrange::sized
Is const-iterable Если I можно скопировать
Общий диапазон Если I и S один и тот же тип.
Заимствуемый диапазон Да

Участники

Функции-члены Description
КонструкторыC++20 Создайте subrange
operator PairLikeC++20 subrange Преобразуйте тип, похожий на пару.
advanceC++20 Перемещение итератора заданного расстояния.
begin Получите итератор к первому элементу.
emptyC++20 Проверьте, является ли пустой subrange .
endC++20 Получите sentinel в конце subrange.
nextC++20 Создает копию этого subrange , но с хранимым итератором перемещается вперед указанное расстояние.
prevC++20 Создает копию этого subrange , но с сохраненным итератором перемещается обратно указанное расстояние.
sizeC++20 Получение количества элементов.
Наследуется от view_interface Description
backC++20 Получите последний элемент.
dataC++20 Получите указатель на первый элемент.
frontC++20 Получите первый элемент.
operator[]C++20 Получите элемент в указанной позиции.
operator boolC++20 Проверьте, является ли пустой subrange .

Замечания

Это subrange полезно, если у вас есть итератор начала и конца, но вы хотите передать один объект. Например, если вы хотите вызвать адаптер диапазона, но имел начальный и конечный итератор, можно использовать subrange для их упаковки и передачи subrange адаптеру диапазона.

Требования

Заголовок: <ranges> (с C++20)

Пространство имен: std::ranges

Параметр компилятора: /std:c++20 или более поздней версии требуется.

Конструкторы

Создайте subrange.

1) subrange() requires default_initializable<I> = default;
2) template <Convertible_to_non_slicing<I> It>
    constexpr subrange(It begin, S end) requires (!Store_size);
3) template <Convertible_to_non_slicing<I> It>
    constexpr subrange(It begin, S end, const Size_type size) requires (K == subrange_kind::sized);
4) template <Not_same_as<subrange> rg>
    requires borrowed_range<rg>
        && Convertible_to_non_slicing<iterator_t<rg>, I>
        && convertible_to<sentinel_t<rg>, S>
    constexpr subrange(rg&& r) requires (!_Store_size || sized_range<rg>);
5) template <borrowed_range rg>
        requires Convertible_to_non_slicing<iterator_t<rg>, I> && convertible_to<sentinel_t<rg>, S>
    constexpr subrange(rg&& r, const _Size_type sizeHint) requires (K == subrange_kind::sized)

Параметры

begin
Итератор, указывающий на первый элемент в подранге.

end
Sentinel, указывающий на конец подранга. Элемент, на который он указывает, не входит в подранг.

sizeHint
Размер диапазона в элементах. Это используется для оптимизации size функции-члена и требуется, если вы хотите сделать размер subrange из итератора и sentinel, типы которых не моделировать sized_sentinel_for.

Сведения о типах параметров шаблона см. в разделе "Параметры шаблона".

Возвращаемое значение

Экземпляр класса subrange.

Замечания

1) По умолчанию создает хранимый итератор и sentinel. Указание размера имеет значение 0.
2) Используется std::move() для перемещения begin итератора и end sentinel в сохраненный итератор и sentinel.
3) Инициализирует хранимый итератор с std::move(begin), сохраненный sentinel с std::move(end)указанием размера и указанием sizeхранящегося размера, с которым должно быть равно расстояние между первым и вторым аргументами.
4) Создание subrange из диапазона.
5) Поведение не определено, если szHint != ranges::distance(rg).

Адаптер counted диапазона может создать subrange. Этот адаптер принимает итератор начала и счетчика.

Пример: counted

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    auto pos5 = std::ranges::find(v, 5);
    auto countedView = std::views::counted(pos5, 5);
    for (auto e : countedView) // outputs 5 6 7 8 9
    {
        std::cout << e << ' ';
    }
    std::cout << '\n';

    // You can pass the range directly if it supports input_or_output_iterator, in which case, the
    // count starts from the first element
    const char chars[] = { 'H','i',' ','t','h','e','r','e' };
    for (char c : std::views::counted(chars, 2))
    {
        std::cout << c; // outputs Hi
    }
}
5 6 7 8 9
Hi

operator PairLike

Преобразуйте тип subrange , который моделирует pair-like.

template<not-same-as<subrange> PairLike>
requires pair-like-convertible-from<PairLike, const I&, const S&>
constexpr operator PairLike() const;

Параметры

Нет.

Сведения о типах параметров шаблона см. в разделе "Параметры шаблона".

Возвращаемое значение

Значение PairLike , которое инициализировано напрямую с помощью хранимого итератора и sentinel. Последнее значение в паре будет sentinel.

Помните, что sentinel находится за последним элементом в подранге, как показано в приведенном ниже примере.

Замечания

Это преобразование полезно с более старым Boost::Ranges кодом, который принимает пары (первый, последний) для обозначения диапазона.
Это преобразование полезно для преобразования подранга в или pair tuple другой тип, который моделирует pair_like. Ниже приведены некоторые примеры pair_like типов:

std::array<T, 2>
std::pair<T, U>
std::ranges::subrange<I, S, K>
std::tuple<T, U>

Пример: operator PairLike()

// requires /std:c++20 or later
#include <iostream>
#include <ranges>
#include <vector>
#include <utility>

int main()
{
    constexpr int a[] = {0, 1, 2, 3, 4, 5};
    std::ranges::subrange rg(a);
    rg.advance(2);
    const std::pair<const int*, const int*> p = rg;
    for (auto e : rg)
    {
        std::cout << e << ' ';
    }

    // because the sentinel points after the last element, subtract one to get the last element
    std::cout << '\n' << *p.first << ':' << *(p.second - 1) << '\n'; // outputs 2:5
 }
2 3 4 5
2:5

advance

Настройте итератор для этого subrange по n элементам.

constexpr subrange& advance(const iter_difference_t<I> n);

Параметры

n
Сколько элементов для настройки итератора. n может быть положительным (перемещение вперед) или, если I это двунаправленный, отрицательный (перемещение назад).

Замечания

Эта функция изменяет текущее состояние итератора в .subrange

Если вы переходите к концу subrange, итератор устанавливается в sentinel в конце subrange.
Если вы перейдете к началу subrange (используя отрицательный n), вы получите недопустимое исключение параметров, если диапазон subrange , сделанный из, не имеет элемента в месте.

Пример: advance.

// requires /std:c++20 or later
#include <iostream>
#include <ranges>
#include <string>
#include <vector>

void print(const std::string &msg, auto &&v)
{
    std::cout << msg << '\n';
    for (auto& x : v)
    {
        std::cout << x << ' ';
    }
    std::cout << '\n';
}

int main()
{
    std::vector v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    print("Original vector: ", v); // outputs 0 1 2 3 4 5 6 7 8 9 10

    // create a subrange 3 4 5 6
    std::ranges::subrange theSubrange{ std::ranges::find(v,3), std::ranges::find(v, 7) };
    print("The subrange: ", theSubrange); // outputs 3 4 5 6

    auto sr = theSubrange.advance(2); // get a subrange 2 positions to the right of the current iterator location
    print("theSubrange.advance(2): ", sr); // outputs 5 6
    print("Note that subrange's iterator moved during advance(): ", sr); // outputs 5 6
    sr = theSubrange.advance(-3); // Moving before the subrange, but onto a valid element in the original range 
    print("theSubrange.advance(-3): ", sr); // outputs 2 3 4 5 6
}
Original vector:
0 1 2 3 4 5 6 7 8 9 10
The subrange:
3 4 5 6
theSubrange.advance(2):
5 6
Note that subrange's iterator moved during advance():
5 6
theSubrange.advance(-3):
2 3 4 5 6

begin

Получите итератор к первому элементу в элементе subrange.

1) constexpr I begin() const requires copyable<I>;
2) [[nodiscard]] constexpr I begin() requires (!std::copyable<I>);

Параметры

Нет.

Возвращаемое значение

Итератор, указывающий на первый элемент в элементе subrange. Если итератор не копируется, он возвращается с std::move(). При перемещении итератора состояние хранимого итератора зависит от реализации конструктора перемещения для I.

Изображение вектора с элементами 10, 20 и 30. Первый элемент содержит 10 и помечен как begin(). Последний элемент содержит 30 и помечен как последний элемент. Мнимый прямоугольник после последнего элемента указывает sentinel и обозначает конец().

empty

Проверьте, является ли пустой subrange .

constexpr bool empty() const;

Параметры

Нет.

Возвращаемое значение

Возвращает, true если subrange элементы отсутствуют. В противном случае возвращается false.

end

Получение sentinel в конце subrange

[[nodiscard]] constexpr S end() const;

Параметры

Нет.

Возвращаемое значение

Sentinel, следующий за последним элементом subrangeв :

Изображение вектора с элементами 10, 20 и 30. Первый элемент содержит 10 и помечен как begin(). Последний элемент содержит 30 и помечен как последний элемент. Мнимый прямоугольник после последнего элемента указывает sentinel и обозначает конец().

Sentinel создается копией из хранимого sentinel.

next

Создает копию этого subrange , но с хранимым итератором перемещается вперед указанное расстояние.

1) [[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) const & requires forward_iterator<I>;
2) [[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) &&;

Параметры

n
Сколько элементов для перемещения итератора вперед. По умолчанию равен 1. Должно быть положительным.

Возвращаемое значение

Возвращает копию начального subrange элемента *n*th.

Замечания

В отличие от advance()этого, next() не изменяет расположение итератора, хранящегося в исходном файле subrange. Возвращенный subrange элемент содержит все элементы, которые имеет исходный подранг, но итератор находится в другом расположении.

1) Возвращаемое значение совпадает с:

auto tmp = *this;
tmp.advance(n);
return tmp;

2) Возвращаемое значение совпадает с:

advance(n);
return std::move(*this);

Пример: next

// requires /std:c++20 or later
#include <iostream>
#include <ranges>
#include <string>
#include <vector>

void print(const std::string &msg, auto &&v)
{
    std::cout << msg << '\n';
    for (auto& x : v)
    {
        std::cout << x << ' ';
    }
    std::cout << '\n';
}

int main()
{
    std::vector v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    print("Original vector:", v); // 0 1 2 3 4 5 6 7 8 9 10

    // create a subrange from the front of v up to (but not including) the element 7
    std::ranges::subrange theSubrange{ std::ranges::find(v,1), std::ranges::find(v, 7) };
    print("The subrange:", theSubrange); // 1 2 3 4 5 6

    auto forward = theSubrange.advance(3); // get a subrange 3 positions to the right of the current iterator location
    print("theSubrange.advance(3):", forward); // 4 5 6

    // prev()
    auto previous = theSubrange.prev(2); // move back 2
    print("theSubrange.prev(2):", previous); // 2 3 4 5 6    
    print("Note that the subrange's iterator did *not* move during prev():", theSubrange); // 4 5 6
}
Original vector:
0 1 2 3 4 5 6 7 8 9 10
The subrange:
1 2 3 4 5 6
theSubrange.next(3):
4 5 6
Note that the original subrange's iterator did *not* move during next():
1 2 3 4 5 6

prev

Создает копию этого subrangeэлемента, но с сохраненным итератором перемещается обратно указанное расстояние.

[[nodiscard]] constexpr subrange prev(std::iter_difference_t<I> n = 1 ) const
    requires std::bidirectional_iterator<I>;

Параметры

n
Сколько элементов для перемещения итератора обратно. По умолчанию равен 1. Должно быть положительным.

Возвращаемое значение

Возвращает копию subrange элемента, но с итератором перемещены обратно n .

Замечания

В отличие от advance()этого, prev() не изменяет расположение итератора, хранящегося в исходном файле subrange.
Возвращенный subrange элемент содержит все элементы, которые имеет исходный подранг, но итератор находится только в другом расположении. Возвращаемое значение можно рассматривать следующим образом:

auto tmp = *this;
tmp.advance(-n);
return tmp;

Пример: prev.

// requires /std:c++20 or later
#include <iostream>
#include <ranges>
#include <string>
#include <vector>

void print(const std::string &msg, auto &&v)
{
    std::cout << msg << '\n';
    for (auto& x : v)
    {
        std::cout << x << ' ';
    }
    std::cout << '\n';
}

int main()
{
    std::vector v = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    print("Original vector:", v); // 0 1 2 3 4 5 6 7 8 9 10

    // create a subrange from the front of v up to (but not including) the element 7
    std::ranges::subrange theSubrange{std::ranges::find(v,1), std::ranges::find(v, 7)};
    print("The subrange: ", theSubrange); // 1 2 3 4 5 6

    auto forward = theSubrange.advance(3); // get a subrange 3 positions to the right of the current iterator location
    print("theSubrange.advance(3):", forward); // 4 5 6

    // prev()
    auto previous = theSubrange.prev(2); // move back 2
    print("theSubrange.prev(2):", previous); // 2 3 4 5 6    
    print("Note that the subrange's iterator did *not* move during prev():", theSubrange); // 4 5 6
}
Original vector:
0 1 2 3 4 5 6 7 8 9 10
The subrange:
1 2 3 4 5 6
theSubrange.advance(3):
4 5 6
theSubrange.prev(2):
2 3 4 5 6
Note that the subrange's iterator did *not* move during prev():
4 5 6

size

Получение количества элементов в элементе subrange.

constexpr size() const
    requires (K == ranges::subrange_kind::sized);

Параметры

Нет.

Возвращаемое значение

Число элементов в массиве subrange.

Если размер не хранится, то это происходит при subrange создании с K == ranges::subrange_kind::sized указанным и std::sized_sentinel_for<S, I> не удовлетворенным размером, то размер возвращается в качестве расстояния между начальным и конечным итераторами.

Изменение положения begin итератора, advanceнапример изменение размера сообщаемого размера.

См. также

<ranges>
counted
Просмотр классов