Compartilhar via


Classe subrange (Biblioteca Padrão C++)

Fornece uma exibição de parte dos elementos de um intervalo, conforme definido por um iterador e sentinela begin.

Sintaxe

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>>

Parâmetros de modelo

I
O tipo de iterador begin. O input_or_output_iterator conceito garante que I seja um iterador que pode ler todos os elementos.

K
O tipo de subintervalo: use subrange_kind::sized para especificar um subintervalo de tamanho. Use sized_sentinel_for<S, I> se o iterador e o sentinela puderem ser subtraídos para produzir o tamanho. O requisito subrange_kind::sized || !sized_sentinel_for<S, I> armazena o tamanho localmente no objeto de subintervalo e requer que você construa o subintervalo usando o construtor que usa um sized_range (para o qual você especificaria subrange_kind::sized aqui) ou por meio do construtor que usa um iterator, sentinele size (assim você especificaria sized_sentinel_for<S, I> aqui).

S
O tipo de iterador final. O sized_sentinel_for conceito garante que S pode ser usado como sentinela e I que é possível calcular a distância entre a sentinela e a posição atual do iterador em I tempo constante.

Ver características

Para obter uma descrição das entradas a seguir, consulte Exibir características da classe

Característica Descrição
Adaptador de gama views::counted
Intervalo subjacente Qualquer intervalo
Tipo de elemento iter_reference_t<I>
Exibir categoria do iterador O mesmo que Ia categoria s
Tamanho Se K for subrange::sized
É const-iterável Se I for copiável
Faixa comum Se I e S são do mesmo tipo.
Alcance emprestado Sim

Membros

Funções de membro Descrição
ConstrutoresC++20 Construa um subrange.
operator PairLikeC++20 Converta a em um tipo semelhante a subrange um par.
advanceC++20 Mova o iterador a uma distância especificada.
begin Obtenha um iterador para o primeiro elemento.
emptyC++20 Testar se o subrange está vazio.
endC++20 Obtenha o sentinela no final do subrangearquivo .
nextC++20 Cria uma cópia disso, subrange mas com o iterador armazenado movido para frente na distância especificada.
prevC++20 Cria uma cópia disso, subrange mas com o iterador armazenado movido para trás na distância especificada.
sizeC++20 Obtenha o número de elementos.
Herdado de view_interface Descrição
backC++20 Obtenha o último elemento.
dataC++20 Obtenha um ponteiro para o primeiro elemento.
frontC++20 Obtenha o primeiro elemento.
operator[]C++20 Obter o elemento na posição especificada.
operator boolC++20 Testar se o subrange está vazio.

Comentários

A subrange é útil quando você tem um iterador de início e fim, mas deseja passar um único objeto. Por exemplo, se você quisesse chamar um adaptador de intervalo, mas tivesse iteradores de início e término, poderia usar a subrange para encapsulá-los e passar o subrange para o adaptador de intervalo.

Requisitos

Cabeçalho: <ranges> (desde C++20)

Namespace: std::ranges

Opção do compilador: /std:c++20 ou posterior é necessária.

Construtores

Crie um 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)

Parâmetros

begin
Iterador que aponta para o primeiro elemento no subintervalo.

end
Sentinela que aponta para o final do subintervalo. O elemento para o qual ele aponta não está incluído no subintervalo.

sizeHint
O tamanho do intervalo em elementos. Isso é usado para otimizar a função de size membro e é necessário se você quiser fazer um tamanho subrange de um iterador e sentinela cujos tipos não modelam sized_sentinel_for.

Para obter informações sobre tipos de parâmetro de modelo, consulte Parâmetros de modelo.

Valor retornado

Uma instância de subrange.

Comentários

1) O padrão constrói o iterador e o sentinela armazenados. A dica de tamanho é definida como 0.
2) Usa std::move() para mover o iterador e end o begin sentinela para o iterador e o sentinela armazenados.
3) Inicializa o iterador armazenado com std::move(begin), o sentinela armazenado com std::move(end), e a dica de tamanho armazenado com size, que deve ser igual à distância entre o primeiro e o segundo argumentos.
4) Construa um subrange a partir de um intervalo.
5) O comportamento não é definido se szHint != ranges::distance(rg).

O counted adaptador de intervalo pode criar um subrangearquivo . Esse adaptador recebe um iterador begin e uma contagem.

Exemplo: 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

Converta a subrange em um tipo que modela pair-like.

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

Parâmetros

Nenhum.

Para obter informações sobre tipos de parâmetro de modelo, consulte Parâmetros de modelo.

Valor retornado

Um PairLike valor que é inicializado diretamente com o iterador e sentinela armazenados. O último valor no par será o sentinela.

Lembre-se de que a sentinela passou do último elemento da subfaixa, conforme mostrado no exemplo abaixo.

Comentários

Essa conversão é útil com código mais antigo Boost::Ranges que aceita (primeiro, último) pares para denotar um intervalo.
Essa conversão é útil para converter um subintervalo em um pair ou tuple outro tipo que modela pair_like. Alguns exemplos de pair_like tipos são:

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

Exemplo: 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

Ajuste o iterador para isso subrange por n elementos.

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

Parâmetros

n
Quantos elementos ajustar o iterador. n pode ser positivo (avançar) ou, se I for bidirecional, negativo (retroceder).

Comentários

Essa função modifica o estado atual do iterador no subrange.

Se você avançar além do final do subrange, o iterador será definido como o sentinela no final do subrange.
Se você avançar além do início do (usando um negativo n), obterá uma exceção de subrange parâmetro inválido se o intervalo do qual você fez o subrange não tiver um elemento no local.

Exemplo 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

Obtenha um iterador para o primeiro elemento no subrange.

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

Parâmetros

Nenhum.

Valor retornado

Um iterador que aponta para o primeiro elemento no subrange. Se o iterador não for copiável, ele será retornado com std::move(). Se o iterador for movido, o estado do iterador armazenado dependerá da implementação do construtor move para I.

Imagem de um vetor com os elementos 10, 20 e 30. O primeiro elemento contém 10 e é rotulado begin(). O último elemento contém 30 e é rotulado como 'último elemento'. Uma caixa imaginária após o último elemento indica o sentinela e é rotulada como end().

empty

Testar se o subrange está vazio.

constexpr bool empty() const;

Parâmetros

Nenhum.

Valor retornado

Retorna true se o não subrange tiver elementos. Caso contrário, retorna false.

end

Obtenha a sentinela no final do subrange

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

Parâmetros

Nenhum.

Valor retornado

A sentinela que segue o último elemento no subrange:

Imagem de um vetor com os elementos 10, 20 e 30. O primeiro elemento contém 10 e é rotulado begin(). O último elemento contém 30 e é rotulado como 'último elemento'. Uma caixa imaginária após o último elemento indica o sentinela e é rotulada como end().

A sentinela é copiada da sentinela armazenada.

next

Cria uma cópia disso, subrange mas com o iterador armazenado movido para frente na distância especificada.

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) &&;

Parâmetros

n
Quantos elementos mover o iterador para frente. O valor padrão é 1. Deve ser positivo.

Valor retornado

Retorna uma cópia do subrange elemento inicial no *n*th.

Comentários

Ao contrário advance()do , next() não altera o local do iterador armazenado no arquivo .subrange O retornado subrange tem todos os elementos que o subintervalo original tem, mas o iterador está em um local diferente.

1) O valor retornado é o mesmo que:

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

2) O valor retornado é o mesmo que:

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

Exemplo: 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

Cria uma cópia disso subrange, mas com o iterador armazenado movido para trás na distância especificada.

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

Parâmetros

n
Quantos elementos mover o iterador de volta. O valor padrão é 1. Deve ser positivo.

Valor retornado

Retorna uma cópia dos subrange elementos but com o iterador movido de volta n .

Comentários

Ao contrário advance()do , prev() não altera o local do iterador armazenado no arquivo .subrange
O retornado subrange tem todos os elementos que o subintervalo original tem, mas o iterador está apenas em um local diferente. Você pode pensar no valor de retorno como:

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

Exemplo 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

Obter o número de elementos no subrange.

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

Parâmetros

Nenhum.

Valor retornado

O número de elementos em subrange.

Se o tamanho não for armazenado, que é o caso quando o subrange é criado com K == ranges::subrange_kind::sized especificado e std::sized_sentinel_for<S, I> não é atendido, o tamanho será retornado como a distância entre os iteradores de início e fim.

Alterar a posição do begin iterador, com advance, por exemplo, altera o tamanho relatado.

Confira também

<ranges>
counted
Ver aulas