Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Os adaptadores de intervalo criam uma exibição (uma das classes View no namespace) a std::views
partir de um intervalo. Recomendamos que você use um adaptador para criar modos de exibição em vez de criar os tipos de exibição diretamente. Os adaptadores são a forma pretendida de aceder às vistas. Eles são mais fáceis de usar e, em alguns casos, mais eficientes do que criar instâncias dos tipos de exibição diretamente.
Um modo de exibição é um objeto leve que se refere a elementos de um intervalo. Uma vista pode:
- Consistem em apenas determinados elementos de um intervalo.
- Representar uma transformação de elementos de um intervalo.
- Seja o inverso ou apenas os primeiros
n
elementos de um intervalo. - Seja uma combinação das coisas anteriores.
Uma visão é barata, O(1)
copiar, atribuir e destruir, não importa quantos elementos estejam envolvidos. Considere o seguinte exemplo:
// 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
O primeiro adaptador de filter
intervalo, input
, fornece uma visão que contém os elementos que são divisíveis por três. O outro adaptador de gama, transform
, considera que contém os elementos divisíveis por três e fornece uma visão do quadrado desses elementos.
Quando um adaptador de intervalo produz uma visualização, ele não incorre no custo de transformar todos os elementos da faixa para produzir essa exibição. O custo para processar um elemento na exibição é pago somente quando você acessa esse elemento.
Criar uma vista é preparação para fazer trabalho no futuro. No exemplo anterior, a criação da exibição não resulta na localização de todos os elementos divisíveis por três ou na quadratura desses elementos. O trabalho acontece somente quando você acessa um elemento na exibição.
Os elementos de um modo de exibição geralmente são os elementos reais do intervalo usado para criar o modo de exibição. A exibição geralmente não possui os elementos; apenas se refere a eles, com exceção de owning_view
. Alterar um elemento altera esse elemento no intervalo a partir do qual o modo de exibição foi criado. O exemplo a seguir mostra esse comportamento:
#include <algorithm>
#include <iostream>
#include <ranges>
int main()
{
int input[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto even = [](const int n) { return n % 2 == 0; };
auto x = input | std::views::filter(even); // create a view of the even elements from input
for (int &i : x)
{
std::cout << i << ' '; // 0 2 4 6 8 10
}
std::cout << '\n';
std::ranges::fill(x, 42); // changes the evens from input[] to 42
for (int &i : input) // demonstrates that the even elements in the range are modified
{
std::cout << i << ' '; // // 42 1 42 3 42 5 42 7 42 9 42
}
}
Os adaptadores de gama apresentam-se de muitas formas. Por exemplo, existem adaptadores de intervalo que permitem produzir uma visualização por:
- Filtrando outro intervalo com base em um predicado (
filter
). - Transformando os elementos em um intervalo (
transform
). - Dividir um intervalo (
split
).
Os adaptadores de gama podem ser encadeados (compostos). É aí que o poder e a flexibilidade das gamas são mais evidentes. Os adaptadores de intervalo de composição permitem que você supere um problema central com os algoritmos STL (Standard Template Library) anteriores, que é que eles não são fáceis de encadear.
Os seguintes adaptadores de intervalo estão disponíveis no std::views
namespace. O std::views
namespace é um alias de conveniência para std::ranges::views
.
Adaptador de gama | Descrição |
---|---|
all
C++20 |
Crie um modo de exibição que se refira a um intervalo e seus elementos. |
common
C++20 |
Crie uma vista que tenha os mesmos tipos iterador e sentinela a partir de um intervalo que não tenha. |
counted
C++20 |
Crie uma exibição dos primeiros n elementos de um intervalo, começando pelo local especificado. |
drop
C++20 |
Crie uma vista a partir de outra vista, ignorando o número especificado de elementos da frente. |
drop_while
C++20 |
Crie um modo de exibição que contenha os elementos de um intervalo que permanecem depois que os elementos principais que correspondem à condição especificada são descartados. |
elements
C++20 |
Crie uma exibição do índice selecionado em cada valor semelhante a uma tupla em um intervalo. |
empty
C++20 |
Crie um modo de exibição que não tenha elementos. |
filter
C++20 |
Crie um modo de exibição que contenha os elementos de um intervalo que correspondam à condição especificada. |
iota
C++20 |
Crie um modo de exibição que contenha uma sequência de valores crescentes. |
istream
C++20 |
Crie uma exibição sobre os elementos de um fluxo. |
join
C++20 |
Crie um modo de exibição que combine todos os elementos de vários intervalos em um único modo de exibição. |
keys
C++20 |
Crie uma exibição do primeiro índice em cada valor semelhante a uma tupla em uma coleção. |
lazy_split
C++20 |
Divida uma vista em subintervalos com base num delimitador. |
reverse
C++20 |
Crie uma exibição dos elementos de um intervalo em ordem inversa. |
single
C++20 |
Crie um modo de exibição que contenha um elemento. |
split
C++20 |
Divida uma vista em subintervalos com base num delimitador. |
take
C++20 |
Crie uma vista dos primeiros n elementos a partir de outra vista. |
take_while
C++20 |
Crie um modo de exibição que contenha os elementos principais de um intervalo que correspondam à condição especificada. |
transform
C++20 |
Crie uma vista de elementos transformados a partir de outra vista. |
values
C++20 |
Crie uma exibição do segundo índice em cada valor semelhante a uma tupla em uma coleção. |
Na tabela anterior, um adaptador de intervalo é normalmente descrito como pegar um intervalo e produzir uma exibição. Para ser mais preciso, os adaptadores de intervalo têm um argumento de intervalo que aceita um dos seguintes:
- Os
cv-unqualified
modelosview
de tipo , e o argumento é um rvalue ou é copiável. - Quando você passa o argumento como um lvalue, ele deve modelar
range
e viver tanto quanto a exibição. - Quando você passa o argumento como um rvalue, como ao chamar
owning_view
, ele deve modelarrange
emovable
.
As funções do adaptador de intervalo são normalmente objetos de função, que se parecem com chamadas de função e impõem restrições aos tipos que podem ser passados.
Você pode passar adaptadores de intervalo e o resultado de operações de pipe (|
) para o código que espera objetos de função. No exemplo a seguir, a exibição que o split
adaptador de intervalo cria é passada para o transform
adaptador de intervalo como se fosse por uma chamada de função, porque o transform
adaptador de intervalo é um objeto de função.
std::map<int, string> x = {{0, "Hello, world"}, {42, "Goodbye, world"}};
auto y = x | views::values | views::transform(views::split(' '));
// y is a range whose elements are ranges of whitespace-delimited strings from each value in x:
// {{"Hello", "world"}, {"Goodbye", "world"}}
all
Crie uma exibição de todos os elementos em um intervalo.
template <ranges::viewable_range R>
constexpr ranges::view auto all(R&& rg) const noexcept;
Parâmetros
R
O tipo do intervalo subjacente.
rg
O intervalo a partir do qual criar a vista.
Valor de retorno
- Se
rg
já for uma vista, uma cópia dorg
. - Se
rg
é um valor de não-visualização, umref_view
que se refere arg
. (O tempo de vida da vista está ligado ao tempo de vida derg
.) - Se
rg
for um valor de não-visualização, como um objeto temporário, ou for o resultado da passagem do intervalo parastd::move
, umowning_view
.
Use std::views::all_t<decltype((rg))>
para obter o tipo do modo de exibição retornado.
Observações
Este adaptador de intervalo é a melhor maneira de converter um intervalo em uma exibição. Uma razão para criar uma visão a partir de um intervalo é passá-lo por valor a baixo custo, se passar o intervalo por valor pode ser caro.
Obter uma visualização para um intervalo é uma alternativa útil para passar um intervalo pesado por valor, porque as visualizações são baratas para criar, copiar e destruir. Uma possível exceção é owning_view
, que é uma exibição que possui o intervalo subjacente.
Em geral, o pior cenário para destruir uma exibição tem O(N)
complexidade para o número de elementos no intervalo. Mesmo que você destrua K
cópias de exibição com N
elementos, a complexidade total ainda O(N)
é porque o intervalo subjacente é destruído apenas uma vez.
Exemplo: all
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = {1,2,3,4,5,6,7,8,9,10};
auto myRefView = std::views::all(v); // create a ref_view of the vector
std::cout << myRefView.size() << '\n'; // 10
auto myOwningView = std::views::all(std::move(v)); // create an owning_view from a moved vector
std::cout << myRefView.size() << '\n'; // outputs 0 because myOwningView now owns the elements
std::cout << v.size() << '\n'; // outputs 0 because myOwningView now owns the elements
std::cout << myOwningView.size(); // 10
}
10
0
0
10
common
Crie um modo de exibição que tenha o mesmo iterador inicial e o mesmo tipo de sentinela a partir de um intervalo que talvez não tenha.
template <ranges::viewable_range R>
constexpr ranges::view auto common(R&& rg) const noexcept;
Parâmetros
R
O tipo do intervalo subjacente.
rg
O intervalo a partir do qual criar a vista.
Valor de retorno
-
views::all(rg)
ifrg
é um intervalo com o mesmo iterador e tipo sentinela. -
common_view(views::all(rg))
serg
tem diferentes tipos de iterador e sentinela.
Observações
Quando uma API exigir que o iterador inicial e o sentinela final tenham o mesmo tipo, e a exibição que você está usando não atender a esse requisito (ou você não sabe se atende), use esse adaptador de intervalo para criar um common_view
. Garante que o tipo de iterador inicial e o tipo de sentinela final são os mesmos.
Exemplo: common
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <numeric>
#include <list>
int main()
{
std::list<int> lst{1, 2, 3, 4, 5, 6, 7, 8, 9};
auto firstFive = std::views::take(lst, 5);
// firstFive.begin(), firstFive.end() have different types: counted_iterator versus default_sentinel
// auto r = std::accumulate(firstFive.begin(), firstFive.end(), 0); // Error: accumulate() requires firstFive.begin() and firstFive.end() types to be the same.
auto common = std::views::common(firstFive); // create a common_view that has the same begin/end iterator types
std::cout << std::accumulate(common.begin(), common.end(), 0); // Now you can call the API because the iterator types are the same. Outputs 15 (1+2+3+4+5)
}
15
counted
Crie uma exibição dos primeiros count
elementos de um intervalo, começando pelo local especificado.
template<class Iterator>
constexpr auto counted(Iterator&& it, iter_difference_t<Iterator> count);
Parâmetros
DifferenceType
O tipo da contagem.
Iterator
O tipo do iterador.
count
O número de elementos a serem incluídos no modo de exibição. Deve ser não-negativo.
- Se
count == 0
, um vaziospan
é retornado. - Se
count
for maior que o número de elementos no intervalo, o comportamento será indefinido.
it
Um iterador para o elemento no intervalo para começar. O elemento para o qual o iterador aponta é incluído na exibição criada.
Valor de retorno
A span
é retornado se it
for um contiguous_iterator
para matrizes, vetores e outros contêineres que armazenam seus elementos contíguos. Caso contrário, um subrange
é retornado.
Observações
Os elementos incluídos são [it, count)
.
Depois que o modo de exibição é criado, o número de elementos no modo de exibição permanece o mesmo, mesmo que o intervalo a partir do qual ele foi criado seja alterado. No entanto, se o intervalo subjacente mudar, acessar elementos da exibição pode resultar em comportamento indefinido.
Exemplo: counted
// requires /std:c++20 or later
#include <algorithm>
#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
drop
Crie um modo de exibição que exclua os primeiros n elementos de um intervalo.
1) template<ranges::viewable_range R>
constexpr ranges::view auto drop(R&& rg, ranges::range_difference_t<R> count);
2) template<class DifferenceType>
constexpr /* range closure object */ drop(DifferenceType&& count);
Parâmetros
DifferenceType
O tipo que descreve o número de elementos a serem ignorados.
count
O número de elementos a cair da frente do rg
. Deve ser não-negativo.
- Se
count == 0
, todos os elementos emrg
são retornados. - Se
count
for maior que o número de elementos norg
, uma exibição vazia será retornada.
R
O tipo do intervalo.
rg
O intervalo usado para criar o modo de exibição.
Valor de retorno
Uma visão do intervalo subjacente, com o número especificado de elementos descartados da frente.
Se você especificar mais elementos a serem descartados do que os existentes no intervalo subjacente, um empty_view
será retornado.
A exibição retornada é normalmente, mas nem sempre, uma especialização do drop_view
. Isso é:
- Se
V
é uma especialização deempty_view
, ou é uma especialização despan
,basic_string_view
,iota_view
, ousubrange
que é ambasrandom_access_range
esized_range
, o resultado é uma especialização deV
. - Caso contrário, o resultado é um
drop_view
.
Observações
Depois de criado, o número de elementos na vista permanece o mesmo, mesmo que a vista a partir da qual foi criada seja alterada. No entanto, se o modo de exibição subjacente for alterado, o acesso a elementos no modo de exibição retornado poderá resultar em um comportamento indefinido.
drop
é o oposto de take
.
O código mostrado anteriormente como "2)" pode ser usado com sintaxe pipe: collection | drop(5)
. Ou pode ser usado com sintaxe de chamada de função: drop(collection, 5)
ou drop(5)(collection)
.
Exemplo: drop
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v{1, 2, 3, 4, 5};
auto newView = std::views::drop(v, 3);
for (auto e : newView) // 4 5
{
std::cout << e << ' ';
}
std::cout << '\n';
auto numbers = std::views::iota(0) | std::views::take(10); // build a view of 10 integers
auto latterHalf = numbers | std::views::drop(5);
for (auto i : latterHalf)
{
std::cout << i << ' '; // 5 6 7 8 9
}
}
4 5
5 6 7 8 9
drop_while
Crie um modo de exibição que contenha os elementos de um intervalo que permanecem depois que os elementos principais que correspondem à condição especificada são descartados.
1) template<ranges::viewable_range R, class P>
constexpr ranges::view auto drop_while(R&& rg, P&& predicate);
2) template<class P>
constexpr /*range adaptor closure*/ drop_while(P&& predicate);
Parâmetros
R
O tipo do intervalo.
predicate
As condições que determinam quais elementos principais devem cair do intervalo.
rg
O intervalo subjacente a partir do qual criar a vista.
Valor de retorno
A drop_while_view
que consiste nos elementos que permanecem quando os elementos principais que correspondem ao predicado são descartados.
Observações
Para de soltar elementos assim que o predicado rg
retorna.false
drop_while
é o oposto de take_while
.
O código mostrado anteriormente como "2)" pode ser usado com sintaxe pipe: collection | drop_while(predicate)
. Ou pode ser usado com sintaxe de chamada de função: drop_while(collection, predicate)
ou drop_while(predicate)(collection)
.
Exemplo: drop_while
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
void print(auto&& v)
{
for (auto&& x : v)
{
std::cout << x << ' ';
}
std::cout << '\n';
}
int main()
{
std::vector<int> v{ 0, 1, 2, 3, -4, 5, 6 };
auto myView = std::views::drop_while(
v,
[](int i) {return i >= 0; });
print(myView); // -4 5 6
auto myView2 = v | std::views::drop_while(
[](int i) {return i < 5; });
print(myView2); // 5 6
}
-4 5 6
5 6
elements
Crie um elements_view
, que é uma exibição do índice selecionado em cada valor semelhante a uma tupla em um intervalo. Por exemplo, dado um intervalo de std::tuple<string, int>
valores, crie um elements_view
de todos os string
elementos de cada tupla.
template<ranges::viewable_range R, size_t N>
constexpr ranges::view auto elements<N>(R&& rg);
Parâmetros
N
O índice do elemento a ser selecionado de cada valor semelhante a uma tupla a ser incluído na exibição.
R
O tipo do intervalo subjacente.
rg
O intervalo de valores semelhantes a tuplas a partir do qual criar a exibição.
Valor de retorno
Um elements_view
que consiste no índice selecionado em cada valor semelhante a uma tupla em uma coleção.
Exemplo: elements
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <map>
#include <string>
int main()
{
std::map<std::string, int> cpp_standards
{
{"C++98", 1998},
{"C++03", 2003},
{"C++11", 2011},
{"C++14", 2014},
{"C++17", 2017},
{"C++20", 2020}
};
// Create an elements_view of all the string elements from each tuple
for (int const year : std::views::elements<1>(cpp_standards))
{
std::cout << year << ' '; // 2003 2011 2014 2017 1998 2020
}
std::cout << '\n';
// Another way, using |: create an elements_view of all the int elements from each tuple
for (auto&& name : cpp_standards | std::views::elements<0>)
{
std::cout << name << ' '; // C++03 C++11 C++14 C++17 C++98 c++20
}
}
2003 2011 2014 2017 1998 2020
C++03 C++11 C++14 C++17 C++98 c++20
empty
Crie um empty_view
, que é um modo de exibição que não tem elementos.
template<class T>
inline constexpr empty_view<T> empty{};
Parâmetros
T
O tipo dos elementos na exibição. A exibição precisa de um tipo de elemento, mesmo que não haja elementos.
Valor de retorno
Um empty_view
.
Observações
Um empty_view
pode ser útil quando você está chamando um código que requer uma exibição, mas não precisa processar nenhum de seus elementos.
Exemplo: empty
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
int main()
{
auto anEmptyView = std::views::empty<int>;
bool isNotEmpty = (bool)anEmptyView;
std::cout << boolalpha << isNotEmpty << "\n"; // false
}
false
filter
Crie um modo de exibição que contenha os elementos de um intervalo que correspondam à condição especificada.
1) template<ranges::viewable_range R, class P>
requires {filter_view(forward<R>(rg), forward<P>(predicate));}
constexpr ranges::view auto filter(R&& rg, P&& predicate);
2) template<class P>
constexpr /*range adaptor closure*/ filter(P&& predicate);
Parâmetros
P
O tipo do predicado.
predicate
As condições que determinam quais elementos manter no intervalo.
R
O tipo do intervalo subjacente.
rg
O intervalo a partir do qual criar a vista.
Valor de retorno
A filter_view
que contém os elementos de um intervalo que correspondem ao predicado.
Observações
Por uma questão de eficiência, quando utilizar filter
e transform
em conjunto com um tubo |
, faça o filter
primeiro para que apenas transform
os elementos que pretende manter.
O código mostrado anteriormente como "2)" pode ser usado com sintaxe pipe: collection | filter(predicate)
. Ou pode ser usado com sintaxe de chamada de função: filter(collection, predicate)
ou filter(predicate)(collection)
.
Exemplo: filter
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
void print(auto&& v)
{
for (auto&& x : v)
{
std::cout << x << ' ';
}
std::cout << '\n';
}
int main()
{
std::vector<int> v{0, 1, 2, 3, -4, 5, 6};
auto myView = std::views::filter(v, [](int i) {return i < 5; });
print(myView); // 0 1 2 3 -4
auto myView2 = v | std::views::filter([](int i) {return i < 5; }); // pipe syntax
print(myView2); // 0 1 2 3 -4
}
0 1 2 3 -4
0 1 2 3 -4
iota
Crie um modo de exibição que contenha uma sequência de valores crescentes. A sequência pode ser limitada ou não.
template<class V>
constexpr ranges::view auto iota(V&& startValue); // create an unbounded sequence of incrementing values
template<class V, class E>
constexpr ranges::view auto iota(V&& startValue, E&& endValue); // create a bounded sequence of incrementing values
Parâmetros
E
O tipo do valor final.
S
O tipo do valor inicial.
startValue
O primeiro valor na sequência.
endValue
Este valor é um passado o último valor que estará na sequência. Por exemplo, std::views::iota(0, 5)
gera uma exibição que tem os valores 0,1,2,3,4
.
Valor de retorno
Um iota_view
de uma sequência de valores crescentes.
Observações
Para uma sequência não limitada, o comportamento é indefinido depois que o valor máximo de seu tipo de dados é atingido.
Exemplo: iota
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
void print(auto&& v)
{
for (auto&& x : v)
{
std::cout << x << ' ';
}
std::cout << '\n';
}
int main()
{
// create an iota view with its range adaptor (preferred)
print(std::views::iota(0, 5)); // outputs 0 1 2 3 4
// create an iota_view class directly
std::ranges::iota_view letters{'a', 'f'};
print(letters); // a b c d e
}
0 1 2 3 4
a b c d e
istream
Crie uma exibição sobre os elementos de um fluxo.
template <class Val>
views::istream<Val>(str);
Parâmetros
str
Um objeto stream. Seu tipo é derivado de uma especialização de std::basic_istream
.
Val
O tipo de elementos a extrair do fluxo.
Valor de retorno
Este adaptador de intervalo é equivalente a ranges::basic_istream_view<Val, typename U::char_type, typename U::traits_type>(str)
, onde U
é o tipo de str
.
Exemplo: istream
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <sstream>
#include <vector>
int main()
{
std::istringstream doubles{"1.1 2.2 3.3 4.4 5.5"};
for (const auto& elem : std::views::istream<double>(doubles))
{
std::cout << elem << ' '; // 1.1 2.2 3.3 4.4 5.5
}
}
1.1 2.2 3.3 4.4 5.5
join
Crie um modo de exibição que combine todos os elementos de vários intervalos em um único modo de exibição.
1) template <ranges::viewable_range R>
[[nodiscard]] constexpr ranges::view auto join(R&& rg) const noexcept;
2) inline constexpr /*range adaptor closure*/ join();
Parâmetros
R
O tipo do intervalo subjacente.
rg
O intervalo a partir do qual criar a vista.
Valor de retorno
A join_view
que contém os elementos de todos os intervalos no intervalo subjacente.
Exemplo: join
#include <iostream>
#include <vector>
#include <ranges>
#include <string>
int main()
{
// a range of two ranges
std::vector<std::string> rangeOfRanges[2]{{"C++20", "contains:"}, {"ranges", "modules", "concepts & more."}};
for (const auto& elem : std::views::join(rangeOfRanges))
{
std::cout << elem << ' ';
}
}
C++20 contains: ranges modules concepts & more.
Observações
O código mostrado anteriormente como "2)" pode ser usado com sintaxe pipe: collection | join
. Ou pode ser usado com sintaxe de chamada de função: join(collection)
.
keys
Crie um keys_view
do primeiro índice em cada valor semelhante a uma tupla em uma coleção. Isso é útil para extrair chaves de contêineres associativos. Por exemplo, dado um intervalo de std::tuple<string, int>
, crie uma exibição que consiste em todos os string
elementos de cada tupla.
template <ranges::viewable_range R>
constexpr auto keys(R&& rg);
Parâmetros
R
O tipo do intervalo subjacente.
Valor de retorno
A keys_view
que consiste no primeiro índice em cada valor semelhante a uma tupla no intervalo.
Exemplo: keys
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <map>
#include <string>
#include <vector>
int main()
{
// ========== extract keys from a map
std::map<std::string, int> cpp_standards
{
{"C++98", 1998},
{"C++03", 2003},
{"C++11", 2011},
{"C++14", 2014},
{"C++17", 2017},
{"C++20", 2020}
};
// Extract all of the keys from the map
for (std::string standards : std::views::keys(cpp_standards))
{
std::cout << standards << ' '; // C++03 C++11 C++14 C++17 C++98 C++20
}
std::cout << '\n';
// ========== Extract keys from a pair
std::vector<std::pair<std::string, int>> windows
{
{"Windows 1.0", 1985},
{"Windows 2.0", 1987},
{"Windows 3.0", 1990},
{"Windows 3.1", 1992},
{"Windows NT 3.1", 1993},
{"Windows 95", 1995},
{"Windows NT 4.0", 1996},
{"Windows 95", 1995},
{"Windows 98", 1998},
{"Windows 1.0", 1985},
{"Windows 2000", 2000}
};
// Another way to call the range adaptor is by using '|'
for (std::string version : windows | std::views::keys)
{
std::cout << version << ' '; // Windows 1.0 Windows 2.0 Windows 3.0 ...
}
}
C++03 C++11 C++14 C++17 C++98 C++20
Windows 1.0 Windows 2.0 Windows 3.0 Windows 3.1 Windows NT 3.1 Windows 95 Windows NT 4.0 Windows 95 Windows 98 Windows 1.0 Windows 2000
lazy_split
Divida um intervalo em subintervalos com base em um delimitador. O delimitador pode ser um único elemento ou uma visão de elementos.
1) template<viewable_range R, class Pattern>
constexpr view auto lazy_split(R&& rg, Pattern&& delimiter);
2) template<class Pattern>
constexpr /*range adaptor closure*/ lazy_split(Pattern&& delimiter);
Parâmetros
delimiter
Um único valor ou uma sequência de valores que especifica onde dividir o intervalo.
Pattern
O tipo do delimitador.
R
O tipo de intervalo a dividir.
rg
O intervalo a dividir.
Valor de retorno
A lazy_split_view
que contém um ou mais subintervalos e é o resultado da divisão do intervalo original em delimiter
.
Observações
O delimitador não faz parte do resultado. Por exemplo, se você dividir o intervalo 1,2,3
no valor 2
, obterá dois subintervalos: 1
e 3
.
Um adaptador relacionado é split
. As principais diferenças entre split_view
e lazy_split_view
são:
Visualizar | Pode dividir um const intervalo |
Iterador de alcance |
---|---|---|
split_view |
Não | Suporta forward_range ou superior |
lazy_split_view |
Sim |
input_range ou superior |
Prefira split_view
porque é mais eficiente, a menos que você precise dividir um intervalo que seja const
.
O código mostrado anteriormente como "2)" pode ser usado com sintaxe pipe: collection | lazy_split(delimiter)
. Ou pode ser usado com sintaxe de chamada de função: lazy_split(collection, delimiter)
ou lazy_split(delimiter)(collection)
.
Exemplo: lazy_split
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> rg{1, 2, 3, 1, 2, 3, 4, 5, 6};
// split on a single element
for (const auto& sub : rg | std::views::split(3))
{
// outputs:
// 1 2
// 1 2
// 4 5 6
for (const auto& elem : sub)
{
std::cout << elem << ' ';
}
std::cout << '\n';
}
// split on a sequence of elements
int delimiters[] = {2, 3};
for (const auto& subrange : std::views::split(rg, delimiters))
{
// outputs 1 1 4 5 6
for (auto& i : subrange)
{
std::cout << i << " ";
}
}
}
1 2
1 2
4 5 6
1 1 4 5 6
reverse
Crie uma exibição dos elementos de um intervalo em ordem inversa.
1) template<viewable_range R>
constexpr ranges::view auto reverse(R&& rg);
2) inline constexpr /*range adaptor closure*/ reverse();
Parâmetros
R
O tipo de intervalo subjacente a reverter.
rg
O intervalo a inverter.
Valor de retorno
Uma vista que apresenta os elementos do intervalo subjacente em ordem inversa. A exibição retornada é normalmente, mas nem sempre, uma especialização do reverse_view
. Isso é:
- Se
V
for uma especialização dereverse_view
, o resultado é a visão subjacente do argumento. Um duplo reverso é um no-op (sem operação). - Se
V
tiver a formasubrange<reverse_iterator<I>, reverse_iterator<I>>
, o resultado é umsubrange
dos iteradores desempacotados. Um duplo reverso é um no-op. - Caso contrário, o resultado é um
reverse_view
.
Observações
O código mostrado anteriormente como "2)" pode ser usado com sintaxe pipe: collection | reverse
. Ou pode ser usado com sintaxe de chamada de função: reverse(collection)
.
Exemplo: reverse
// 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 };
auto rv = v | std::views::reverse; // using the pipe syntax
for (auto &&e : rv) // outputs 6 5 -4 3 2 1 0
{
std::cout << e << ' ';
}
std::cout << '\n';
// using the range adaptor without using the pipe syntax
auto rv2 = std::views::reverse(v);
for (auto &&e : rv2) // outputs 6 5 -4 3 2 1 0
{
std::cout << e << ' ';
}
}
6 5 -4 3 2 1 0
6 5 -4 3 2 1 0
single
Crie um single_view
, que é um modo de exibição que contém um elemento .
template<class T>
constexpr ranges::view auto single(T&& t);
Parâmetros
T
O tipo do elemento na exibição.
t
O valor do elemento a ser armazenado na exibição.
Valor de retorno
Um single_view
que contém t
.
Observações
Essa exibição é útil para fins de teste, para chamar o código que precisa ser fornecido com uma exibição que tenha pelo menos um elemento nele.
Exemplo: single
// requires /std:c++20 or later
#include <ranges>
#include <string>
#include <tuple>
#include <iostream>
int main()
{
auto sv = std::views::single(7);
std::cout << sv.front() << " " << *sv.data() << "\n"; // 7 7
auto sv2 = std::views::single(<std::tuple<double, std::string>{6502, "8-bit"});
std::cout << std::get<0>(sv2[0]) << " " << std::get<1>(sv2[0]) << "\n"; // 6502 8-bit
}
7 7
6502 8-bit
split
Divida uma vista em subintervalos com base num delimitador. O delimitador pode ser um único elemento ou uma sequência de elementos.
1) template<viewable_range R, class Pattern>
constexpr view auto split(R&& rg, Pattern&& delimiter);
2) template<class Pattern>
constexpr /*range adaptor closure*/ split(Pattern&& delimiter);
Parâmetros
delimiter
Um único valor ou uma sequência de valores que especifica onde dividir o intervalo.
Pattern
O tipo do delimitador.
R
O tipo do intervalo subjacente a dividir.
rg
O intervalo a dividir.
Valor de retorno
A split_view
que contém um ou mais subintervalos.
Observações
O delimitador não faz parte do resultado. Por exemplo, se você dividir o intervalo 1,2,3
no valor 2
, obterá dois subintervalos: 1
e 3
.
Um adaptador relacionado é lazy_split
. As principais diferenças entre split_view
e lazy_split_view
são:
Visualizar | Pode dividir um const intervalo |
Tipo de intervalo |
---|---|---|
split_view |
Não | Suporta forward_range ou superior |
lazy_split_view |
Sim | Suporta input_range ou superior |
Prefira split_view
porque é mais eficiente, a menos que você precise dividir um intervalo que seja const
.
O código mostrado anteriormente como "2)" pode ser usado com sintaxe pipe: collection | split(delimiter)
. Ou pode ser usado com sintaxe de chamada de função: split(collection, 5)
ou split(5)(collection)
.
Exemplo: split
// requires /std:c++20 or later
#include <ranges>
#include <vector>
#include <iostream>
int main()
{
std::vector<int> rg{ 1, 2, 3, 1, 2, 3, 4, 5, 6 };
// split on a single element, 3
for (const auto& sub : rg | std::views::split(3))
{
// This prints out:
// 1,2
// 4,5,6
for (const auto& elem : sub)
{
std::cout << elem << ' ';
}
std::cout << '\n';
}
// split on a sequence of elements, 2,3
int delimiters[] = {2, 3};
for (const auto& subrange : std::views::split(rg, delimiters))
{
// outputs 1 1 4 5 6
for (auto& i : subrange)
{
std::cout << i << " ";
}
}
}
1 2
1 2
4 5 6
1 1 4 5 6
take
Crie um modo de exibição que contenha o número especificado de elementos retirados da frente de um intervalo.
1) template<ranges::viewable_range R>
constexpr ranges::view auto take(R&& rg, ranges::range_difference_type<R> count);
2) template<class DifferenceType>
constexpr /*range adaptor closure*/ take(DifferenceType&& count);
Parâmetros
R
O tipo do intervalo subjacente.
rg
O intervalo a partir do qual criar a vista.
count
O número de elementos a serem retirados da frente do rg
.
Valor de retorno
A exibição retornada é normalmente, mas nem sempre, uma especialização do take_view
. Mais especificamente:
- Se
V
é uma especialização deempty_view
, ou é uma especialização despan
,basic_string_view
,iota_view
, ousubrange
que é ambasrandom_access_range
esized_range
, o resultado é uma especialização deV
. - Caso contrário, o resultado é um
take_view
.
Observações
Se você especificar mais elementos a serem tomados do que os existentes no rg
, todos os elementos serão usados.
take
é o oposto de drop
.
O código mostrado anteriormente como "2)" pode ser usado com sintaxe pipe: collection | take(5)
. Ou pode ser usado com sintaxe de chamada de função: take(5, collection)
ou take(5)(collection)
.
Exemplo: take
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string s{ "abcdefg" };
auto myView = std::views::take(s, 3);
for (auto c : myView)
{
std::cout << c << ' '; // a b c
}
std::cout << std::endl;
for (auto c : s | std::views::take(3)) // pipe syntax
{
std::cout << c << ' '; // a b c
}
}
a b c
a b c
take_while
Crie um modo de exibição que contenha os elementos principais de um intervalo que correspondam à condição especificada.
1) template<ranges::viewable_range R, class P>
constexpr ranges::view auto take_while(R&& rg, P&& predicate);
2) template<class P>
constexpr /*range adaptor closure*/ take_while(P&& predicate);
Parâmetros
P
O tipo do predicado.
predicate
As condições que determinam quais elementos principais copiar do intervalo.
R
O tipo do intervalo subjacente.
rg
O intervalo a partir do qual criar a vista.
Valor de retorno
A take_while_view
que consiste nos primeiros count
elementos que atendem aos critérios especificados no intervalo.
Observações
Para de tomar elementos de rg
depois que o predicado retorna false
ou o intervalo fica sem elementos.
take_while
é o oposto de drop_while
.
O código mostrado anteriormente como "2)" pode ser usado com sintaxe pipe: collection | take_while(pred)
. Ou pode ser usado com sintaxe de chamada de função: take_while(collection, pred)
ou take_while(pred)(collection)
.
Exemplo: take_while
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
void print(auto&& v)
{
for (auto&& x : v)
{
std::cout << x << ' ';
}
std::cout << '\n';
}
int main()
{
std::vector<int> v{ 0, 1, 2, 3, -4, 5, 6 };
auto myView = std::views::take_while(
v, [](int i) {return i >= 0; });
print(myView); // 0 1 2 3
print(v | std::views::take_while( // 0 1 2 3 -4
[](int i) {return i < 5; })); // pipe syntax
}
0 1 2 3
0 1 2 3 -4
transform
Crie uma exibição de elementos, cada um dos quais é uma transformação de um elemento no intervalo especificado.
1) template<viewable_range R, class F>
constexpr ranges::view auto transform(R&& rg, F&& fun);
2) template<class F>
constexpr /*range adaptor closure*/ transform(F&& fun);
Parâmetros
F
O tipo do objeto de função para transformar os elementos.
R
O tipo do intervalo subjacente.
fun
A função que transforma os elementos.
rg
O intervalo a partir do qual criar a vista.
Valor de retorno
A transform_view
que contém os elementos transformados de rg
.
Observações
Por uma questão de eficiência, quando compor filter
e transform
, faça o filter
primeiro para que você transform
apenas os elementos que você pretende manter.
O código mostrado anteriormente como "2)" pode ser usado com sintaxe pipe: collection | transform(fun)
. Ou pode ser usado com sintaxe de chamada de função: transform(collection, fun)
ou transform(fun)(collection)
.
Exemplo: transform
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>
void print(auto&& v)
{
for (auto&& x : v)
{
std::cout << x << ' ';
}
std::cout << '\n';
}
int main()
{
std::vector<int> v{0, 1, 2, 3, -4, 5, 6};
auto myView = std::views::transform(v, [](int i) {return i * 2; });
print(myView); // 0 2 4 6 -8 10 12
print(v | std::views::transform( // 0 2 4 6 -8 10 12
[](int i) {return i * 2; })); // pipe syntax
}
0 2 4 6 -8 10 12
0 2 4 6 -8 10 12
values
Crie um values_view
que consiste no segundo índice em cada valor semelhante a uma tupla em uma coleção. Isso é útil para fazer uma exibição dos valores em um contêiner associativo. Por exemplo, dado um intervalo de std::tuple<string, int>
valores, crie uma exibição que consiste em todos os int
elementos de cada tupla.
template <ranges::viewable_range R>
constexpr ranges::view auto values(R&& rg);
Parâmetros
R
O tipo do intervalo subjacente.
rg
O intervalo subjacente de valores semelhantes a tuplas.
Valor de retorno
Um values_view
construído a partir do segundo índice em cada valor semelhante a uma tupla no intervalo.
Exemplo: values
// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <map>
#include <string>
#include <vector>
int main()
{
// ========== working with a map
std::map<std::string, int> cpp_standards
{
{"C++98", 1998},
{"C++03", 2003},
{"C++11", 2011},
{"C++14", 2014},
{"C++17", 2017},
{"C++20", 2020}
};
// Extract all of the years from the map
for (int years : std::views::values(cpp_standards))
{
std::cout << years << ' '; // 2003 2011 2014 2017 1998 2020
}
std::cout << '\n';
// ========== working with pairs
std::vector<std::pair<std::string, int>> windows
{
{"Windows 1.0", 1985},
{"Windows 2.0", 1987},
{"Windows 3.0", 1990},
{"Windows 3.1", 1992},
{"Windows NT 3.1", 1993},
{"Windows 95", 1995},
{"Windows NT 4.0", 1996},
{"Windows 95", 1995},
{"Windows 98", 1998},
{"Windows 1.0", 1985},
{"Windows 2000", 2000}
};
// Another way to call the range adaptor by using '|'
// Create a values_view that contains the year from each pair
for (int years : windows | std::views::values)
{
std::cout << years << ' '; // 1985 1987 1990 1992 ...
}
}
2003 2011 2014 2017 1998 2020
1985 1987 1990 1992 1993 1995 1996 1995 1998 1985 2000
Aliases de tipo de adaptador de intervalo
all_t
Fornece o tipo de exibição que all
retorna.
template <ranges::viewable_range R>
using all_t = decltype(views::all(std::declval<R>()));
Parâmetros
R
O tipo do intervalo subjacente.
Valor de retorno
O tipo de exibição que all
retorna: decltype(views::all(std::declval<R>()))
.
Exemplo: all_t
#include <ranges>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = {1,2,3,4,5,6,7,8,9,10};
auto myView = std::views::all(v);
std::views::all_t<decltype((v))> &viewType = myView;
}