Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Uma vista é um intervalo leve que se refere a elementos que não lhe pertencem (exceto owning_view). Normalmente, uma vista baseia-se noutro intervalo e fornece uma forma diferente de o ver, quer o transforme quer filtre. Por exemplo, std::views::filter é um modo de exibição que usa os critérios especificados para selecionar elementos de outro intervalo.
Quando você acessa os elementos em uma exibição, isso é feito "preguiçosamente" para que o trabalho seja feito apenas quando você obtém um elemento. Isso torna possível combinar, ou compor, pontos de vista sem uma penalidade de desempenho.
Por exemplo, você pode criar um modo de exibição que forneça apenas os elementos pares de um intervalo e, em seguida, transformá-los em quadratura. O trabalho para fazer a filtragem e a transformação é feito apenas para os elementos que você acessa e somente quando você os acessa.
Uma vista pode ser copiada, atribuída e destruída em tempo constante, independentemente do número de elementos que contenha. Isso ocorre porque um modo de exibição não possui os elementos aos quais se refere, portanto, não precisa fazer uma cópia. É por isso que você pode compor visualizações sem uma penalidade de desempenho.
Normalmente, você cria uma exibição usando um adaptador de intervalo. Os adaptadores de intervalo são a maneira pretendida de criar uma exibição, são mais fáceis de usar do que instanciar as classes de exibição diretamente e, às vezes, são mais eficientes do que instanciar as classes de exibição diretamente. As classes de exibição são expostas diretamente caso você precise criar seu próprio tipo de exibição personalizado com base em um tipo de exibição existente.
Aqui está um breve exemplo de criação de uma visão dos quadrados dos elementos que são divisíveis por três em um vetor:
// requires /std:c++20 or later
#include <ranges>
#include <vector>
#include <iostream>
int main()
{
std::vector<int> input = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto divisible_by_three = [](const int n) {return n % 3 == 0;};
auto square = [](const int n) {return n * n;};
auto x = input
| std::views::filter(divisible_by_three)
| std::views::transform(square);
for (int i : x)
{
std::cout << i << ' '; // 0 9 36 81
}
}
0 9 36 81
Usar um modo de exibição depois que o intervalo no qual ele se baseia é modificado pode levar a um comportamento indefinido. Por exemplo, um reverse_view vetor baseado em um não deve ser reutilizado se você adicionar ou remover elementos do vetor subjacente. Modificar o vetor subjacente invalida o iterador do end contêiner - incluindo a cópia do iterador que a exibição pode ter feito.
Como os modos de exibição são baratos de criar, você geralmente deve recriar um modo de exibição se modificar o intervalo subjacente. O exemplo a seguir demonstra como armazenar um pipeline de exibição em uma variável para que você possa reutilizá-lo.
// requires /std:c++20 or later
#include <iostream>
#include <ranges>
#include <vector>
#include <list>
#include <string_view>
#include <algorithm>
template<typename rangeType>
void show(std::string_view msg, rangeType r)
{
std::cout << msg;
std::ranges::for_each(r,
[](auto e)
{
std::cout << e << ' ';
});
std::cout << '\n';
}
int main()
{
std::vector v{ 1, 2, 3, 4 };
show("v: ", v);
// You can save a view pipeline
auto rev3 = std::views::take(3) | std::views::reverse;
show("v | rev3: ", v | rev3); // 3 2 1
v.insert(v.begin(), 0); // v = 0 1 2 3 4
show("v: ", v);
// Because modifying the vector invalidates its iterators, rebuild the view.
// We are reusing the view pipeline we saved earlier
show("v | rev3(v): ", rev3(v));
}
v: 1 2 3 4
v | rev3: 3 2 1
v: 0 1 2 3 4
v | rev3(v): 2 1 0
As classes de exibição a std::ranges seguir são definidas no namespace.
| Visualizar | Descrição |
|---|---|
basic_istream_view
C++20 |
Uma visão de elementos sucessivos de um fluxo de entrada. As especializações incluem istream_view e wistream_view. |
common_view
C++20 |
Adapta uma exibição que tem diferentes tipos de iterador/sentinela em uma exibição com os mesmos tipos de iterador/sentinela. |
drop_view
C++20 |
Criado a partir de outra vista, ignorando os primeiros count elementos. |
drop_while_view
C++20 |
Criado a partir de outra exibição, ignorando elementos à esquerda desde que um predicado seja mantido. |
elements_view
C++20 |
Uma exibição sobre o índice selecionado em cada valor semelhante a uma tupla em uma coleção. Por exemplo, dado um intervalo de std::tuple<string, int> valores, crie uma exibição que consiste em todos os string elementos de cada tupla. |
empty_view
C++20 |
Uma vista sem elementos. |
filter_view
C++20 |
Filtra elementos de um intervalo que não correspondem a um predicado. |
iota_view
C++20 |
Uma exibição gerada que contém uma sequência de valores de incremento. |
join_view
C++20 |
Combina todos os elementos de vários intervalos em uma única visualização. |
keys_view
C++20 |
Uma exibição sobre o primeiro índice em cada valor semelhante a uma tupla em uma coleção. Por exemplo, dado um intervalo de std::tuple<string, int> valores, crie uma exibição que consiste nos string elementos de cada tupla. |
lazy_split_view
C++20 |
Divide uma exibição em subintervalos com base em um delimitador. |
owning_view
C++20 |
Assume a propriedade dos elementos de outro intervalo. |
ref_view
C++20 |
Um modo de exibição que faz referência aos elementos que pertencem a outro intervalo. |
reverse_view
C++20 |
Apresenta os elementos de um intervalo em ordem inversa. |
single_view
C++20 |
Um modo de exibição que contém apenas um elemento. |
split_view
C++20 |
Divide uma exibição em subintervalos com base em um delimitador. |
subrange
C++20 |
Uma visão de parte dos elementos de um intervalo, conforme definido por um iterador inicial e uma sentinela. |
take_view
C++20 |
Contém o número especificado de elementos retirados da frente de um intervalo. |
take_while_view
C++20 |
Contém os elementos principais de um intervalo que correspondem ao predicado dado. |
transform_view
C++20 |
Uma exibição de uma sequência subjacente após uma função de transformação é aplicada a cada elemento. |
values_view
C++20 |
Uma exibição sobre o segundo índice em cada valor semelhante a uma tupla em uma coleção. Por exemplo, dado um intervalo de std::tuple<string, int> valores, crie uma exibição que consiste nos int elementos de cada tupla. |
Muitas dessas classes têm adaptadores de intervalo correspondentes no std::views namespace que cria instâncias delas. Prefira usar um adaptador para criar um modo de exibição em vez de criar classes de exibição diretamente. Os adaptadores de gama são a forma pretendida de criar vistas, são mais fáceis de utilizar e, em alguns casos, são mais eficientes.
Ver características das classes
Cada tópico de classe de exibição tem uma seção Características após a seção de sintaxe. A seção Características tem as seguintes entradas:
Adaptador de intervalo: um link para o adaptador de intervalo que cria a exibição. Normalmente, você usa um adaptador de intervalo para criar um modo de exibição em vez de criar uma classe de exibição diretamente, por isso ele é listado aqui por conveniência.
Intervalo subjacente: as visualizações têm requisitos de iterador diferentes para o tipo de intervalo subjacente que podem usar. Consulte hierarquia de iteradores de intervalos para obter mais informações sobre os tipos de iteradores.
View iterator category: A categoria iterador da exibição. Quando um modo de exibição adapta um intervalo, o tipo de iterador para o modo de exibição é normalmente o mesmo que o tipo de iterador do intervalo subjacente. No entanto, pode ser diferente para alguns pontos de vista. Por exemplo,
reverse_viewtem umbidirectional_iterator, mesmo que o intervalo subjacente tenha umrandom_access_iterator.Tipo de elemento: o tipo dos elementos que o iterador da exibição retorna.
Dimensionado: se o modo de exibição pode retornar o número de elementos aos quais se refere. Nem todas as visualizações podem.
Intervalo comum: especifica se a exibição é um
common_range, o que significa que os tipos iterador inicial e sentinela são os mesmos. Intervalos comuns são úteis para código pré-intervalo que funciona com pares de iteradores. Um exemplo são construtores de par iterador para um contêiner de sequência, comovector(ranges::begin(x), ranges::end(x)).Intervalo emprestado: especifica se o modo de exibição é um intervalo emprestado.
borrowed_range<T>significa que você pode usar iteradores paraTdepois queTfor destruído.Nenhum contêiner padrão é um intervalo emprestado, porque destruir o contêiner libera os elementos e invalida quaisquer iteradores. Nesse caso, dizemos que os iteradores são deixados "pendurados" após a destruição.
Por exemplo,
std::ranges::find()normalmente retorna um iterador para o elemento encontrado no argumento range. Se o argumento range for um contêiner temporário (rvalue), é um erro armazenar o iterador retornado e usá-lo mais tarde porque ele está "pendurado".Os algoritmos de intervalo que retornam iteradores (ou subintervalos) o fazem somente quando seus argumentos são lvalues (não temporários) ou intervalos emprestados. Caso contrário, eles retornam um
std::danglingobjeto, que fornece uma dica em mensagens de erro sobre o que deu errado se você tentou usá-lo como um iterador.É
constiterável: indica se você pode iterar em umaconstinstância do modo de exibição. Nem todas asconstvisualizações podem ser iteradas. Se um modo de exibição nãoconstfor iterável, você não poderá iterá-lo oufor (const auto& element : as_const(theView))passá-lo para uma função que faça umaconstreferência ao modo de exibição e, em seguida, tente iterar sobre ele.
Hierarquia do iterador de intervalos
Na seção Características de cada tópico de classe de exibição, a categoria iterador em Intervalo subjacente e categoria de iterador de exibição refere-se ao tipo de iterador que o intervalo/exibição suporta. Existem seis categorias de iteradores de intervalos, que são identificados pelos conceitos C++20. A hierarquia dos iteradores de intervalo, em ordem crescente de capacidade, é:
| Conceito de iterador de alcance | Descrição |
|---|---|
output_range |
Somente gravação, só avança; Passagem única. |
input_range |
Somente leitura, só avança; Passagem única. |
forward_range |
Só avança; multi-passagem. |
bidirectional_range |
Pode avançar e retroceder; multi-passagem. |
random_access_range |
Pode aceder à coleção com um índice; multi-passagem. |
contiguous_range |
Pode acessar a coleção com um índice, e os elementos são armazenados contíguamente na memória. |
De um modo geral, um iterador tem a capacidade dos iteradores que o precedem na tabela. Por exemplo, bidirectional_range tem as capacidades de forward_range, mas não vice-versa. Exceto input_range, que não tem a capacidade de output_range porque você não pode escrever para um input_range.
A instrução "requer input_range ou superior" significa que a exibição pode ser usada com um input_range, forward_range, bidirectional_range, random_access_range, ou contiguous_range iterador, porque todos eles são tão capazes quanto input_range.
A hierarquia do iterador de intervalos está diretamente relacionada à hierarquia do iterador. Para obter mais informações, consulte Conceitos de iterador.