Adaptadores de intervalo
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 exibições em vez de criar os tipos de exibição diretamente. Os adaptadores são a maneira pretendida de acessar as exibições. 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.
Uma exibição é um objeto leve que se refere a elementos de um intervalo. Uma exibição pode:
- Consistem apenas em determinados elementos de um intervalo.
- Representam 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)
para 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 intervalo, filter
, fornece uma exibição que contém os elementos que input
são divisíveis por três. O outro adaptador de intervalo, transform
, usa a exibição que contém os elementos divisíveis por três e fornece uma exibição do quadrado desses elementos.
Quando um adaptador de intervalo produz uma exibição, ele não incorre no custo de transformar todos os elementos no intervalo para produzir essa exibição. O custo para processar um elemento na exibição é pago somente quando você acessa esse elemento.
Criar uma exibição é uma preparação para fazer o trabalho no futuro. No exemplo anterior, a criação da vista não resulta na localização de todos os elementos divisíveis por três ou na elevabilidade desses elementos. O trabalho acontece somente quando você acessa um elemento na exibição.
Os elementos de uma exibição geralmente são os elementos reais do intervalo usado para criar a exibição. A visualizaçã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 do qual a exibição foi criada. 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
}
}
Adaptadores de intervalo vêm em várias formas. Por exemplo, existem adaptadores de intervalo que permitem que você produza uma exibição:
- Filtrando outro intervalo com base em um predicado (
filter
). - Transformando os elementos em um intervalo (
transform
). - Dividindo um intervalo (
split
).
Os adaptadores de alcance podem ser encadeados (compostos). É aí que o poder e a flexibilidade dos intervalos são mais aparentes. A composição de adaptadores de intervalo permite 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 adaptadores de intervalo a seguir 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 uma exibição que se refira a um intervalo e seus elementos. |
common C++20 |
Crie uma exibição que tenha os mesmos tipos de iterador e sentinela 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 uma 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 uma vista que não tenha elementos. |
filter C++20 |
Crie uma exibição que contenha os elementos de um intervalo que correspondam à condição especificada. |
iota C++20 |
Crie uma 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 uma exibição que combine todos os elementos de vários intervalos em uma única exibição. |
keys C++20 |
Crie uma exibição do primeiro índice em cada valor semelhante a tupla em uma coleção. |
lazy_split C++20 |
Divida uma exibição em subintervalos com base em um delimitador. |
reverse C++20 |
Crie uma exibição dos elementos de um intervalo na ordem inversa. |
single C++20 |
Crie uma exibição que contenha um elemento. |
split C++20 |
Divida uma exibição em subintervalos com base em um delimitador. |
take C++20 |
Crie uma visualização dos primeiros n elementos de outra visualização. |
take_while C++20 |
Crie uma 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 tupla em uma coleção. |
Na tabela anterior, um adaptador de intervalo é normalmente descrito como pegando um intervalo e produzindo uma exibição. Para ser preciso, os adaptadores de intervalo têm um argumento de intervalo que aceita um dos seguintes:
- O
cv-unqualified
tipo modelaview
, 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 normalmente são objetos de função, que se parecem com chamadas de função e impõem restrições nos 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 adaptador de split
intervalo cria é passada para o transform
adaptador de intervalo como se fosse por uma chamada de função, pois o adaptador de transform
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 do qual criar a exibição.
Valor retornado
- Se
rg
já for uma exibição, uma cópia dorg
. - Se
rg
for um lvalue sem visualização, aref_view
que se refere arg
. (O tempo de vida da exibição está vinculado ao tempo de vida derg
.) - If
rg
é um rvalue que não é de exibição, como um objeto temporário, ou é o resultado da passagem do intervalo parastd::move
, umowning_view
.
Use std::views::all_t<decltype((rg))>
para obter o tipo da exibição retornada.
Comentários
Esse adaptador de intervalo é a melhor maneira de converter um intervalo em uma exibição. Um motivo para criar uma exibição de um intervalo é passá-la por valor a baixo custo, se passar o intervalo por valor puder ser caro.
Obter uma exibição para um intervalo é uma alternativa útil para passar um intervalo de peso pesado por valor porque as exibiçõ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 se você destruir K
cópias da 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 uma exibição que tenha o mesmo iterador inicial e tipo sentinela 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 do qual criar a exibição.
Valor retornado
views::all(rg)
ifrg
é um intervalo com o mesmo tipo de iterador e sentinela.common_view(views::all(rg))
ifrg
tem diferentes tipos de iterador e sentinela.
Comentários
Quando uma API exige que o iterador begin e o sentinel end tenham o mesmo tipo e a exibição que você está usando não atende a esse requisito (ou você não sabe se atende), use esse adaptador de intervalo para criar um common_view
. Ele garante que o tipo do iterador de início e o tipo do sentinela final sejam os mesmos.
Exemplo: common
// requires /std:c++20 or higher
#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 no 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 na exibição. Não deve ser 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 retornado
A span
é retornado se it
for a contiguous_iterator
para matrizes, vetores e outros contêineres que armazenam seus elementos de forma contígua. Caso contrário, a subrange
será retornado.
Comentários
Os elementos incluídos são [it, count)
.
Depois que a exibição é criada, o número de elementos na exibição permanece o mesmo, mesmo que o intervalo do qual ela foi criada seja alterado. No entanto, se o intervalo subjacente for alterado, o acesso a elementos da exibição poderá resultar em um 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 uma 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 serem descartados da frente do rg
. Não deve ser negativo.
- Se
count == 0
, todos os elementos emrg
são retornados. - Se
count
for maior que o número de elementos emrg
, uma exibição vazia será retornada.
R
O tipo do intervalo.
rg
O intervalo usado para criar a exibição.
Valor retornado
Uma exibição do intervalo subjacente, com o número especificado de elementos descartados da frente.
Se você especificar mais elementos a serem descartados do que existem no intervalo subjacente, an empty_view
será retornado.
A exibição retornada é normalmente, mas nem sempre, uma especialização de drop_view
. Ou seja:
- Se
V
é uma especialização deempty_view
, ou é uma especialização despan
,basic_string_view
,iota_view
, ousubrange
que é ambosrandom_access_range
esized_range
, o resultado é uma especialização deV
. - Caso contrário, o resultado será
drop_view
.
Comentários
Depois de criado, o número de elementos na exibição permanece o mesmo, mesmo que a exibição da qual ele foi criado seja alterada. No entanto, se a exibição subjacente for alterada, o acesso a elementos na exibição retornada poderá resultar em um comportamento indefinido.
drop
é o oposto de take
.
O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de 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 uma 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 ser descartados do intervalo.
rg
O intervalo subjacente do qual criar a exibição.
Valor retornado
A drop_while_view
que consiste nos elementos que permanecem quando os elementos principais que correspondem ao predicado são descartados.
Comentários
Interrompe o descarte de rg
elementos assim que o predicado retorna false
.
drop_while
é o oposto de take_while
.
O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de 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 para criar a exibição.
Valor retornado
Um elements_view
que consiste no índice selecionado em cada valor semelhante a 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 é uma 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 retornado
Um empty_view
.
Comentários
An 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 higher
#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 uma 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 do qual criar a exibição.
Valor retornado
A filter_view
que contém os elementos de um intervalo que correspondem ao predicado.
Comentários
Por uma questão de eficiência, quando você usar filter
e transform
junto com um tubo |
, faça o filter
primeiro para que você transform
apenas os elementos que pretende manter.
O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de 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 uma 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
Esse valor é um após 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 retornado
Um iota_view
de uma sequência de valores crescentes.
Comentários
Para uma sequência não associada, 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 de fluxo. Seu tipo é derivado de uma especialização de std::basic_istream
.
Val
O tipo dos elementos a serem extraídos do fluxo.
Valor retornado
Uma basic_istream_view
.
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 uma exibição que combine todos os elementos de vários intervalos em uma única 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 do qual criar a exibição.
Valor retornado
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.
Comentários
O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de pipe: collection | join
. Ou pode ser usado com a sintaxe de chamada de função: join(collection)
.
keys
Crie um keys_view
do primeiro índice em cada valor semelhante a 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 retornado
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 visualizaçã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 especificam onde dividir o intervalo.
Pattern
O tipo do delimitador.
R
O tipo do intervalo a ser dividido.
rg
O intervalo a ser dividido.
Valor retornado
A lazy_split_view
que contém um ou mais subintervalos e é o resultado da divisão do intervalo original em delimiter
.
Comentários
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](split-view-class.md) and
lazy_split_view' são:
Exibir | Pode dividir um const intervalo |
Iterador de intervalo |
---|---|---|
split_view |
não | Suportes 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 a sintaxe de 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 na 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 do intervalo subjacente a ser revertido.
rg
O intervalo a ser revertido.
Valor retornado
Uma exibição que apresenta os elementos do intervalo subjacente em ordem inversa. A exibição retornada é normalmente, mas nem sempre, uma especialização de reverse_view
. Ou seja:
- Se
V
é uma especialização dereverse_view
, o resultado é a visão subjacente do argumento. Um reverso duplo é um no-op (sem operação). - Se
V
tiver o formuláriosubrange<reverse_iterator<I>, reverse_iterator<I>>
, o resultado é umsubrange
dos iteradores desencapsulados. Um duplo reverso é um no-op. - Caso contrário, o resultado será
reverse_view
.
Comentários
O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de pipe: collection | reverse
. Ou pode ser usado com a 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 é uma 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 retornado
Um single_view
que contém t
.
Comentários
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.
Exemplo: single
// requires /std:c++20 or higher
#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 exibição em subintervalos com base em um 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 especificam onde dividir o intervalo.
Pattern
O tipo do delimitador.
R
O tipo do intervalo subjacente a ser dividido.
rg
O intervalo a ser dividido.
Valor retornado
A split_view
que contém um ou mais subintervalos.
Comentários
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:
Exibir | Pode dividir um const intervalo |
Tipo de intervalo |
---|---|---|
split_view |
não | Suportes forward_range ou superior |
lazy_split_view |
sim | Suportes 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 a sintaxe de 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 uma 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 do qual criar a exibição.
count
O número de elementos a serem retirados da frente do rg
.
Valor retornado
A exibição retornada é normalmente, mas nem sempre, uma especialização de take_view
. Especificamente:
- Se
V
é uma especialização deempty_view
, ou é uma especialização despan
,basic_string_view
,iota_view
, ousubrange
que é ambosrandom_access_range
esized_range
, o resultado é uma especialização deV
. - Caso contrário, o resultado será
take_view
.
Comentários
Se você especificar mais elementos a serem obtidos do que existem no rg
, todos os elementos serão obtidos.
take
é o oposto de drop
.
O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de 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 uma 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 do qual criar a exibição.
Valor retornado
A take_while_view
que consiste nos primeiros count
elementos que atendem aos critérios especificados no intervalo.
Comentários
Interrompe a obtenção de rg
elementos 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 a sintaxe de 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 do qual criar a exibição.
Valor retornado
A transform_view
que contém os elementos transformados de rg
.
Comentários
Por uma questão de eficiência, quando você compõe filter
e transform
, faça o filter
primeiro para que você transform
apenas os elementos que pretende manter.
O código mostrado anteriormente como "2)" pode ser usado com a sintaxe de 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 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 consista em todos os int
elementos de cada tupla.
template <range::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 retornado
A 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 do tipo 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 retornado
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;
}